SpringSecurity user authentication process analysis principles

1. The user authentication process flow principle

Here Insert Picture Description

1.1 AuthenticationFilter

  1. According to intercept chain model, a different login have different AuthenticationFilter
  2. If the account password used to log, will be UsernamePasswordAuthenticationFilterto intercept
  3. By UsernamePasswordAuthenticationFilterthe attemptAuthentication()method creates an UsernamePasswordAuthenticationTokenObject
  • UsernamePasswordAuthenticationFilter.java , account password filter
public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
    //1. 创建UsernamePasswordAuthenticationToken对象
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				username, password);
	//2. 接着进入AuthenticationManager管理器中选择对应的AuthenticationProvider验证器进行校验
		return this.getAuthenticationManager().authenticate(authRequest);
	}
  • UsernamePasswordAuthenticationToken.java , create objects
//构造器
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
		super(null);//未认证,将权限信息设置为null
		this.principal = principal;//将账号密码保存到本地
		this.credentials = credentials;//将权限信息保存到本地
		setAuthenticated(false);//认证状态为false
}

1.2 AuthenticationManager

  1. AuthenticationManagerResponsible for managing many of AuthenticationProviderthese Provider can provide different calibration procedures for different landing approach
  2. By acquiring ProvicerManagerand call its authenticate()methods through all the check mode provider to verify, get a validator to support the current login mode
  3. You will find the corresponding login by the Provider provider.authenticate(authentication);verifies the checksum way calling provider offers

1.3 AuthenticationProvider

  1. By way of example here, the account password, it will be used to achieve a AbstractUserDetailsAuthenticationProviderspecific implementation class DaoAuthenticationProviderto perform a checksum;
  2. Verification process calls AbstractUserDetailsAuthenticationProviderthe authenticatemethod
  3. Verification process is divided into three stages:
    1. preAuthenticationChecks.check(user);Pre-check, according to the four methods UserDetails interface, for the account is enabled, the account has expired, if the account lockout status check
    2. additionalAuthenticationChecks();,密码校验,该方法在是DaoAuthenticationProvider中进行了实现,通过我们配置的PasswordEncoder进行密码校验
    3. postAuthenticationChecks.check(user);,后校验,检验密码是否过期;
  4. 用户认证成功后,就会根据我们提供的UserDetails信息,执行createSuccessAuthentication(principalToReturn, authentication, user);方法;
  5. 创建了一个新的UsernamePasswordAuthenticationToken对象,并以Authentication的形式返回
  • UsernamePasswordAuthenticationToken.java
public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
			Collection<? extends GrantedAuthority> authorities) {
    super(authorities);//保存用户权限信息
    this.principal = principal;
    this.credentials = credentials;
    super.setAuthenticated(true); // 认证成功
}

1.4 返回AuthenticationFilter处理登录结果

  1. Authentication保存最终认证成功的用户认证对象,该对象将返回到最开始的拦截器当中
  2. 最终返回拦截器链中的AbstractAuthenticationProcessingFilter,执行该过滤器的doFilter方法
  3. 在doFilter中,执行successfulAuthentication(request, response, chain, authResult);来执行登录成功的处理器,
  4. successHandler.onAuthenticationSuccess(request, response, authResult);登录成功处理器执行登陆成功的业务逻辑;
  5. 如果在这个认证过程中出现失败都会抛出异常并被过滤器捕获,执行登录失败处理器

2.在多个请求中共享认证结果原理

Here Insert Picture Description

  1. 在用户认证流程过程中,若认证成功的认证信息最后会传回到认证拦截器链当中,并在doFilter中执行successfulAuthentication(request, response, chain, authResult);,去调用我们自定义的认证成功处理器,在调用认证成功处理器之前有一句代码是将用户信息传入SecurityContext
  2. SecurityContextHolder.getContext().setAuthentication(authResult);
  3. SecurityContext是用来包装Authentication对象而已
  4. SecurityContextHodler来获取容器保存用户认证信息,这里的SercurityContextHolder可以视为一个线程级别的变量对象,可被多个线程所共享;、
  5. 在拦截器链的最开始,有一个拦截器叫SecurityContextPersistenceFilter,它的作用有两个
    1. When a request comes in : the Session check, to determine whether there SecurityContext session (i.e. there is no user authentication information), if it will be out, put the request thread;
    2. When the request is complete ** Returns: Are there SecurityContext ** Check the thread, the authentication information into the session

Here Insert Picture Description

3. Obtain user authentication information

  1. method one:SecurityContextHolder.getContext().getAuthentication()
  2. Method 2: In the parameters of the controller, the type declaration Authentication, SPRINGMVC us to automatically inject user authentication information;
  • For a complete authentication information
@GetMapping("/authentication")
public Authentication getUser(Authentication authentication){
    return authentication;
}
  • Users only get basic information
@GetMapping("/userDetail")
public UserDetails getUser(@AuthenticationPrincipal  UserDetails userDetails){
    return userDetails;
}
Released five original articles · won praise 0 · Views 209

Guess you like

Origin blog.csdn.net/drama_CJL/article/details/104237856