概述

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications. Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

[

](https://github.com/spring-projects/spring-security)
官方地址: https://spring.io/projects/spring-security
Github:https://github.com/spring-projects/spring-security

架构

image.png

maven

  1. <!-- 用于开发 -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-security</artifactId>
  5. </dependency>
  6. <!-- 用于测试 -->
  7. <dependency>
  8. <groupId>org.springframework.security</groupId>
  9. <artifactId>spring-security-test</artifactId>
  10. <scope>test</scope>
  11. </dependency>

核心组件

  • SecurityContext:上下文对象,Authentication对象会放在里面。
  • SecurityContextHolder:用于拿到上下文对象的静态工具类。
  • Authentication:认证接口,定义了认证对象的数据形式。
  • AuthenticationManager:用于校验Authentication,返回一个认证完成后的Authentication对象。
  1. 先是一个请求带着身份信息进来
    2. 经过AuthenticationManager的认证,
    3. 再通过SecurityContextHolder获取SecurityContext,
    4. 最后将认证后的信息放入到SecurityContext

SecurityContext

上下文对象,认证后的数据就放在这里面,接口定义如下:

  1. public interface SecurityContext extends Serializable {
  2. // 获取Authentication对象
  3. Authentication getAuthentication();
  4. // 放入Authentication对象
  5. void setAuthentication(Authentication authentication);
  6. }

SecurityContextHolder

  1. public class SecurityContextHolder {
  2. public static void clearContext() {
  3. strategy.clearContext();
  4. }
  5. public static SecurityContext getContext() {
  6. return strategy.getContext();
  7. }
  8. public static void setContext(SecurityContext context) {
  9. strategy.setContext(context);
  10. }
  11. }

可以说是SecurityContext的工具类,用于get or set or clearSecurityContext,默认会把数据都存储到当前线程中。

Authentication

image.png代码

  1. public interface Authentication extends Principal, Serializable {
  2. Collection<? extends GrantedAuthority> getAuthorities();
  3. Object getCredentials();
  4. Object getDetails();
  5. Object getPrincipal();
  6. boolean isAuthenticated();
  7. void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
  8. }
  • getAuthorities: 获取用户权限,一般情况下获取到的是用户的角色信息
  • getCredentials: 获取证明用户认证的信息,通常情况下获取到的是密码等信息。
  • getDetails: 获取用户的额外信息,(这部分信息可以是我们的用户表中的信息)。
  • getPrincipal: 获取用户身份信息,在未认证的情况下获取到的是用户名,在已认证的情况下获取到的是 UserDetails。
  • isAuthenticated: 获取当前 Authentication 是否已认证。
  • setAuthenticated: 设置当前 Authentication 是否已认证(true or false)。

Authentication只是定义了一种在SpringSecurity进行认证过的数据的数据形式应该是怎么样的,要有权限,要有密码,要有身份信息,要有额外信息。

AuthenticationManager

  1. public interface AuthenticationManager {
  2. // 认证方法
  3. Authentication authenticate(Authentication authentication)
  4. throws AuthenticationException;
  5. }

AuthenticationManager定义了一个认证方法,它将一个未认证的Authentication传入,返回一个已认证的Authentication,默认使用的实现类为:ProviderManager。

AbstractUserDetailsAuthenticationProvider

  1. // AbstractUserDetailsAuthenticationProvider
  2. public Authentication authenticate(Authentication authentication){
  3. // 校验未认证的Authentication对象里面有没有用户名
  4. String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
  5. : authentication.getName();
  6. boolean cacheWasUsed = true;
  7. // 从缓存中去查用户名为XXX的对象
  8. UserDetails user = this.userCache.getUserFromCache(username);
  9. // 如果没有就进入到这个方法
  10. if (user == null) {
  11. cacheWasUsed = false;
  12. try {
  13. // 调用我们重写UserDetailsService的loadUserByUsername方法
  14. // 拿到我们自己组装好的UserDetails对象
  15. user = retrieveUser(username,
  16. (UsernamePasswordAuthenticationToken) authentication);
  17. }
  18. catch (UsernameNotFoundException notFound) {
  19. logger.debug("User '" + username + "' not found");
  20. if (hideUserNotFoundExceptions) {
  21. throw new BadCredentialsException(messages.getMessage(
  22. "AbstractUserDetailsAuthenticationProvider.badCredentials",
  23. "Bad credentials"));
  24. }
  25. else {
  26. throw notFound;
  27. }
  28. }
  29. Assert.notNull(user,
  30. "retrieveUser returned null - a violation of the interface contract");
  31. }
  32. try {
  33. // 校验账号是否禁用
  34. preAuthenticationChecks.check(user);
  35. // 校验数据库查出来的密码,和我们传入的密码是否一致
  36. additionalAuthenticationChecks(user,
  37. (UsernamePasswordAuthenticationToken) authentication);
  38. }
  39. }

UserDetails

UserDetailsService

image.png

数据库自定义

命名规则 data.sql 和schema.sql 文件
jdbc
image.png

参考

https://www.cmsblogs.com/article/1398542173804302336