SpringSecurity(四): 動態認證用戶信息UserDetailsService


SpringSecurity(一、二、三)身份認證的用戶名和密碼是啟動服務器自動生成的,或者是代碼中寫死的,存儲在內存中。而實際項目中應該從動態的從數據庫中獲取進行身份認證。
 
1.實現流程:  
  (1)關注 UserDetailsService 、 UserDetails 接口
  (2)自定義一個 UserDetailsService 接口的實現類 CustomUserDetailsService ,實現該接口中的loadUserByUsername 方法 ,通過該方法定義獲取用戶信息的邏輯。
  (3) 從數據庫獲取到的用戶信息封裝到 UserDetail 接口的實現類中(Spring Security 提供了一個org.springframework.security.core.userdetails.User 實現類封裝用戶信息)。
  (4)如果未獲取到用戶信息,則拋出異常 throws UsernameNotFoundException
public interface UserDetails extends Serializable { 
  //此用戶可訪問的資源權限
  Collection<? extends GrantedAuthority> getAuthorities();
  //用戶名
  String getPassword();
  //密碼
  String getUsername();
  //帳戶是否過期(true 未過期,false 已過期)   boolean isAccountNonExpired();
  //帳戶是否被鎖定(true 未鎖定,false 已鎖定),鎖定的用戶是可以恢復的   boolean isAccountNonLocked();
  //密碼是否過期(安全級別比較高的系統,如30天要求更改密碼,true 未過期,false 過期)   boolean isCredentialsNonExpired();
  //帳戶是否可用(一般指定是否刪除,系統一般不會真正的刪除用戶信息,而是假刪除,通過一個狀態碼標志 用戶被刪除)刪除的用戶是可以恢復的   
boolean isEnabled();
}

2.自定義CustomUserDetailsService類實現UserDetailsService接口

/**
 * 查詢數據庫中的用戶信息
 */
@Component("CustomUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
   Logger logger=LoggerFactory.getLogger(CustomUserDetailsService.class);

   @Autowired
    BCryptPasswordEncoder bCryptPasswordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
       logger.info("請求認證的用戶名:"+username);

       //1.通過請求的用戶名去數據庫中查詢用戶信息
        if (!"zcc".equals(username)){
            throw new UsernameNotFoundException("用戶名或密碼錯誤");
        }

        //假設當前這個用戶在數據庫中存儲的密碼是123
        String password=bCryptPasswordEncoder.encode("123");

        //2.查詢該用戶所擁有的權限
        

        // 3.封裝用戶信息: username用戶名,password數據庫中的密碼,authorities資源權限標識符
        // SpringSecurity 底層會校驗是否身份合法。
        return  new User(username,password, AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN"));

    }
}

3.重構安全配置類SpringSecurityConfig

  注入 CustomUserDetailsService  在confifigure(AuthenticationManagerBuilder auth) 方法中指定認證方式
   @Autowired
    CustomUserDetailsService customUserDetailsService;


    /**
     * 認證管理器:
     * 1、認證信息提供方式(用戶名、密碼、當前用戶的資源權限)
     * 2、可采用內存存儲方式,也可能采用數據庫方式等
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //基於內存存儲認證信息 存儲的密碼必須是加密后的 不然會報錯:There is no PasswordEncoder mapped for the id "null"
        //auth.inMemoryAuthentication().withUser("zcc").password("123").authorities("ADMIN");
        /*String password = bCryptPasswordEncoder().encode("123");
        logger.info("加密后的密碼:" + password);
        auth.inMemoryAuthentication().withUser("zcc").password(password).authorities("ADMIN");*/


        // 指定使用自定義查詢用戶信息來完成身份認證
        auth.userDetailsService(customUserDetailsService);

    }

 完整代碼地址:https://gitee.com/zhechaochao/security-parent.git

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM