五、Spring Boot整合Spring Security之認證流程2

那你为何对我三笑留情發表於2024-10-14

二、概要說明

  1. 上文已詳細介紹了四、Spring Boot整合Spring Security之認證流程
  2. 本文則著重介紹使用者名稱密碼認證過濾器UsernamePasswordAuthenticationFilter的實現原理過程
  3. 認證管理器(authenticationManager)
  4. 認證提供者(AuthenticationProvider)
  5. 自定義配置使用者名稱密碼實現(UserDetailsService)

三、UsernamePasswordAuthenticationFilter

1、結構及作用

  1. 繼承AbstractAuthenticationProcessingFilter
    1. 初始化請求地址
    2. 初始化authenticationManager
    3. 初始化successHandler
    4. 初始化failureHandler
    5. 實現過濾器入口doFilter方法
    6. doFilter方法呼叫抽象方法attemptAuthentication,attemptAuthentication供子類實現完成使用者名稱密碼驗證業務
    7. 認證成功時更新安全上下文,並呼叫successHandler.onAuthenticationSuccess
    8. 認證失敗時刪除安全上下文,並呼叫failureHandler.onAuthenticationFailure
  2. 實現attemptAuthentication方法
    1. 從請求中獲取使用者名稱密碼
    2. 生成未認證的Authentication
    3. 呼叫authenticationManager的authenticate方法完成使用者名稱密碼驗證

UsernamePasswordAuthenticationFilter

四、認證管理器(AuthenticationManager)

1、作用

  1. 完成Authentication的認證

2、ProviderManager(預設實現)

  1. ProviderManager實現AuthenticationManager介面
  2. AuthenticationManager的作用的是完成Authentication的認證
  3. 但是ProviderManager並未直接完成Authentication的認證
  4. 而是提供一個AuthenticationProvider集合
  5. 遍歷AuthenticationProvider集合來完成Authentication的認證
  6. 當需要多種認證方式時,可以註冊自定義的AuthenticationProvider,後續介紹註冊方式

AuthenticationManager

五、AuthenticationProvider

1、作用

  • 呼叫介面獲取使用者資訊UserDetails
  • 驗證使用者及密碼是否可用

2、DaoAuthenticationProvider(預設實現)

  1. DaoAuthenticationProvider繼承AbstractUserDetailsAuthenticationProvider實現AuthenticationProvider介面
  2. 呼叫retrieveUser方法獲取使用者資訊UserDetails
    1. 呼叫userDetailsService.loadUserByUsername獲取使用者資訊UserDetails
  3. 驗證使用者是否存在並可用,不存在或者不可用時拋異常(過期、鎖定、啟用)
  4. 驗證密碼是否可用,不可用時拋異常(為空、過期)
  5. 使用密碼加密器校驗密碼(介面輸入的密碼和資料庫已加密的密碼)
  6. 密碼不一致時拋異常

AuthenticationProvider

六、UserDetailsService

1、作用

  • 透過使用者名稱username獲取使用者資訊UserDetails
  • 返回使用者資訊UserDetails

2、InMemoryUserDetailsManager(預設實現)

  1. 專案啟動時會預設生成一個使用者名稱密碼,存在記憶體中
  2. 透過使用者名稱獲取該使用者並返回

3、推薦實現:自定義UserDetailsService

  1. 透過使用者名稱從資料庫中獲取到使用者
  2. 資料庫使用者轉為UserDetails,資料庫中未設定的屬性像是否啟用、賬號未過期、密碼未過期、賬號未鎖定直接設定為true即可
package com.yu.demo.service.impl;

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

   //@Autowired
   //private UserService userService;

   @Override
   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      //TODO 透過username從資料庫中獲取使用者,將使用者轉UserDetails
      //User user = userService.getByUsername(username);
      //return new User(username, user.getPassword(), user.getEnable(), user.getAccountNonExpired(), user.getCredentialsNonExpired(), user.getAccountNonLocked(), user.getAuthorities());
      //{noop}不使用密碼加密器,密碼123的都可以驗證成功
      return new User(username, "{noop}123", true, true, true, true, AuthorityUtils.NO_AUTHORITIES);
   }
}

UserDetailsServiceImpl

相關文章