国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Shiro

2019-11-14 22:03:01
字體:
來源:轉載
供稿:網友
Shiro - 認證

認證是Shiro最基本的工作!

先從代碼開始,運行后再慢慢研究。 以下是我添加的dependecies:

<!-- shiro --><dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-core</artifactId>    <version>${shiro.version}</version></dependency><dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-sPRing</artifactId>    <version>${shiro.version}</version></dependency><dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-web</artifactId>    <version>${shiro.version}</version></dependency>

在資源目錄下創建shiro.ini,文件內容為:

[users]king=t;stmdtkg

寫一個main方法:package pac.testcase.shiro;

import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.ExcessiveAttemptsException;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePassWordToken;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;public class TestAuthen {    public static void main(String[] args) {        Factory<SecurityManager> factory = new IniSecurityManagerFactory();        SecurityManager manager = factory.getInstance();        SecurityUtils.setSecurityManager(manager);        UsernamePasswordToken token = new UsernamePasswordToken("king", "t;stmdtkg");        token.setRememberMe(true);        Subject currentUser = SecurityUtils.getSubject();        try {            currentUser.login(token);        } catch ( UnknownAccountException e ) {             System.out.println("你是誰?");        } catch ( IncorrectCredentialsException e ) {            System.out.println("密碼錯誤!!");        } catch ( LockedAccountException e ) {            System.out.println("該賬戶不可用~");        } catch ( ExcessiveAttemptsException e ) {            System.out.println("別再試了!!");        }        currentUser.logout();    }}

代碼非常好懂。 如果IniSecurityManagerFactory沒有指定配置文件,則

DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini"。

另外,SecurityUtils.setSecurityManager(manager);該方法是一個全局設置,設置整個VM單例的SecurityManager,一般開發中很少用到該方法。

另外,Shiro提供了豐富的Exception,我們可以根據不同的catch響應不同的提示。

關于身份驗證,有兩個重要的概念需要解釋:

  • Principals:身份(暫且這樣翻譯吧),Subject的唯一標識,可以是任何東西,比如用戶名或者e-mail地址。
  • Credentials:憑證,用于證明身份的東西,可以簡單理解為密碼。

一些類和方法的命名中如果出現這些詞匯不至于太陌生。

記錄一下身份驗證的具體步驟,用5個步驟簡單概括一下:

Step 1.

將代表用戶身份和憑證的token對象作為參數調用login方法。

Step 2.

在上面的代碼中Subject對象實際上是作為一個用于委派(delegate)任務的對象——DelegatingSubject,以調用login(token)將驗證的任務委托給SecurityManager。SecurityManager調用

Subject login(Subject subject, AuthenticationToken authenticationToken)

這里是驗證真正開始的地方。

Step 3.

SecurityManager作為一個'umbrella'組件(這個比喻很流行嗎...),接收token并將任務委托給內部的 Authenticator(ps:SecurityManager extends Authenticator, Authorizer, sessionManager)并調用

public AuthenticationInfo authenticate(AuthenticationToken authenticationToken)        throws AuthenticationException;

通常情況下,這個authenticator是ModularRealmAuthenticator,ModularRealmAuthenticator可以在驗證時與多個realm進行交流(ModularRealmAuthenticator實現AuthenticationInfo doAuthenticate(AuthenticationToken token),上級AbstractAuthenticator在authenticate(token)中調用doAuthenticate(token))。

Step 4.

如果配置了多個Realm,ModularRealmAuthenticator會用配置的驗證策略(AuthenticationStrategy)去進行多Realm驗證。

驗證策略與每一個Realm的結果交互。

如果只配置了一個Realm,驗證策略則沒有任何意義。

Step 5.

調用Realm的boolean supports(AuthenticationToken token)確認Realm是否支持提交過來的token。

如果Realm支持提交過來的token,token將作為參數并調用:

AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;

根據不同的token響應特定的驗證信息(AuthenticationInfo)。

當一個應用配置了多個Realm,ModularRealmAuthenticator通過其內部的AuthenticationStrategy去定義驗證策略(好像說了句廢話....命名確實很棒...)。

舉個例子: 如果一個Realm成功驗證了一個token,而其他的Realm全部失敗了,此時我們應該如何認定驗證是成功還是失敗?

是全部通過才算成功?還是說其中一個通過即可?或者說其中特定幾個通過后是否有必要繼續考慮其他?

接下來,試著用代碼體驗 multi-RealmAuthenticationStrategy

Step 1.

實現org.apache.shiro.realm.Realm來自定義幾個Realm。

在getAuthenticationInfo方法中直接返回驗證信息根本看不出驗證策略是否生效,于是我在一個Realm里拋出一個異常。

package pac.testcase.shiro.realm;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.realm.Realm;public class MyRealm1 implements Realm {    public String getName() {        return this.getClass().getName();    }    public boolean supports(AuthenticationToken token) {        return true;    }    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)            throws AuthenticationException {        if(!new String((char[])token.getCredentials()).equals("t;stmdtkg"))            throw new IncorrectCredentialsException();        return new SimpleAuthenticationInfo(token.getPrincipal(),token.getCredentials(),this.getName());    }}
Step 2.

繼續使用本文開始時的代碼,將自定義的幾個Realm配置到shiro.ini中。

realm0=pac.testcase.shiro.realm.MyRealm0realm1=pac.testcase.shiro.realm.MyRealm1
Step 3.

在shiro.ini中配置驗證策略。

realm0=pac.testcase.shiro.realm.MyRealm0realm1=pac.testcase.shiro.realm.MyRealm1authcStrategy = org.apache.shiro.authc.pam.AllSuccessfulStrategysecurityManager.authenticator.authenticationStrategy = $authcStrategy
Step 4.

運行程序,輸出"密碼錯誤!!"

AuthenticationStrategy是無狀態的,處理一個驗證請求時AuthenticationStrategy會一共交互4次。

分別是:

  • 任何一個Realm執行之前。
  • 每個Realm的getAuthenticationInfo方法被調用之前。
  • 每個Realm的getAuthenticationInfo方法被調用之后。
  • 所有的Realm執行之后。

另外,從所有成功的Realm中聚集結果并將其綁定到一個AuthenticationInfo也是AuthenticationStrategy的工作。

這個最后聚集起來的驗證信息則是Shiro用來表示Subject的標志,也就是所謂Principal。

具體體現在org.apache.shiro.authc.pam.ModularRealmAuthenticator中:

protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {    AuthenticationStrategy strategy = getAuthenticationStrategy();    AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);    if (log.isTraceEnabled()) {        log.trace("Iterating through {} realms for PAM authentication", realms.size());    }    for (Realm realm : realms) {        aggregate = strategy.beforeAttempt(realm, token, aggregate);        if (realm.supports(token)) {            log.trace("Attempting to authenticate token [{}] using realm [{}]", token, realm);            AuthenticationInfo info = null;            Throwable t = null;            try {                info = realm.getAuthenticationInfo(token);            } catch (Throwable throwable) {                t = throwable;                if (log.isDebugEnabled()) {                    String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";                    log.debug(msg, t);                }            }            aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);        } else {            log.debug("Realm [{}] does not support token {}.  Skipping realm.", realm, token);        }    }    aggregate = strategy.afterAllAttempts(token, aggregate);    return aggregate;}

Shiro默認提供了三種AuthenticationStrategy實現:

  • AtLeastOneSuccessfulStrategy:其中一個通過則成功。
  • FirstSuccessfulStrategy:其中一個通過則成功,但只返回第一個通過的Realm提供的驗證信息。
  • AllSuccessfulStrategy:凡是配置到應用中的Realm都必須全部通過。

ModularRealmAuthenticator默認采用AtLeastOneSuccessfulStrategy,如果想用其他的驗證策略則需要自行配置。

需要指出的是ModularRealmAuthenticator是按照某種順序與每個Realm進行交互的。

ModularRealmAuthenticator訪問配置于SecurityManager的Realm。

當處理一個驗證請求時會迭代Realm集合,調用所有支持當前token的Realm。

如果使用ini配置則會按照配置的順序去執行。

如果想要顯示定義Realm的順序,則在securityManager的屬性中按喜歡的順序設置一下即可。

比如:

securityManager.realms=$myRealm2,$myRealm1

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 门源| 榆树市| 全椒县| 大厂| 卫辉市| 公安县| 宜兴市| 合作市| 茶陵县| 海门市| 汝城县| 镇巴县| 托克托县| 天台县| 衡山县| 鄱阳县| 富宁县| 东乌| 龙里县| 海门市| 朝阳县| 祥云县| 龙游县| 平定县| 金沙县| 丹凤县| 双桥区| 凤阳县| 双峰县| 阜新市| 卫辉市| 玉龙| 中山市| 勃利县| 瑞金市| 定陶县| 多伦县| 临西县| 平乐县| 太保市| 涞水县|