使用shiro進行登入校驗;自定義realm的實現
在web中, 使用者輸入使用者名稱密碼登入,我們需要用這些資訊和已經註冊存在在資料庫中的賬戶資訊進行對比,判斷使用者名稱和密碼是否正確。
shiro提供了自定義realm的實現來進行處理對不同資料來源的校驗:
realm就是一個安全資料來源。可以將其看作為資料庫的另一層封裝,連線了應用和db
使用者提交的資料流到reaml中,reaml中存著資料庫中的賬戶資訊,因此進行對比。
1、首先呼叫Subject.login(token)進行登入,其會自動委託給Security Manager,呼叫之前必
須通過SecurityUtils. setSecurityManager()設定;
2、SecurityManager負責真正的身份驗證邏輯;它會委託給Authenticator進行身份驗證;
3、Authenticator才是真正的身份驗證者,Shiro API中核心的身份認證入口點,此處可以自
定義插入自己的實現;
4、Authenticator可能會委託給相應的AuthenticationStrategy進行多Realm身份驗證,預設
ModularRealmAuthenticator會呼叫AuthenticationStrategy進行多Realm身份驗證;
5、Authenticator 會把相應的token 傳入Realm,從Realm 獲取身份驗證資訊,如果沒有返
回/丟擲異常表示身份驗證失敗了。此處可以配置多個Realm,將按照相應的順序及策略進
行訪問。
自定義realm的實現:在獲取securityManager的時候初始化指定了ini配置檔案,配置檔案中指定讓shiro執行自定義的realm,而不是
最初的[users]的這種方式來獲取使用者名稱和密碼:
自定義realm時候配置檔案的寫法: realm名稱=realm實現類的全路徑,shiro反射拿到 ,設定securityManager.realms=$自定義reaml名
多個reaml實現的時候,繼續往下追加
類似:
realm1=.......
realm2=.......
realm3=.......
securityManager.realms=$realm1,$realm2,$realm3
#宣告一個realm myRealm1= com.gjj.test.shiro.RealmService #指定securityManager的realms實現,通過$name來指定realm securityManager.realms=$myRealm1
shiro的實現:
1.實現Realm介面:
2.配置 shiro_realm.inipackage com.gjj.test.shiro; import org.apache.shiro.authc.*; import org.apache.shiro.realm.Realm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 自定義realm的實現 * Created by guojiangjiang on 2016/6/5. */ public class RealmService implements Realm { private static final Logger logger = LoggerFactory.getLogger(RealmService.class); private static final String REAM_NAME = "OwnRealm"; /** * 返回一個唯一的realm名字 * * @return */ @Override public String getName() { return this.REAM_NAME; } /** * 判斷此realm是否支援此token * * @param authenticationToken * @return */ @Override public boolean supports(AuthenticationToken authenticationToken) { //是否支援使用者名稱登入的token return authenticationToken instanceof UsernamePasswordToken; } /** * 根據token獲取認證資訊 * * @param token 認證令牌 * @return * @throws AuthenticationException */ @Override public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String userName = String.valueOf(token.getPrincipal()); String passwd = String.valueOf(token.getCredentials()); int count = 0; if ("jack".equals(userName)) { count += 1; logger.info("使用者名稱正確:{}", userName); } else { throw new UnknownAccountException("使用者名稱錯誤!"); } if ("12345".equals(passwd)) { count += 1; logger.info("密碼正確:{}", passwd); } else { throw new IncorrectCredentialsException("密碼錯誤!!!"); } // 返回認證資訊的一個簡單實現,三個引數,使用者名稱,密碼,域name AuthenticationInfo info = new SimpleAuthenticationInfo(userName, passwd, this.REAM_NAME); return info; } }
#宣告一個realm myRealm1= com.gjj.test.shiro.RealmService #指定securityManager的realms實現,通過$name來指定realm securityManager.realms=$myRealm13.在程式碼中接收使用者提交的引數,配置realm:
package com.gjj.test.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Realm:域,Shiro 從從Realm獲取安全資料(如使用者、角色、許可權),就是說SecurityManager
* 要驗證使用者身份,那麼它需要從Realm獲取相應的使用者進行比較以確定使用者身份是否合法;
* 也需要從Realm得到使用者相應的角色/許可權進行驗證使用者是否能進行操作;可以把Realm看
* 成DataSource , 即安全資料來源。如我們之前的ini 配置方式將使用
* org.apache.shiro.realm.text.IniRealm。
* realm就類似於安全資料來源。
* <p/>
* Created by guojiangjiang on 2016/6/5.
*/
public class RealmTest {
private static final Logger logger = LoggerFactory.getLogger(RealmTest.class);
public static void main(String[] args) {
testRealm();
}
private static void testRealm() {
//1、獲取SecurityManager工廠,此處使用Ini配置檔案初始化SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro_ownRealm.ini");
//2、得到SecurityManager例項並繫結給SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及建立使用者名稱/密碼身份驗證Token(即使用者身份/憑證)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("jack", "12345");
try {
//4、登入,即身份驗證
subject.login(token);
} catch (AuthenticationException e) {
//5、身份驗證失敗
}
}
}