Spring Security(三):用戶自定義認證邏輯

上一篇進行了最簡單的Spring Security的初始搭建,像用戶名和密碼都是固定的,這篇就來講講自定義用戶認證邏輯的實現,包括用戶信息的獲取,用戶密碼的校驗以及用戶密碼的加密校驗。

處理用戶信息獲取邏輯

源碼

  • 用戶信息的獲取邏輯被封裝在UserDetailsService接口中,接口源碼:
public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
  • 作用:根據用戶前端輸入的用戶名,會到存儲去讀取用戶信息封裝到返回值UserDetails中,如果通過輸入的用戶名沒法找到數據庫中數據,則會拋出一個UsernameNotFoundException異常。

實操

  • 我們可以創建自己的一個MyUserDetailsService,實現上面的接口,在loadUserByUsername方法中進行一個數據庫用戶信息的查詢返回。
@Component
public class MyUserDetailsService implements UserDetailsService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyUserDetailsService.class);

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LOGGER.info("登錄名:" + username);
        // balabala,根據用戶名查找用戶密碼等信息返回(記得實際開發中是查庫得到的),第三個參數是用戶授權,後面再來詳細講
        return new User(username, "123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}
  • 效果:任意用戶名,密碼是123456才能進行登錄(假裝上面的密碼是數據庫中查到的!)
    用戶登錄

處理用戶校驗邏輯

源碼

  • UserDetails接口解析,該接口用於返回用戶信息。
public interface UserDetails extends Serializable {
    /**
     * 用戶授權
     */
    Collection<? extends GrantedAuthority> getAuthorities();
    /**
     * 用戶密碼
     */
    String getPassword();
    /**
     * 用戶名
     */
    String getUsername();
    /**
     * 以下四個方法可以自定義校驗邏輯,返回賬戶是否過期,true表示沒有過期
     */
    boolean isAccountNonExpired();
    /**
     * 賬戶是否被鎖定或者凍結(一般可恢復),true表示沒被凍結
     */
    boolean isAccountNonLocked();
    /**
     * 密碼是否過期,true表示沒有過期,可能有的網站需求密碼需要30天更換等
     */
    boolean isCredentialsNonExpired();
    /**
     * 賬戶是否可用或者是否被刪(一般不可恢復),true表示可用
     */
    boolean isEnabled();
}

實操

  • 演示:以上四個boolean類型的方法只要有一個不爲true都不能夠通過登錄校驗
@Component
public class MyUserDetailsService implements UserDetailsService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyUserDetailsService.class);

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LOGGER.info("登錄名:" + username);
        // balabala,根據用戶名查找用戶密碼等信息返回,第三個參數是用戶授權,後面再來詳細講
        return new User(username, "123456",
                true, true, true, false,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

演示

處理密碼加密解碼

源碼

  • PasswordEncoder接口解析,該接口用於密碼的加密解密
public interface PasswordEncoder {
    /**
     * 密碼加密,在註冊的時候,密碼插入數據庫之前需要你手動調用進行一個加密操作
     */
    String encode(CharSequence var1);
    /**
     * 判斷加密的密碼和用戶傳過來的密碼是否匹配,該方法由security調用,匹配上了返回true,否則返回false
     */
    boolean matches(CharSequence var1, String var2);
}

實操

  1. 配置上面接口的一個實例Bean。
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
  1. 記得我們的密碼是被加密的,所以數據庫中的密碼應該是被加密過的。
public class MyUserDetailsService implements UserDetailsService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyUserDetailsService.class);
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LOGGER.info("登錄名:" + username);
        // balabala,根據用戶名查找用戶密碼等信息返回,第三個參數是用戶授權,後面再來詳細講
        String password = passwordEncoder.encode("123456");
        return new User(username, password,
                true, true, true, false,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}
  1. 演示,結果就是輸入正確密碼才能登陸,這裏我們發現對同一個密碼加密後的密文是不一樣的,這是BCryptPasswordEncoder提供的加密方式,當然你可以自己實現加密,比如MD5加密方式等。
    演示

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章