├── .gitignore
├── 00 - 注册登录
├── README.md
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── spring4all
│ │ ├── Application.java
│ │ ├── config
│ │ └── WebSecurityConfig.java
│ │ └── controller
│ │ ├── HomeController.java
│ │ └── UserController.java
│ └── resources
│ ├── application.yml
│ └── templates
│ ├── header.html
│ ├── index.html
│ ├── login.html
│ └── user
│ └── user.html
├── 00 - 注册登录(数据库)
├── README.md
├── pom.xml
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── spring4all
│ │ │ ├── Application.java
│ │ │ ├── config
│ │ │ ├── DbUserDetailsService.java
│ │ │ └── WebSecurityConfig.java
│ │ │ ├── controller
│ │ │ ├── HomeController.java
│ │ │ └── UserController.java
│ │ │ ├── entity
│ │ │ └── UserDO.java
│ │ │ ├── repository
│ │ │ └── UserRepository.java
│ │ │ └── service
│ │ │ ├── UserService.java
│ │ │ └── impl
│ │ │ └── BaseUserService.java
│ │ └── resources
│ │ ├── application.yml
│ │ └── templates
│ │ ├── header.html
│ │ ├── index.html
│ │ ├── login.html
│ │ ├── register.html
│ │ └── user
│ │ └── user.html
└── user.sql
├── 01 - 密码加密(数据库)
├── README.md
├── pom.xml
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── spring4all
│ │ │ ├── Application.java
│ │ │ ├── config
│ │ │ ├── DbUserDetailsService.java
│ │ │ └── WebSecurityConfig.java
│ │ │ ├── controller
│ │ │ ├── HomeController.java
│ │ │ └── UserController.java
│ │ │ ├── entity
│ │ │ └── UserDO.java
│ │ │ ├── repository
│ │ │ └── UserRepository.java
│ │ │ └── service
│ │ │ ├── UserService.java
│ │ │ └── impl
│ │ │ └── BaseUserService.java
│ │ └── resources
│ │ ├── application.yml
│ │ └── templates
│ │ ├── header.html
│ │ ├── index.html
│ │ ├── login.html
│ │ ├── register.html
│ │ └── user
│ │ └── user.html
└── user.sql
├── 02 - 自定义登录
├── README.md
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── spring4all
│ │ ├── Application.java
│ │ ├── config
│ │ ├── CustomFromLoginFilter.java
│ │ └── WebSecurityConfig.java
│ │ └── controller
│ │ ├── HomeController.java
│ │ └── UserController.java
│ └── resources
│ ├── application.yml
│ └── templates
│ ├── header.html
│ ├── index.html
│ ├── login.html
│ └── user
│ └── user.html
├── 03 - 前后端分离(JSON交互)
├── README.md
├── pom.xml
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── spring4all
│ │ │ ├── Application.java
│ │ │ ├── bean
│ │ │ └── WebResponse.java
│ │ │ ├── config
│ │ │ ├── CustomAccessDeniedHandler.java
│ │ │ ├── CustomAuthenticationEntryPoint.java
│ │ │ ├── CustomAuthenticationFailureHandler.java
│ │ │ ├── CustomAuthenticationSuccessHandler.java
│ │ │ ├── CustomJSONLoginFilter.java
│ │ │ ├── CustomLogoutSuccessHandler.java
│ │ │ └── WebSecurityConfig.java
│ │ │ ├── constant
│ │ │ ├── CommonResponse.java
│ │ │ └── HttpResponseStatusEnum.java
│ │ │ ├── controller
│ │ │ ├── HomeController.java
│ │ │ └── UserController.java
│ │ │ ├── entity
│ │ │ └── UserDO.java
│ │ │ ├── repository
│ │ │ └── UserRepository.java
│ │ │ └── service
│ │ │ ├── UserService.java
│ │ │ └── impl
│ │ │ └── BaseUserService.java
│ │ └── resources
│ │ └── application.yml
└── user.sql
├── 04 - Basic 认证
├── README.md
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── com
│ │ └── spring4all
│ │ ├── Application.java
│ │ ├── config
│ │ └── WebSecurityConfig.java
│ │ └── controller
│ │ ├── HomeController.java
│ │ └── UserController.java
│ └── resources
│ ├── application.yml
│ └── templates
│ ├── header.html
│ ├── index.html
│ ├── login.html
│ └── user
│ └── user.html
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
3 | */target/*
4 |
5 | *.iml
6 |
--------------------------------------------------------------------------------
/00 - 注册登录/README.md:
--------------------------------------------------------------------------------
1 | ## 使用手册
2 |
3 | 1、执行 `mvn spring-boot:run`
4 |
5 | 2、访问 http://localhost:8080/
6 |
7 | 3、点击 `登录`
8 |
9 | > 账号:anoyi
10 | > 密码:anoyi
--------------------------------------------------------------------------------
/00 - 注册登录/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.anoyi
8 | security-login-no-db
9 | 1.0-SNAPSHOT
10 |
11 | Spring Security 基础 DEMO (无数据库版)- 更多内容访问 https://anoyi.com
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.1.3.RELEASE
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-thymeleaf
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-security
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-maven-plugin
41 |
42 |
43 |
44 | repackage
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/java/com/spring4all/Application.java:
--------------------------------------------------------------------------------
1 | package com.spring4all;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(Application.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/java/com/spring4all/config/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
7 | import org.springframework.security.core.userdetails.User;
8 | import org.springframework.security.core.userdetails.UserDetailsService;
9 | import org.springframework.security.provisioning.InMemoryUserDetailsManager;
10 |
11 | @EnableWebSecurity
12 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
13 |
14 | /**
15 | * 匹配 "/" 路径,不需要权限即可访问
16 | * 匹配 "/user" 及其以下所有路径,都需要 "USER" 权限
17 | * 登录地址为 "/login",登录成功默认跳转到页面 "/user"
18 | * 退出登录的地址为 "/logout",退出成功后跳转到页面 "/login"
19 | * 默认启用 CSRF
20 | */
21 | @Override
22 | protected void configure(HttpSecurity http) throws Exception {
23 | http
24 | .authorizeRequests()
25 | .antMatchers("/").permitAll()
26 | .antMatchers("/user/**").hasRole("USER")
27 | .and()
28 | .formLogin().loginPage("/login").defaultSuccessUrl("/user")
29 | .and()
30 | .logout().logoutUrl("/logout").logoutSuccessUrl("/login");
31 | }
32 |
33 | /**
34 | * 在内存中创建一个名为 "user" 的用户,密码为 "pwd",拥有 "USER" 权限
35 | */
36 | @Bean
37 | @Override
38 | protected UserDetailsService userDetailsService() {
39 | User.UserBuilder users = User.withDefaultPasswordEncoder();
40 | InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
41 | manager.createUser(users.username("anoyi").password("anoyi").roles("USER").build());
42 | return manager;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/java/com/spring4all/controller/HomeController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 |
6 | @Controller
7 | public class HomeController {
8 |
9 | @GetMapping({"/", "/index", "/home"})
10 | public String root(){
11 | return "index";
12 | }
13 |
14 | @GetMapping("/login")
15 | public String login(){
16 | return "login";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/java/com/spring4all/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import org.springframework.security.core.annotation.AuthenticationPrincipal;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 |
8 | import java.security.Principal;
9 |
10 | @Controller
11 | public class UserController {
12 |
13 | @GetMapping("/user")
14 | public String user(@AuthenticationPrincipal Principal principal, Model model){
15 | model.addAttribute("username", principal.getName());
16 | return "user/user";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | thymeleaf:
6 | cache: false
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/resources/templates/header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Spring Security
16 |
Spring Security 是一个功能强大且可高度自定义的身份验证和访问控制框架,它是保护基于 Spring 的应用的最佳实践,与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求。
17 |
官方文档 »
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
Github
26 |
Spring Security 源码
27 |
查看详情 »
28 |
29 |
30 |
Stackoverflow
31 |
Spring Security 相关问题答疑
32 |
查看详情 »
33 |
34 |
35 |
Micro
36 |
Spring Security 在微服务架构下的实践
37 |
查看详情 »
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/resources/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 登录 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Login
20 |
21 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/00 - 注册登录/src/main/resources/templates/user/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 用户中心 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |

17 |
Anoyi
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/README.md:
--------------------------------------------------------------------------------
1 | ## 使用手册
2 |
3 | 1、创建数据库
4 | ```
5 | create database `security00` default character set utf8mb4 collate utf8mb4_general_ci;
6 | ```
7 |
8 | 2、执行 `user.sql`
9 |
10 | 3、执行 `mvn spring-boot:run`
11 |
12 | 4、注册账号 http://localhost:8080/register
13 |
14 | 5、登录 http://localhost:8080/login
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.anoyi
8 | security-login-db
9 | 1.0-SNAPSHOT
10 |
11 | Spring Security 基础 DEMO (数据库版)- 更多内容访问 https://anoyi.com
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.1.3.RELEASE
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-thymeleaf
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-security
33 |
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-data-jpa
38 |
39 |
40 |
41 | org.projectlombok
42 | lombok
43 | 1.16.16
44 |
45 |
46 |
47 | org.mariadb.jdbc
48 | mariadb-java-client
49 | 2.0.2
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-maven-plugin
59 |
60 |
61 |
62 | repackage
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | spring-milestones
73 | Spring Milestones
74 | https://repo.spring.io/libs-milestone
75 |
76 | false
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/Application.java:
--------------------------------------------------------------------------------
1 | package com.spring4all;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(Application.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/config/DbUserDetailsService.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import com.spring4all.service.UserService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
7 | import org.springframework.security.core.userdetails.UserDetails;
8 | import org.springframework.security.core.userdetails.UserDetailsService;
9 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
10 | import org.springframework.stereotype.Service;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | @Service
16 | public class DbUserDetailsService implements UserDetailsService {
17 |
18 | private final UserService userService;
19 |
20 | @Autowired
21 | DbUserDetailsService(UserService userService){
22 | this.userService = userService;
23 | }
24 |
25 | @Override
26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
27 | UserDO userDO = userService.getByUsername(username);
28 | if (userDO == null){
29 | throw new UsernameNotFoundException("用户不存在!");
30 | }
31 | List simpleGrantedAuthorities = new ArrayList<>();
32 | simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
33 | return new org.springframework.security.core.userdetails.User(userDO.getUsername(), userDO.getPassword(), simpleGrantedAuthorities);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/config/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
9 | import org.springframework.security.crypto.password.NoOpPasswordEncoder;
10 | import org.springframework.security.crypto.password.PasswordEncoder;
11 |
12 | @EnableWebSecurity
13 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
14 |
15 | private DbUserDetailsService dbUserDetailsService;
16 |
17 | @Autowired
18 | public void setAnyUserDetailsService(DbUserDetailsService dbUserDetailsService){
19 | this.dbUserDetailsService = dbUserDetailsService;
20 | }
21 |
22 | /**
23 | * 匹配 "/" 路径,不需要权限即可访问
24 | * 匹配 "/user" 及其以下所有路径,都需要 "USER" 权限
25 | * 登录地址为 "/login",登录成功默认跳转到页面 "/user"
26 | * 退出登录的地址为 "/logout",退出成功后跳转到页面 "/login"
27 | * 默认启用 CSRF
28 | */
29 | @Override
30 | protected void configure(HttpSecurity http) throws Exception {
31 | http
32 | .authorizeRequests()
33 | .antMatchers("/").permitAll()
34 | .antMatchers("/user/**").hasAuthority("USER")
35 | .and()
36 | .formLogin().loginPage("/login").defaultSuccessUrl("/user")
37 | .and()
38 | .logout().logoutUrl("/logout").logoutSuccessUrl("/login");
39 | }
40 |
41 | /**
42 | * 添加 UserDetailsService, 实现自定义登录校验
43 | */
44 | @Override
45 | protected void configure(AuthenticationManagerBuilder builder) throws Exception{
46 | builder.userDetailsService(dbUserDetailsService);
47 | }
48 |
49 | @Bean
50 | public static PasswordEncoder passwordEncoder() {
51 | return NoOpPasswordEncoder.getInstance();
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/controller/HomeController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import com.spring4all.service.UserService;
5 | import lombok.AllArgsConstructor;
6 | import org.springframework.stereotype.Controller;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.PostMapping;
9 |
10 | @Controller
11 | @AllArgsConstructor
12 | public class HomeController {
13 |
14 | private final UserService userService;
15 |
16 | @GetMapping({"/", "/index", "/home"})
17 | public String root(){
18 | return "index";
19 | }
20 |
21 | @GetMapping("/login")
22 | public String login(){
23 | return "login";
24 | }
25 |
26 | @GetMapping("/register")
27 | public String register(){
28 | return "register";
29 | }
30 |
31 | @PostMapping("/register")
32 | public String doRegister(UserDO userDO){
33 | // 此处省略校验逻辑
34 | userService.insert(userDO);
35 | return "redirect:register?success";
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import org.springframework.security.core.annotation.AuthenticationPrincipal;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 |
8 | import java.security.Principal;
9 |
10 | @Controller
11 | public class UserController {
12 |
13 | @GetMapping("/user")
14 | public String user(@AuthenticationPrincipal Principal principal, Model model){
15 | model.addAttribute("username", principal.getName());
16 | return "user/user";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/entity/UserDO.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.entity;
2 |
3 | import lombok.Data;
4 |
5 | import javax.persistence.*;
6 |
7 | @Entity
8 | @Table(name = "user")
9 | @Data
10 | public class UserDO {
11 |
12 | @Id
13 | @GeneratedValue(strategy = GenerationType.AUTO)
14 | private Long id;
15 |
16 | /**
17 | * 账号
18 | */
19 | private String username;
20 |
21 | /**
22 | * 密码
23 | */
24 | private String password;
25 |
26 | /**
27 | * 昵称
28 | */
29 | private String nickname;
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.repository;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import org.springframework.data.repository.CrudRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface UserRepository extends CrudRepository {
9 |
10 | UserDO findByUsername(String username);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.service;
2 |
3 | import com.spring4all.entity.UserDO;
4 |
5 | public interface UserService {
6 |
7 | /**
8 | * 添加新用户
9 | *
10 | * username 唯一, 默认 USER 权限
11 | */
12 | void insert(UserDO userDO);
13 |
14 | /**
15 | * 查询用户信息
16 | * @param username 账号
17 | * @return UserEntity
18 | */
19 | UserDO getByUsername(String username);
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/java/com/spring4all/service/impl/BaseUserService.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.service.impl;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import com.spring4all.repository.UserRepository;
5 | import com.spring4all.service.UserService;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.context.annotation.Primary;
8 | import org.springframework.stereotype.Service;
9 |
10 | @Service
11 | @Primary
12 | @Slf4j
13 | public class BaseUserService implements UserService {
14 |
15 | private final UserRepository userRepository;
16 |
17 | public BaseUserService(UserRepository userRepository){
18 | this.userRepository = userRepository;
19 | }
20 |
21 | @Override
22 | public void insert(UserDO userDO) {
23 | String username = userDO.getUsername();
24 | if (exist(username)){
25 | throw new RuntimeException("用户名已存在!");
26 | }
27 | userRepository.save(userDO);
28 | }
29 |
30 | @Override
31 | public UserDO getByUsername(String username) {
32 | return userRepository.findByUsername(username);
33 | }
34 |
35 | /**
36 | * 判断用户是否存在
37 | */
38 | private boolean exist(String username){
39 | UserDO userDO = userRepository.findByUsername(username);
40 | return (userDO != null);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | thymeleaf:
6 | cache: false
7 | datasource:
8 | url: jdbc:mysql://localhost:3306/security00?useUnicode=true&characterEncoding=utf8mb4
9 | driver-class-name: org.mariadb.jdbc.Driver
10 | username: root
11 | password: Passw0rd
12 | jpa:
13 | hibernate:
14 | ddl-auto: update
15 | database-platform: org.hibernate.dialect.MySQL5Dialect
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/resources/templates/header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Spring Security
16 |
Spring Security 是一个功能强大且可高度自定义的身份验证和访问控制框架,它是保护基于 Spring 的应用的最佳实践,与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求。
17 |
官方文档 »
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
Github
26 |
Spring Security 源码
27 |
查看详情 »
28 |
29 |
30 |
Stackoverflow
31 |
Spring Security 相关问题答疑
32 |
查看详情 »
33 |
34 |
35 |
Micro
36 |
Spring Security 在微服务架构下的实践
37 |
查看详情 »
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/resources/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 登录 | SpringForAll - Spring Security
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Login
20 |
21 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/resources/templates/register.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 注册 | SpringForAll - Spring Security
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Login
20 |
21 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/src/main/resources/templates/user/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 登录 | SpringForAll - Spring Security
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |

17 |
Anoy
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/00 - 注册登录(数据库)/user.sql:
--------------------------------------------------------------------------------
1 | -- ----------------------------
2 | -- Table structure for `user`
3 | -- ----------------------------
4 | DROP TABLE IF EXISTS `user`;
5 | CREATE TABLE `user` (
6 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
7 | `username` varchar(255) DEFAULT NULL COMMENT '账号',
8 | `password` varchar(255) DEFAULT NULL COMMENT '密码',
9 | `nickname` varchar(255) DEFAULT '' COMMENT '昵称',
10 | PRIMARY KEY (`id`)
11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/README.md:
--------------------------------------------------------------------------------
1 | ## 使用手册
2 |
3 | 1、创建数据库
4 | ```
5 | create database `security01` default character set utf8mb4 collate utf8mb4_general_ci;
6 | ```
7 |
8 | 2、执行 `user.sql`
9 |
10 | 3、执行 `mvn spring-boot:run`
11 |
12 | 4、注册账号 http://localhost:8080/register
13 |
14 | 5、登录 http://localhost:8080/login
15 |
16 | ## 相关资料
17 |
18 | - https://docs.spring.io/spring-security/site/docs/5.1.4.RELEASE/reference/htmlsingle/#spring-security-crypto-encryption
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.anoyi
8 | security-login-db-encrypt
9 | 1.0-SNAPSHOT
10 |
11 | Spring Security 基础 DEMO (数据库版)- 更多内容访问 https://anoyi.com
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.1.3.RELEASE
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-thymeleaf
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-security
33 |
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-data-jpa
38 |
39 |
40 |
41 | org.projectlombok
42 | lombok
43 | 1.16.16
44 |
45 |
46 |
47 | org.mariadb.jdbc
48 | mariadb-java-client
49 | 2.0.2
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | org.springframework.boot
58 | spring-boot-maven-plugin
59 |
60 |
61 |
62 | repackage
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | spring-milestones
73 | Spring Milestones
74 | https://repo.spring.io/libs-milestone
75 |
76 | false
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/Application.java:
--------------------------------------------------------------------------------
1 | package com.spring4all;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(Application.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/config/DbUserDetailsService.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import com.spring4all.service.UserService;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
7 | import org.springframework.security.core.userdetails.UserDetails;
8 | import org.springframework.security.core.userdetails.UserDetailsService;
9 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
10 | import org.springframework.stereotype.Service;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | @Service
16 | public class DbUserDetailsService implements UserDetailsService {
17 |
18 | private final UserService userService;
19 |
20 | @Autowired
21 | DbUserDetailsService(UserService userService){
22 | this.userService = userService;
23 | }
24 |
25 | @Override
26 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
27 | UserDO userDO = userService.getByUsername(username);
28 | if (userDO == null){
29 | throw new UsernameNotFoundException("用户不存在!");
30 | }
31 | List simpleGrantedAuthorities = new ArrayList<>();
32 | simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
33 | return new org.springframework.security.core.userdetails.User(userDO.getUsername(), userDO.getPassword(), simpleGrantedAuthorities);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/config/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
9 | import org.springframework.security.crypto.password.NoOpPasswordEncoder;
10 | import org.springframework.security.crypto.password.PasswordEncoder;
11 |
12 | @EnableWebSecurity
13 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
14 |
15 | private DbUserDetailsService dbUserDetailsService;
16 |
17 | @Autowired
18 | public void setDbUserDetailsService(DbUserDetailsService dbUserDetailsService){
19 | this.dbUserDetailsService = dbUserDetailsService;
20 | }
21 |
22 | /**
23 | * 匹配 "/" 路径,不需要权限即可访问
24 | * 匹配 "/user" 及其以下所有路径,都需要 "USER" 权限
25 | * 登录地址为 "/login",登录成功默认跳转到页面 "/user"
26 | * 退出登录的地址为 "/logout",退出成功后跳转到页面 "/login"
27 | * 默认启用 CSRF
28 | */
29 | @Override
30 | protected void configure(HttpSecurity http) throws Exception {
31 | http
32 | .authorizeRequests()
33 | .antMatchers("/").permitAll()
34 | .antMatchers("/user/**").hasAuthority("USER")
35 | .and()
36 | .formLogin().loginPage("/login").defaultSuccessUrl("/user")
37 | .and()
38 | .logout().logoutUrl("/logout").logoutSuccessUrl("/login");
39 | }
40 |
41 | /**
42 | * 添加 UserDetailsService, 实现自定义登录校验
43 | */
44 | @Override
45 | protected void configure(AuthenticationManagerBuilder builder) throws Exception{
46 | builder.userDetailsService(dbUserDetailsService);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/controller/HomeController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import com.spring4all.service.UserService;
5 | import lombok.AllArgsConstructor;
6 | import org.springframework.stereotype.Controller;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.PostMapping;
9 |
10 | @Controller
11 | @AllArgsConstructor
12 | public class HomeController {
13 |
14 | private final UserService userService;
15 |
16 | @GetMapping({"/", "/index", "/home"})
17 | public String root(){
18 | return "index";
19 | }
20 |
21 | @GetMapping("/login")
22 | public String login(){
23 | return "login";
24 | }
25 |
26 | @GetMapping("/register")
27 | public String register(){
28 | return "register";
29 | }
30 |
31 | @PostMapping("/register")
32 | public String doRegister(UserDO userDO){
33 | // 此处省略校验逻辑
34 | userService.insert(userDO);
35 | return "redirect:register?success";
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import org.springframework.security.core.annotation.AuthenticationPrincipal;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 |
8 | import java.security.Principal;
9 |
10 | @Controller
11 | public class UserController {
12 |
13 | @GetMapping("/user")
14 | public String user(@AuthenticationPrincipal Principal principal, Model model){
15 | model.addAttribute("username", principal.getName());
16 | return "user/user";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/entity/UserDO.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.entity;
2 |
3 | import lombok.Data;
4 |
5 | import javax.persistence.*;
6 |
7 | @Entity
8 | @Table(name = "user")
9 | @Data
10 | public class UserDO {
11 |
12 | @Id
13 | @GeneratedValue(strategy = GenerationType.AUTO)
14 | private Long id;
15 |
16 | /**
17 | * 账号
18 | */
19 | private String username;
20 |
21 | /**
22 | * 密码
23 | */
24 | private String password;
25 |
26 | /**
27 | * 昵称
28 | */
29 | private String nickname;
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.repository;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import org.springframework.data.repository.CrudRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface UserRepository extends CrudRepository {
9 |
10 | UserDO findByUsername(String username);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.service;
2 |
3 | import com.spring4all.entity.UserDO;
4 |
5 | public interface UserService {
6 |
7 | /**
8 | * 添加新用户
9 | *
10 | * username 唯一, 默认 USER 权限
11 | */
12 | void insert(UserDO userDO);
13 |
14 | /**
15 | * 查询用户信息
16 | * @param username 账号
17 | * @return UserEntity
18 | */
19 | UserDO getByUsername(String username);
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/java/com/spring4all/service/impl/BaseUserService.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.service.impl;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import com.spring4all.repository.UserRepository;
5 | import com.spring4all.service.UserService;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.context.annotation.Primary;
8 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
9 | import org.springframework.security.crypto.password.NoOpPasswordEncoder;
10 | import org.springframework.security.crypto.password.PasswordEncoder;
11 | import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
12 | import org.springframework.security.crypto.password.StandardPasswordEncoder;
13 | import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
14 | import org.springframework.stereotype.Service;
15 |
16 | import java.util.HashMap;
17 | import java.util.Map;
18 | import java.util.Random;
19 |
20 | @Service
21 | @Primary
22 | @Slf4j
23 | public class BaseUserService implements UserService {
24 |
25 | private final static Map ENCODER_TYPE = new HashMap<>();
26 |
27 | private final static Map ENCODER_MAP = new HashMap<>();
28 |
29 | private final static String PASSWORD_FORMAT = "{%s}%s";
30 |
31 | private final UserRepository userRepository;
32 |
33 | public BaseUserService(UserRepository userRepository) {
34 | this.userRepository = userRepository;
35 | }
36 |
37 | static {
38 | ENCODER_TYPE.put(0, "noop");
39 | ENCODER_TYPE.put(1, "bcrypt");
40 | ENCODER_TYPE.put(2, "pbkdf2");
41 | ENCODER_TYPE.put(3, "scrypt");
42 | ENCODER_TYPE.put(4, "sha256");
43 | ENCODER_MAP.put("noop", NoOpPasswordEncoder.getInstance());
44 | ENCODER_MAP.put("bcrypt", new BCryptPasswordEncoder());
45 | ENCODER_MAP.put("pbkdf2", new Pbkdf2PasswordEncoder());
46 | ENCODER_MAP.put("scrypt", new SCryptPasswordEncoder());
47 | ENCODER_MAP.put("sha256", new StandardPasswordEncoder());
48 | }
49 |
50 | @Override
51 | public void insert(UserDO userDO) {
52 | String username = userDO.getUsername();
53 | if (exist(username)) {
54 | throw new RuntimeException("用户名已存在!");
55 | }
56 | // 随机使用加密方式
57 | Random random = new Random();
58 | int x = random.nextInt(5);
59 | String encoderType = ENCODER_TYPE.get(x);
60 | PasswordEncoder passwordEncoder = ENCODER_MAP.get(encoderType);
61 | userDO.setPassword(String.format(PASSWORD_FORMAT, encoderType, passwordEncoder.encode(userDO.getPassword())));
62 | userRepository.save(userDO);
63 | }
64 |
65 | @Override
66 | public UserDO getByUsername(String username) {
67 | return userRepository.findByUsername(username);
68 | }
69 |
70 | /**
71 | * 判断用户是否存在
72 | */
73 | private boolean exist(String username) {
74 | UserDO userDO = userRepository.findByUsername(username);
75 | return (userDO != null);
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | thymeleaf:
6 | cache: false
7 | datasource:
8 | url: jdbc:mysql://localhost:3306/security01?useUnicode=true&characterEncoding=utf8mb4
9 | driver-class-name: org.mariadb.jdbc.Driver
10 | username: root
11 | password: Passw0rd
12 | jpa:
13 | hibernate:
14 | ddl-auto: update
15 | database-platform: org.hibernate.dialect.MySQL5Dialect
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/resources/templates/header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Spring Security
16 |
Spring Security 是一个功能强大且可高度自定义的身份验证和访问控制框架,它是保护基于 Spring 的应用的最佳实践,与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求。
17 |
官方文档 »
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
Github
26 |
Spring Security 源码
27 |
查看详情 »
28 |
29 |
30 |
Stackoverflow
31 |
Spring Security 相关问题答疑
32 |
查看详情 »
33 |
34 |
35 |
Micro
36 |
Spring Security 在微服务架构下的实践
37 |
查看详情 »
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/resources/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 登录 | SpringForAll - Spring Security
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Login
20 |
21 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/resources/templates/register.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 注册 | SpringForAll - Spring Security
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Login
20 |
21 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/src/main/resources/templates/user/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 登录 | SpringForAll - Spring Security
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |

17 |
Anoy
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/01 - 密码加密(数据库)/user.sql:
--------------------------------------------------------------------------------
1 | -- ----------------------------
2 | -- Table structure for `user`
3 | -- ----------------------------
4 | DROP TABLE IF EXISTS `user`;
5 | CREATE TABLE `user` (
6 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
7 | `username` varchar(255) DEFAULT NULL COMMENT '账号',
8 | `password` varchar(255) DEFAULT NULL COMMENT '密码',
9 | `nickname` varchar(255) DEFAULT '' COMMENT '昵称',
10 | PRIMARY KEY (`id`)
11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--------------------------------------------------------------------------------
/02 - 自定义登录/README.md:
--------------------------------------------------------------------------------
1 | ## 使用手册
2 |
3 | 1、执行 `mvn spring-boot:run`
4 |
5 | 2、访问 http://localhost:8080/
6 |
7 | 3、点击 `登录`
8 |
9 | > 账号:anoyi
10 | > 密码:anoyi
--------------------------------------------------------------------------------
/02 - 自定义登录/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.anoyi
8 | security-custom-login
9 | 1.0-SNAPSHOT
10 |
11 | Spring Security 基础 DEMO - 更多内容访问 https://anoyi.com
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.1.3.RELEASE
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-thymeleaf
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-security
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-maven-plugin
41 |
42 |
43 |
44 | repackage
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/java/com/spring4all/Application.java:
--------------------------------------------------------------------------------
1 | package com.spring4all;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(Application.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/java/com/spring4all/config/CustomFromLoginFilter.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import org.springframework.http.HttpMethod;
4 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
5 | import org.springframework.security.core.Authentication;
6 | import org.springframework.security.core.AuthenticationException;
7 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
8 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
9 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
10 |
11 | import javax.servlet.ServletException;
12 | import javax.servlet.http.HttpServletRequest;
13 | import javax.servlet.http.HttpServletResponse;
14 | import java.io.IOException;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | /**
19 | * 自定义表单登录
20 | */
21 | public class CustomFromLoginFilter extends AbstractAuthenticationProcessingFilter {
22 |
23 | CustomFromLoginFilter(String defaultFilterProcessesUrl) {
24 | super(new AntPathRequestMatcher(defaultFilterProcessesUrl, HttpMethod.POST.name()));
25 | }
26 |
27 | @Override
28 | public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
29 | String username = httpServletRequest.getParameter("username");
30 | String password = httpServletRequest.getParameter("password");
31 | customCheck(username, password);
32 | List simpleGrantedAuthorities = new ArrayList<>();
33 | simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
34 | return new UsernamePasswordAuthenticationToken(username, password, simpleGrantedAuthorities);
35 | }
36 |
37 | private void customCheck(String username, String password){
38 | if (!("anoyi".equals(username) && "anoyi".equals(password))){
39 | throw new RuntimeException("用户名或密码错误!");
40 | }
41 |
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/java/com/spring4all/config/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
4 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
5 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
6 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
7 |
8 | @EnableWebSecurity
9 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
10 |
11 | /**
12 | * 匹配 "/" 路径,不需要权限即可访问
13 | * 匹配 "/user" 及其以下所有路径,都需要 "USER" 权限
14 | * 退出登录的地址为 "/logout",退出成功后跳转到页面 "/login"
15 | * 默认启用 CSRF
16 | */
17 | @Override
18 | protected void configure(HttpSecurity http) throws Exception {
19 | http
20 | .authorizeRequests()
21 | .antMatchers("/").permitAll()
22 | .antMatchers("/user/**").hasAuthority("USER")
23 | .and()
24 | .logout().logoutUrl("/logout").logoutSuccessUrl("/login");
25 |
26 | http.addFilterAt(customFromLoginFilter(), UsernamePasswordAuthenticationFilter.class);
27 | }
28 |
29 | /**
30 | * 自定义认证过滤器
31 | */
32 | private CustomFromLoginFilter customFromLoginFilter() {
33 | return new CustomFromLoginFilter("/login");
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/java/com/spring4all/controller/HomeController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 |
6 | @Controller
7 | public class HomeController {
8 |
9 | @GetMapping({"/", "/index", "/home"})
10 | public String root(){
11 | return "index";
12 | }
13 |
14 | @GetMapping("/login")
15 | public String login(){
16 | return "login";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/java/com/spring4all/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import org.springframework.security.core.annotation.AuthenticationPrincipal;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 |
8 | import java.security.Principal;
9 |
10 | @Controller
11 | public class UserController {
12 |
13 | @GetMapping("/user")
14 | public String user(@AuthenticationPrincipal Principal principal, Model model){
15 | model.addAttribute("username", principal.getName());
16 | return "user/user";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | thymeleaf:
6 | cache: false
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/resources/templates/header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Spring Security
16 |
Spring Security 是一个功能强大且可高度自定义的身份验证和访问控制框架,它是保护基于 Spring 的应用的最佳实践,与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求。
17 |
官方文档 »
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
Github
26 |
Spring Security 源码
27 |
查看详情 »
28 |
29 |
30 |
Stackoverflow
31 |
Spring Security 相关问题答疑
32 |
查看详情 »
33 |
34 |
35 |
Micro
36 |
Spring Security 在微服务架构下的实践
37 |
查看详情 »
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/resources/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 登录 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Login
20 |
21 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/02 - 自定义登录/src/main/resources/templates/user/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 用户中心 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |

17 |
Anoyi
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/README.md:
--------------------------------------------------------------------------------
1 | ## 使用手册
2 |
3 | 1、创建数据库(可选操作)
4 | >(与 [00 - 注册登录](https://github.com/ChinaSilence/spring-security-demos/tree/master/00%20-%20%E6%B3%A8%E5%86%8C%E7%99%BB%E5%BD%95) 章节数据库相同)
5 | ```
6 | create database `security00` default character set utf8mb4 collate utf8mb4_general_ci;
7 | ```
8 |
9 | 2、执行 `user.sql`(可选操作)
10 |
11 | 3、执行 `mvn spring-boot:run`
12 |
13 | 4、【未登录】获取个人信息
14 | ```
15 | curl -X GET http://localhost:8080/user
16 |
17 | # 结果
18 | {"code":"401","message":"authenticate fail"}
19 | ```
20 |
21 | 5、【未登录】注册账号(可选操作)
22 | ```
23 | curl -X POST \
24 | http://localhost:8080/register \
25 | -H 'Content-Type: application/json' \
26 | -d '{
27 | "username":"anoyi",
28 | "password":"anoyi",
29 | "nickname":"Anoyi"
30 | }'
31 |
32 | # 结果
33 | {"code": "0","message": "success","result": "注册成功"}
34 | ```
35 |
36 |
37 | 6、登录账号
38 | ```
39 | curl -v -X POST \
40 | http://localhost:8080/login \
41 | -H 'Content-Type: application/json' \
42 | -d '{
43 | "username":"anoyi",
44 | "password":"anoyi"
45 | }'
46 |
47 | # 结果
48 | * Trying 127.0.0.1...
49 | * TCP_NODELAY set
50 | * Connected to localhost (127.0.0.1) port 8080 (#0)
51 | > POST /login HTTP/1.1
52 | > Host: localhost:8080
53 | > User-Agent: curl/7.54.0
54 | > Accept: */*
55 | > Content-Type: application/json
56 | > Content-Length: 44
57 | >
58 | * upload completely sent off: 44 out of 44 bytes
59 | < HTTP/1.1 200
60 | < X-Content-Type-Options: nosniff
61 | < X-XSS-Protection: 1; mode=block
62 | < Cache-Control: no-cache, no-store, max-age=0, must-revalidate
63 | < Pragma: no-cache
64 | < Expires: 0
65 | < X-Frame-Options: DENY
66 | < Set-Cookie: JSESSIONID=37A9E0E7143FC52E77639069A6F8C3B3; Path=/; HttpOnly
67 | < Content-Type: application/json;charset=UTF-8
68 | < Content-Length: 56
69 | < Date: Tue, 02 Apr 2019 07:38:34 GMT
70 | <
71 | * Connection #0 to host localhost left intact
72 | {"code":"0","message":"success","result":"登录成功"}
73 | ```
74 | > 登录成功,并返回 SESSION 信息:`Set-Cookie: JSESSIONID=37A9E0E7143FC52E77639069A6F8C3B3; Path=/; HttpOnly`
75 |
76 | 7、【已登录】获取个人信息
77 | ```
78 | curl -X GET http://localhost:8080/user -H 'Cookie: JSESSIONID=19CE7D4D28E32073226AEAC0529B3523'
79 |
80 | # 结果
81 | {"code":"0","message":"success","result":"anoyi"}
82 | ```
83 |
84 | 7、【已登录】获取 ADMIN 信息
85 | ```
86 | curl -X GET http://localhost:8080/admin -H 'Cookie: JSESSIONID=19CE7D4D28E32073226AEAC0529B3523'
87 |
88 | # 结果
89 | {"code":"2","message":"forbidden"}
90 | ```
91 |
92 | 8、【已登录】退出登录
93 | ```
94 | curl -X GET http://localhost:8080/logout
95 |
96 | # 结果
97 | {"code":"0","message":"success","result":"退出成功"}
98 | ```
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.anoyi
8 | security-json
9 | 1.0-SNAPSHOT
10 |
11 | Spring Security 基础 DEMO (数据库版)- 更多内容访问 https://anoyi.com
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.1.3.RELEASE
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-security
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-data-jpa
33 |
34 |
35 |
36 | org.projectlombok
37 | lombok
38 | 1.16.16
39 |
40 |
41 |
42 | org.mariadb.jdbc
43 | mariadb-java-client
44 | 2.0.2
45 |
46 |
47 |
48 | com.alibaba
49 | fastjson
50 | 1.2.56
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | org.springframework.boot
59 | spring-boot-maven-plugin
60 |
61 |
62 |
63 | repackage
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | spring-milestones
74 | Spring Milestones
75 | https://repo.spring.io/libs-milestone
76 |
77 | false
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/Application.java:
--------------------------------------------------------------------------------
1 | package com.spring4all;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(Application.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/bean/WebResponse.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.bean;
2 |
3 |
4 | import com.spring4all.constant.CommonResponse;
5 | import com.spring4all.constant.HttpResponseStatusEnum;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 |
10 | /**
11 | * HTTP 统一响应结果
12 | */
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | public class WebResponse {
17 |
18 | /**
19 | * 响应码
20 | */
21 | private String code;
22 |
23 | /**
24 | * 提示信息
25 | */
26 | private String message;
27 |
28 | /**
29 | * 结果
30 | */
31 | private Object result;
32 |
33 | public WebResponse(HttpResponseStatusEnum httpResponseStatusEnum) {
34 | this.code = httpResponseStatusEnum.getCode();
35 | this.message = httpResponseStatusEnum.getMessage();
36 | }
37 |
38 | public WebResponse(CommonResponse commonResponse) {
39 | this.code = commonResponse.getCode();
40 | this.message = commonResponse.getMessage();
41 | }
42 |
43 | /**
44 | * 成功响应
45 | */
46 | public static WebResponse success() {
47 | return new WebResponse(HttpResponseStatusEnum.SUCCESS.getCode(), HttpResponseStatusEnum.SUCCESS.getMessage(), null);
48 | }
49 |
50 | /**
51 | * 成功响应
52 | */
53 | public static WebResponse success(Object result) {
54 | return new WebResponse(HttpResponseStatusEnum.SUCCESS.getCode(), HttpResponseStatusEnum.SUCCESS.getMessage(), result);
55 | }
56 |
57 | /**
58 | * 禁止操作
59 | */
60 | public static WebResponse forbidden() {
61 | return new WebResponse(HttpResponseStatusEnum.FORBIDDEN_OPERATION.getCode(), HttpResponseStatusEnum.FORBIDDEN_OPERATION.getMessage(), null);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/config/CustomAccessDeniedHandler.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.spring4all.bean.WebResponse;
5 | import org.springframework.http.MediaType;
6 | import org.springframework.security.access.AccessDeniedException;
7 | import org.springframework.security.web.access.AccessDeniedHandler;
8 |
9 | import javax.servlet.ServletException;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.io.IOException;
13 | import java.nio.charset.StandardCharsets;
14 |
15 | /**
16 | * 拒绝访问处理器(登录状态下,无权限会触发)
17 | */
18 | public class CustomAccessDeniedHandler implements AccessDeniedHandler {
19 |
20 | @Override
21 | public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
22 | httpServletResponse.setStatus(HttpServletResponse.SC_OK);
23 | httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
24 | httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());
25 | httpServletResponse.getWriter().write(JSON.toJSONString(WebResponse.forbidden()));
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/config/CustomAuthenticationEntryPoint.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.spring4all.bean.WebResponse;
5 | import org.springframework.http.MediaType;
6 | import org.springframework.security.core.AuthenticationException;
7 | import org.springframework.security.web.AuthenticationEntryPoint;
8 |
9 | import javax.servlet.ServletException;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.io.IOException;
13 | import java.nio.charset.StandardCharsets;
14 |
15 | /**
16 | * 认证入口(未登录状态)
17 | */
18 | public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
19 |
20 | @Override
21 | public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
22 | WebResponse response = new WebResponse();
23 | response.setCode(String.valueOf(HttpServletResponse.SC_UNAUTHORIZED));
24 | response.setMessage("authenticate fail");
25 | httpServletResponse.setStatus(HttpServletResponse.SC_OK);
26 | httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
27 | httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());
28 | httpServletResponse.getWriter().write(JSON.toJSONString(response));
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/config/CustomAuthenticationFailureHandler.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.spring4all.bean.WebResponse;
5 | import org.springframework.http.MediaType;
6 | import org.springframework.security.core.AuthenticationException;
7 | import org.springframework.security.web.authentication.AuthenticationFailureHandler;
8 |
9 | import javax.servlet.ServletException;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.io.IOException;
13 | import java.nio.charset.StandardCharsets;
14 |
15 | /**
16 | * 认证失败处理器
17 | */
18 | public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
19 |
20 | @Override
21 | public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
22 | WebResponse response = new WebResponse();
23 | response.setCode("-1");
24 | response.setMessage(e.getMessage());
25 | httpServletResponse.setStatus(HttpServletResponse.SC_OK);
26 | httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
27 | httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());
28 | httpServletResponse.getWriter().write(JSON.toJSONString(response));
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/config/CustomAuthenticationSuccessHandler.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.spring4all.bean.WebResponse;
5 | import org.springframework.http.MediaType;
6 | import org.springframework.security.core.Authentication;
7 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
8 |
9 | import javax.servlet.ServletException;
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 | import java.io.IOException;
13 | import java.nio.charset.StandardCharsets;
14 |
15 | /**
16 | * 认证成功处理器
17 | */
18 | public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
19 |
20 | @Override
21 | public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
22 | WebResponse response = WebResponse.success("登录成功");
23 | httpServletResponse.setStatus(HttpServletResponse.SC_OK);
24 | httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
25 | httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString());
26 | httpServletResponse.getWriter().write(JSON.toJSONString(response));
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/config/CustomJSONLoginFilter.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.spring4all.entity.UserDO;
6 | import com.spring4all.service.UserService;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.http.HttpMethod;
9 | import org.springframework.security.authentication.AuthenticationServiceException;
10 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
11 | import org.springframework.security.core.Authentication;
12 | import org.springframework.security.core.AuthenticationException;
13 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
14 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
15 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
16 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
17 | import org.springframework.util.StreamUtils;
18 |
19 | import javax.servlet.ServletException;
20 | import javax.servlet.http.HttpServletRequest;
21 | import javax.servlet.http.HttpServletResponse;
22 | import java.io.IOException;
23 | import java.io.InputStream;
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | /**
28 | * 自定义 JSON 登录
29 | */
30 | @Slf4j
31 | public class CustomJSONLoginFilter extends AbstractAuthenticationProcessingFilter {
32 |
33 | private final UserService userService;
34 |
35 | CustomJSONLoginFilter(String defaultFilterProcessesUrl, UserService userService) {
36 | super(new AntPathRequestMatcher(defaultFilterProcessesUrl, HttpMethod.POST.name()));
37 | this.userService = userService;
38 | }
39 |
40 | @Override
41 | public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
42 | JSONObject requestBody = getRequestBody(httpServletRequest);
43 | String username = requestBody.getString("username");
44 | String password = requestBody.getString("password");
45 | validateUsernameAndPassword(username, password);
46 | List simpleGrantedAuthorities = new ArrayList<>();
47 | simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
48 | return new UsernamePasswordAuthenticationToken(username, password, simpleGrantedAuthorities);
49 | }
50 |
51 | /**
52 | * 获取请求体
53 | */
54 | private JSONObject getRequestBody(HttpServletRequest request) throws AuthenticationException{
55 | try {
56 | StringBuilder stringBuilder = new StringBuilder();
57 | InputStream inputStream = request.getInputStream();
58 | byte[] bs = new byte[StreamUtils.BUFFER_SIZE];
59 | int len;
60 | while ((len = inputStream.read(bs)) != -1) {
61 | stringBuilder.append(new String(bs, 0, len));
62 | }
63 | return JSON.parseObject(stringBuilder.toString());
64 | } catch (IOException e) {
65 | log.error("get request body error.");
66 | }
67 | throw new AuthenticationServiceException("invalid request body");
68 | }
69 |
70 | /**
71 | * 校验用户名和密码
72 | */
73 | private void validateUsernameAndPassword(String username, String password) throws AuthenticationException {
74 | UserDO userDO = userService.getByUsername(username);
75 | if (userDO == null){
76 | throw new UsernameNotFoundException("user not exist");
77 | }
78 | if(!userDO.getPassword().equals(password)){
79 | throw new AuthenticationServiceException("error username or password");
80 | }
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/config/CustomLogoutSuccessHandler.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.spring4all.bean.WebResponse;
5 | import org.springframework.http.MediaType;
6 | import org.springframework.security.core.Authentication;
7 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.http.HttpServletRequest;
10 | import javax.servlet.http.HttpServletResponse;
11 | import java.io.IOException;
12 | import java.nio.charset.StandardCharsets;
13 |
14 | /**
15 | * 退出成功处理器
16 | */
17 | public class CustomLogoutSuccessHandler implements LogoutSuccessHandler {
18 |
19 | @Override
20 | public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
21 | WebResponse httpServletResponse = WebResponse.success("退出成功");
22 | response.setStatus(HttpServletResponse.SC_OK);
23 | response.setContentType(MediaType.APPLICATION_JSON_VALUE);
24 | response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
25 | response.getWriter().write(JSON.toJSONString(httpServletResponse));
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/config/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import com.spring4all.service.UserService;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
8 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
9 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
10 | import org.springframework.security.crypto.password.NoOpPasswordEncoder;
11 | import org.springframework.security.crypto.password.PasswordEncoder;
12 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
13 |
14 | @EnableWebSecurity
15 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
16 |
17 | private UserService userService;
18 |
19 | @Autowired
20 | public void setUserService(UserService userService){
21 | this.userService = userService;
22 | }
23 |
24 | /**
25 | * 匹配 "/register" 路径,不需要权限即可访问
26 | * 匹配 "/user" 及其以下所有路径,都需要 "USER" 权限
27 | * 登录地址为 "/login",登录成功返回响应状态码
28 | * 退出登录的地址为 "/logout",退出成功返回响应状态码
29 | * 禁用 CSRF
30 | */
31 | @Override
32 | protected void configure(HttpSecurity http) throws Exception {
33 | http
34 | .authorizeRequests()
35 | .antMatchers("/", "/register").permitAll()
36 | .antMatchers("/user/**").hasAuthority("USER")
37 | .antMatchers("/admin/**").hasAuthority("ADMIN")
38 | .and()
39 | .logout().logoutUrl("/logout")
40 | .logoutSuccessHandler(new CustomLogoutSuccessHandler())
41 | .clearAuthentication(true).permitAll()
42 | .and()
43 | .exceptionHandling().authenticationEntryPoint(new CustomAuthenticationEntryPoint())
44 | .accessDeniedHandler(new CustomAccessDeniedHandler())
45 | .and()
46 | .csrf().disable();
47 |
48 | http.addFilterAt(customJSONLoginFilter(), UsernamePasswordAuthenticationFilter.class);
49 | }
50 |
51 | /**
52 | * 自定义认证过滤器
53 | */
54 | private CustomJSONLoginFilter customJSONLoginFilter() {
55 | CustomJSONLoginFilter customJSONLoginFilter = new CustomJSONLoginFilter("/login", userService);
56 | customJSONLoginFilter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler());
57 | customJSONLoginFilter.setAuthenticationSuccessHandler(new CustomAuthenticationSuccessHandler());
58 | return customJSONLoginFilter;
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/constant/CommonResponse.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.constant;
2 |
3 | /**
4 | * 通用响应体
5 | */
6 | public interface CommonResponse {
7 |
8 | /**
9 | * 获取状态码
10 | */
11 | String getCode();
12 |
13 | /**
14 | * 获取消息
15 | */
16 | String getMessage();
17 |
18 | /**
19 | * 响应结果
20 | */
21 | Object getResult();
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/constant/HttpResponseStatusEnum.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.constant;
2 |
3 | import lombok.AllArgsConstructor;
4 |
5 | @AllArgsConstructor
6 | public enum HttpResponseStatusEnum implements CommonResponse {
7 |
8 | SUCCESS("0", "success"), // 成功请求
9 | FORBIDDEN_OPERATION("2", "forbidden") // 权限不足
10 | ;
11 | private String code;
12 | private String message;
13 |
14 | @Override
15 | public String getCode() {
16 | return code;
17 | }
18 |
19 | @Override
20 | public String getMessage() {
21 | return message;
22 | }
23 |
24 | @Override
25 | public Object getResult() {
26 | return null;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/controller/HomeController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import com.spring4all.bean.WebResponse;
4 | import com.spring4all.entity.UserDO;
5 | import com.spring4all.service.UserService;
6 | import lombok.AllArgsConstructor;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 | import org.springframework.web.bind.annotation.RequestBody;
9 | import org.springframework.web.bind.annotation.RestController;
10 |
11 | @RestController
12 | @AllArgsConstructor
13 | public class HomeController {
14 |
15 | private final UserService userService;
16 |
17 | @PostMapping("/register")
18 | public WebResponse doRegister(@RequestBody UserDO userDO){
19 | // 此处省略校验逻辑
20 | userService.insert(userDO);
21 | return WebResponse.success("注册成功");
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import com.spring4all.bean.WebResponse;
4 | import org.springframework.security.core.annotation.AuthenticationPrincipal;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.RestController;
7 |
8 | import java.security.Principal;
9 |
10 | @RestController
11 | public class UserController {
12 |
13 | @GetMapping("/user")
14 | public WebResponse user(@AuthenticationPrincipal Principal principal){
15 | return WebResponse.success(principal.getName());
16 | }
17 |
18 | @GetMapping("/admin")
19 | public WebResponse admin(@AuthenticationPrincipal Principal principal){
20 | return WebResponse.success(principal.getName());
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/entity/UserDO.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.entity;
2 |
3 | import lombok.Data;
4 |
5 | import javax.persistence.*;
6 |
7 | @Entity
8 | @Table(name = "user")
9 | @Data
10 | public class UserDO {
11 |
12 | @Id
13 | @GeneratedValue(strategy = GenerationType.AUTO)
14 | private Long id;
15 |
16 | /**
17 | * 账号
18 | */
19 | private String username;
20 |
21 | /**
22 | * 密码
23 | */
24 | private String password;
25 |
26 | /**
27 | * 昵称
28 | */
29 | private String nickname;
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.repository;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import org.springframework.data.repository.CrudRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface UserRepository extends CrudRepository {
9 |
10 | UserDO findByUsername(String username);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.service;
2 |
3 | import com.spring4all.entity.UserDO;
4 |
5 | public interface UserService {
6 |
7 | /**
8 | * 添加新用户
9 | *
10 | * username 唯一, 默认 USER 权限
11 | */
12 | void insert(UserDO userDO);
13 |
14 | /**
15 | * 查询用户信息
16 | * @param username 账号
17 | * @return UserEntity
18 | */
19 | UserDO getByUsername(String username);
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/java/com/spring4all/service/impl/BaseUserService.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.service.impl;
2 |
3 | import com.spring4all.entity.UserDO;
4 | import com.spring4all.repository.UserRepository;
5 | import com.spring4all.service.UserService;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.context.annotation.Primary;
8 | import org.springframework.stereotype.Service;
9 |
10 | @Service
11 | @Primary
12 | @Slf4j
13 | public class BaseUserService implements UserService {
14 |
15 | private final UserRepository userRepository;
16 |
17 | public BaseUserService(UserRepository userRepository){
18 | this.userRepository = userRepository;
19 | }
20 |
21 | @Override
22 | public void insert(UserDO userDO) {
23 | String username = userDO.getUsername();
24 | if (exist(username)){
25 | throw new RuntimeException("用户名已存在!");
26 | }
27 | userRepository.save(userDO);
28 | }
29 |
30 | @Override
31 | public UserDO getByUsername(String username) {
32 | return userRepository.findByUsername(username);
33 | }
34 |
35 | /**
36 | * 判断用户是否存在
37 | */
38 | private boolean exist(String username){
39 | UserDO userDO = userRepository.findByUsername(username);
40 | return (userDO != null);
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | thymeleaf:
6 | cache: false
7 | datasource:
8 | url: jdbc:mysql://localhost:3306/security00?useUnicode=true&characterEncoding=utf8mb4
9 | driver-class-name: org.mariadb.jdbc.Driver
10 | username: root
11 | password: Passw0rd
12 | jpa:
13 | hibernate:
14 | ddl-auto: update
15 | open-in-view: false
16 | database-platform: org.hibernate.dialect.MySQL5Dialect
--------------------------------------------------------------------------------
/03 - 前后端分离(JSON交互)/user.sql:
--------------------------------------------------------------------------------
1 | -- ----------------------------
2 | -- Table structure for `user`
3 | -- ----------------------------
4 | DROP TABLE IF EXISTS `user`;
5 | CREATE TABLE `user` (
6 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
7 | `username` varchar(255) DEFAULT NULL COMMENT '账号',
8 | `password` varchar(255) DEFAULT NULL COMMENT '密码',
9 | `nickname` varchar(255) DEFAULT '' COMMENT '昵称',
10 | PRIMARY KEY (`id`)
11 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--------------------------------------------------------------------------------
/04 - Basic 认证/README.md:
--------------------------------------------------------------------------------
1 | ## 使用手册
2 |
3 | 1、执行 `mvn spring-boot:run`
4 |
5 | 2、访问 http://localhost:8080/
6 |
7 | 3、点击 `登录`
8 |
9 | > 账号:anoyi
10 | > 密码:anoyi
--------------------------------------------------------------------------------
/04 - Basic 认证/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.anoyi
8 | security-basic-authentication
9 | 1.0-SNAPSHOT
10 |
11 | Spring Security 基础 DEMO (无数据库版)- 更多内容访问 https://anoyi.com
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.1.3.RELEASE
17 |
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-thymeleaf
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-security
33 |
34 |
35 |
36 |
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-maven-plugin
41 |
42 |
43 |
44 | repackage
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/java/com/spring4all/Application.java:
--------------------------------------------------------------------------------
1 | package com.spring4all;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class Application {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(Application.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/java/com/spring4all/config/WebSecurityConfig.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
7 | import org.springframework.security.core.userdetails.User;
8 | import org.springframework.security.core.userdetails.UserDetailsService;
9 | import org.springframework.security.provisioning.InMemoryUserDetailsManager;
10 |
11 | @EnableWebSecurity
12 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
13 |
14 | /**
15 | * 匹配 "/" 路径,不需要权限即可访问
16 | * 匹配 "/user" 及其以下所有路径,都需要 "USER" 权限
17 | * 登录地址为 "/login",登录成功默认跳转到页面 "/user"
18 | * 退出登录的地址为 "/logout",退出成功后跳转到页面 "/login"
19 | * 默认启用 CSRF
20 | */
21 | @Override
22 | protected void configure(HttpSecurity http) throws Exception {
23 | http.authorizeRequests()
24 | .anyRequest().authenticated()
25 | .and()
26 | .httpBasic().realmName("spring");
27 | }
28 |
29 | /**
30 | * 在内存中创建一个名为 "user" 的用户,密码为 "pwd",拥有 "USER" 权限
31 | */
32 | @Bean
33 | @Override
34 | protected UserDetailsService userDetailsService() {
35 | User.UserBuilder users = User.withDefaultPasswordEncoder();
36 | InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
37 | manager.createUser(users.username("anoyi").password("anoyi").roles("USER").build());
38 | return manager;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/java/com/spring4all/controller/HomeController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import org.springframework.stereotype.Controller;
4 | import org.springframework.web.bind.annotation.GetMapping;
5 |
6 | @Controller
7 | public class HomeController {
8 |
9 | @GetMapping({"/", "/index", "/home"})
10 | public String root(){
11 | return "index";
12 | }
13 |
14 | @GetMapping("/login")
15 | public String login(){
16 | return "login";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/java/com/spring4all/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.spring4all.controller;
2 |
3 | import org.springframework.security.core.annotation.AuthenticationPrincipal;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 |
8 | import java.security.Principal;
9 |
10 | @Controller
11 | public class UserController {
12 |
13 | @GetMapping("/user")
14 | public String user(@AuthenticationPrincipal Principal principal, Model model){
15 | model.addAttribute("username", principal.getName());
16 | return "user/user";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | thymeleaf:
6 | cache: false
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/resources/templates/header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/resources/templates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Spring Security
16 |
Spring Security 是一个功能强大且可高度自定义的身份验证和访问控制框架,它是保护基于 Spring 的应用的最佳实践,与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求。
17 |
官方文档 »
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
Github
26 |
Spring Security 源码
27 |
查看详情 »
28 |
29 |
30 |
Stackoverflow
31 |
Spring Security 相关问题答疑
32 |
查看详情 »
33 |
34 |
35 |
Micro
36 |
Spring Security 在微服务架构下的实践
37 |
查看详情 »
38 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/resources/templates/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 登录 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Login
20 |
21 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/04 - Basic 认证/src/main/resources/templates/user/user.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 用户中心 | Spring Security Demos
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |

17 |
Anoyi
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Spring Security Guides
2 | -----
3 | Protects your application with comprehensive and extensible authentication and authorization support.
4 |
5 |
6 |
--------------------------------------------------------------------------------