寫在前面
在上一篇文章《shiro認證流程原始碼分析--練氣初期》當中,我們簡單分析了一下shiro的認證流程。不難發現,如果我們需要使用其他資料來源的資訊完成認證操作,我們需要自定義Realm繼承AuthorizingRealm類,並實現兩個方法,分別對應授權和認證。
在這一篇文章當中,我們將介紹如何自定義Realm物件,完成認證資訊資料來源的切換。
自定義Reaml
/**自定義Realm物件
* @author 賴柄灃 bingfengdev@aliyun.com
* @version 1.0
* @date 2020/10/4 11:00
*/
public class MySqlRealm extends AuthorizingRealm {
/**授權,今天暫不實現
* @author 賴柄灃 bingfengdev@aliyun.com
* @date 2020-10-04 11:01:50
* @param principalCollection
* @return org.apache.shiro.authz.AuthorizationInfo
* @throws AuthenticationException
* @version 1.0
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
/**認證
* @author 賴柄灃 bingfengdev@aliyun.com
* @date 2020-10-04 11:01:50
* @param authenticationToken
* @return org.apache.shiro.authz.AuthorizationInfo
* @throws AuthenticationException
* @version 1.0
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 1. 從token中獲取使用者名稱
String principal = (String) authenticationToken.getPrincipal();
//2. 根據使用者名稱查詢資料庫(模擬)
if (principal == "xiangbei") {
AuthenticationInfo authInfo = new SimpleAuthenticationInfo("xiangbei","123",this.getName());
return authInfo;
}
return null;
}
}
在認證器中使用自定義Realm進行認證
/**認證管理器
* @author 賴柄灃 bingfengdev@aliyun.com
* @version 1.0
* @date 2020/10/4 11:11
*/
public class CurrentSystemAuthenticator {
private DefaultSecurityManager securityManager;
public CurrentSystemAuthenticator() {
//建立安全管理器
securityManager = new DefaultSecurityManager();
//設定自定義realm
this.securityManager.setRealm(new MySqlRealm());
//將安全管理器設定到安全工具類中
SecurityUtils.setSecurityManager(securityManager);
}
public void authenticate(String username,String password){
//獲取當前登入主題
Subject subject = SecurityUtils.getSubject();
//生成toeken
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//進行認證
try {
subject.login(token);
}catch (UnknownAccountException | IncorrectCredentialsException e) {
System.out.println("使用者名稱或密碼不正確");
}
//列印認證狀態
if (subject.isAuthenticated()){
System.out.println(token.getPrincipal()+" 認證通過!");
}else {
System.out.println(token.getPrincipal()+" 認證未通過!");
}
}
}
進行測試
認證通過的情況
用例程式碼
/**測試認證
* @author 賴柄灃 bingfengdev@aliyun.com
* @version 1.0
* @date 2020/9/21 0:49
*/
public class TestAuthenticator {
private Authenticator authenticator=null;
@Before
public void init() {
authenticator = new Authenticator();
}
@Test
public void testAuth(){
authenticator.authenticate("xiangbei","123");
}
}
輸出
xiangbei 認證通過!
認證不通過的情況
認證不通過的情況在shiro當中分為幾種情況,具體可以檢視我的上一篇文章《shiro認證流程原始碼分析--練氣初期》 關於shiro認證異常的分析,常用的有如下幾種:
- 賬戶不正確(不存在)
- 密碼錯誤
- 賬戶被鎖定
- 密碼過期
在實際專案中為了安全起見,賬戶不正確和密碼錯誤統一返回“使用者名稱或密碼不正確”類似的的提示,避免造成賬戶洩露。
下面針對這種情況給予演示
用例程式碼
/**
* @author 賴柄灃 bingfengdev@aliyun.com
* @version 1.0
* @date 2020/10/4 11:20
*/
public class AuthcTest {
private CurrentSystemAuthenticator authenticator;
@Before
public void init() {
this.authenticator = new CurrentSystemAuthenticator();
}
@Test
public void testAuthc(){
this.authenticator.authenticate("xiangbei","13");
}
}
輸出
使用者名稱或密碼不正確
xiangbei 認證未通過!
寫在最後
這一篇文章主要是帶領大家瞭解一下如何通過自定義Realm物件完成shiro認證資料來源的切換。對於MySQL的整合,我們將在後面的文章當中整合SpringBoot時介紹。
下一篇文章將簡單介紹shiro中的密碼加密以及如何配置使用。
本文所涉及的程式碼下載地址:https://github.com/code81192/art-demo/tree/master/shiro-authc-mysql