├── .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 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 | 34 |
35 |
36 |
37 |
38 |

登录失败,账号或密码错误!

39 |
40 |
41 |

42 |
43 |
44 |
45 | 46 |
47 |
48 |
49 |
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 | avatar 17 |

Anoyi

18 |
19 | 20 |
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 |
44 |

© 2019 Power By Anoyi .

45 |
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 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 | 34 |
35 |
36 |
37 |
38 |

登录失败,账号或密码错误!

39 |
40 |
41 |

42 |
43 |
44 |
45 | 46 |
47 |
48 |
49 |
50 | 创建账号 | 忘记密码? 51 |
52 |
53 |
54 |
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 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 | 33 |
34 |
35 |
36 |
37 |
38 | 39 |
40 |
41 |
42 |
43 |

注册失败,账号已存在!

44 |
45 |
46 |

注册成功,可以登录了!

47 |
48 |
49 |
50 | 51 |
52 |
53 |
54 |
55 | 返回登录页面 56 |
57 |
58 |
59 |
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 | avatar 17 |

Anoy

18 |
19 | 20 |
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 |
44 |

© 2019 Power By Anoyi .

45 |
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 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 | 34 |
35 |
36 |
37 |
38 |

登录失败,账号或密码错误!

39 |
40 |
41 |

42 |
43 |
44 |
45 | 46 |
47 |
48 |
49 |
50 | 创建账号 | 忘记密码? 51 |
52 |
53 |
54 |
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 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 | 33 |
34 |
35 |
36 |
37 |
38 | 39 |
40 |
41 |
42 |
43 |

注册失败,账号已存在!

44 |
45 |
46 |

注册成功,可以登录了!

47 |
48 |
49 |
50 | 51 |
52 |
53 |
54 |
55 | 返回登录页面 56 |
57 |
58 |
59 |
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 | avatar 17 |

Anoy

18 |
19 | 20 |
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 |
44 |

© 2019 Power By Anoyi .

45 |
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 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 | 34 |
35 |
36 |
37 |
38 |

登录失败,账号或密码错误!

39 |
40 |
41 |

42 |
43 |
44 |
45 | 46 |
47 |
48 |
49 |
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 | avatar 17 |

Anoyi

18 |
19 | 20 |
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 |
44 |

© 2019 Power By Anoyi .

45 |
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 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
32 | 34 |
35 |
36 |
37 |
38 |

登录失败,账号或密码错误!

39 |
40 |
41 |

42 |
43 |
44 |
45 | 46 |
47 |
48 |
49 |
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 | avatar 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 | --------------------------------------------------------------------------------