通過shiro教程1我們發現僅僅將數據源信息定義在ini文件中與我們實際開發環境有很大不兼容,所以我們希望能夠自定義Realm。
自定義Realm的實現
創建自定義Realmjava類
創建一個java文件繼承AuthorizingRealm類,重寫兩個抽象方法
/**
* 自定義的Realm
* @author dengp
*
*/
public class MyRealm extends AuthorizingRealm{
/**
* 認證方法
* @param token
* 就是我們在測試代碼中 定義的UsernamePasswordToken對象
* 有我們保存的需要驗證的賬號密碼信息
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 獲取賬號信息
String principal = (String) token.getPrincipal();
// 正常邏輯此處應該根據賬號去數據庫中查詢,此處我們默認賬號為 root 密碼123456
// 驗證賬號
if(!"root".equals(principal)){
// 賬號錯誤
return null;
}
String pwd = "123456";
// 驗證密碼
AuthenticationInfo info = new SimpleAuthenticationInfo(principal, pwd,"myrealm");
return info;
}
/**
* 授權方法
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
}
}
方法名 | 說明 |
---|---|
doGetAuthenticationInfo | 完成賬號認證的方法 |
doGetAuthorizationInfo | 完成用戶授權的方法 |
配置ini.xml文件
[main]
#自定義 realm
customRealm=com.dpb.realm.MyRealm
#將realm設置到securityManager
securityManager.realms=$customRealm
測試
測試代碼和上個案例一模一樣
@Test
public void test() {
// 1.獲取SecurityManager工廠對象
Factory<SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro.ini");
// 2.通過Factory對象獲取SecurityManager對象
SecurityManager securityManager = factory.getInstance();
// 3.將SecurityManager對象添加到當前運行環境中
SecurityUtils.setSecurityManager(securityManager);
// 4.獲取Subject對象
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken("root1", "12345");
// 登錄操作
try {
subject.login(token);
} catch (UnknownAccountException e) {
System.out.println("賬號出錯...");
} catch(IncorrectCredentialsException e){
System.out.println("密碼出錯...");
}
// 獲取登錄的狀態
System.out.println(subject.isAuthenticated());
}
原理分析
為什么要繼承AuthorizingRealm?
上個教程中我們完整的分析了認證的流程
我們發現在認證的過程核心代碼是此:
核心方法是doGetAuthenticationInfo(token)
在Realm的結構中
AuthorizingRealm和AuthenticatingRealm都提供的有doGetAuthenticationInfo(token)的抽象方法。
但是AuthenticatingRealm中要重寫的抽象方法太多
而AuthorizingRealm只需要重寫兩個方法,且這兩個方法都是我們需要使用的。故選擇繼承AuthorizingRealm
自定義的Realm什么時候被調用的?
密碼驗證什么時候執行的?
注意:自定義Realm中只完成了賬號的認證。密碼認證還是在AuthenticatingRealm中完成的,只是我們在自定義Realm中完成了密碼的設置。