0%

springSecurity简介

springSecurity简介

Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案,是一种基于Spring AOP和Servlet规范中的Filter实现的安全框架,其本质是一个过滤器链

名词解释

**主体(principal)**使用系统的用户或设备或从其他系统远程登录的用户等等,谁在使用该系统

**认证(authentication)**权限管理系统确认一个主体的身份,允许主体进入系统,“主体”证明自己是谁。

**授权(authorization)**将操作系统的“权力”授予“主体”,这样主体就具备了操作系统中特定功能的能力,授权就是给用户分配权限

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

核心类

  • SecurityContextHolder 用于存储安全上下文的信息,当前用户、是否被认证、权限都存储在其中

    提供了三种存储策略,当然也可以自定义储存策略,设置strategyName来进行反射获取

    • MODE_THREADLOCAL 使用ThreadLocalSecurityContextHolderStrategy
    • MODE_INHERITABLETHREADLOCAL 使用InheritableThreadLocalSecurityContextHolderStrategy
    • MODE_GLOBAL 使用GlobalSecurityContextHolderStrategy
  • Authentication 继承自Principal,可以通过该接口来获取到用户的权限、密码以及身份信息和认证信息

    • getAuthorities 获取权限
    • getCredentials 获取密码,用户提交的密码
    • getDetails 获取详情
    • getPrincipal 获取认证信息,返回的是UserDetails的实现类
  • AuthenticationManager 认证相关的核心接口,定义了认证方法authenticate

    1
    2
    Authentication authenticate(Authentication authentication)
    throws AuthenticationException;
  • ProviderManager 认证管理,实现了AuthenticationManager,并在authenticate方法中将真正的认证逻辑委托给了AuthenticationProvider对象

  • DaoAuthenticationProvider 该类是AuthenticationProvider最常用的实现类,用来获取用户提交的用户名和密码对比正确性,实现了其父类的两个抽象方法

    1
    2
    3
    4
    5
    6
    7
    // 用于身份认证
    protected abstract void additionalAuthenticationChecks(UserDetails userDetails,
    UsernamePasswordAuthenticationToken authentication)
    // 用于从数据库获取用户信息, 这里会调用userDetailsService.loadUserByUsername方法来进行获取
    protected abstract UserDetails retrieveUser(String username,
    UsernamePasswordAuthenticationToken authentication)
    throws AuthenticationException;
  • UserDetails 用户信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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
    public interface UserDetails extends Serializable {
    // ~ Methods
    // ========================================================================================================

    /**
    * Returns the authorities granted to the user. Cannot return <code>null</code>.
    *
    * @return the authorities, sorted by natural key (never <code>null</code>)
    */
    Collection<? extends GrantedAuthority> getAuthorities();

    /**
    * Returns the password used to authenticate the user.
    *
    * @return the password
    */
    // 正确的密码
    String getPassword();

    /**
    * Returns the username used to authenticate the user. Cannot return <code>null</code>
    * .
    *
    * @return the username (never <code>null</code>)
    */
    String getUsername();

    /**
    * Indicates whether the user's account has expired. An expired account cannot be
    * authenticated.
    *
    * @return <code>true</code> if the user's account is valid (ie non-expired),
    * <code>false</code> if no longer valid (ie expired)
    */
    boolean isAccountNonExpired();

    /**
    * Indicates whether the user is locked or unlocked. A locked user cannot be
    * authenticated.
    *
    * @return <code>true</code> if the user is not locked, <code>false</code> otherwise
    */
    boolean isAccountNonLocked();

    /**
    * Indicates whether the user's credentials (password) has expired. Expired
    * credentials prevent authentication.
    *
    * @return <code>true</code> if the user's credentials are valid (ie non-expired),
    * <code>false</code> if no longer valid (ie expired)
    */
    boolean isCredentialsNonExpired();

    /**
    * Indicates whether the user is enabled or disabled. A disabled user cannot be
    * authenticated.
    *
    * @return <code>true</code> if the user is enabled, <code>false</code> otherwise
    */
    boolean isEnabled();
    }
  • UserDetailsService 负责获取正确的用户信息,提供了几个实现类,也可以实现UserDetailsService接口来进行自定义

    1
    2
    3
    4
    public interface UserDetailsService {

    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    }

进行认证

UsernamePasswordAuthenticationFilter

对/login 的 POST 请求做拦截,校验表单中用户名,密码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}

String username = obtainUsername(request);
String password = obtainPassword(request);

if (username == null) {
username = "";
}

if (password == null) {
password = "";
}

username = username.trim();
// 用户名和密码被过滤器获取到,封装成 Authentication,通常情况下是 UsernamePasswordAuthenticationToken这个实现类
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
username, password);

// Allow subclasses to set the "details" property
setDetails(request, authRequest);
// AuthenticationManager 身份管理器负责验证这个 Authentication
return this.getAuthenticationManager().authenticate(authRequest);
}
1
2
3
4
5
# 配置用户名,密码
security:
user:
name: admin
password: admin

其中的用户名密码都是spring security生成或者配置的,但是在实际使用中用户名和密码都是从数据库去进行读取的,所以这段逻辑需要进行自定义,如果需要自定义逻辑时,需要实现 UserDetailsService 接口

1
2
3
4
public interface UserDetailsService {

UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

欢迎关注我的其它发布渠道