七厌小、ModularRealmAuthenticator 的源碼分析和配置

                       ModularRealmAuthenticator 的源碼分析和配置

SecurityManager得到token信息后闲礼,通過調(diào)用authenticator.authenticate(token)方法,把身份驗證委托給內(nèi)置的Authenticator的實例進(jìn)行驗證砂心。authenticator通常是ModularRealmAuthenticator
實例,支持對一個或多個Realm實例進(jìn)行適配蛇耀。ModularRealmAuthenticator提供了一種可插拔的認(rèn)證風(fēng)格辩诞,你可以在此處插入自定義Realm實現(xiàn)。

如果配置了多個Realm纺涤,ModularRealmAuthenticator會根據(jù)配置的AuthenticationStrategy(身份驗證策略)進(jìn)行多Realm認(rèn)證過程译暂。
注:如果應(yīng)用程序中僅配置了一個Realm抠忘,Realm將被直接調(diào)用而無需再配置認(rèn)證策略。

判斷每個Realm是否支持提交的token外永,如果支持Realm就會調(diào)用getAuthenticationInfo(token)方法進(jìn)行認(rèn)證處理崎脉。
AuthenticationStrategy(身份驗證策略)會在后邊講解

在這里插入圖片描述
public abstract class AbstractAuthenticator implements Authenticator, LogoutAware {
 
public final AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {

    if (token == null) {
        throw new IllegalArgumentException("Method argument (authentication token) cannot be null.");
    }

    log.trace("Authentication attempt received for token [{}]", token);

    AuthenticationInfo info;
    try {
    *// 調(diào)用 ModularRealmAuthenticator。 doAuthenticate(token) 方法*
        info = doAuthenticate(token);
        if (info == null) {
            String msg = "No account information found for authentication token [" + token + "] by this " +
                    "Authenticator instance.  Please check that it is configured correctly.";
            throw new AuthenticationException(msg);
        }
    } catch (Throwable t) {
        AuthenticationException ae = null;
        if (t instanceof AuthenticationException) {
            ae = (AuthenticationException) t;
        }
        if (ae == null) {
            //Exception thrown was not an expected AuthenticationException.  Therefore it is probably a little more
            //severe or unexpected.  So, wrap in an AuthenticationException, log to warn, and propagate:
            String msg = "Authentication failed for token submission [" + token + "].  Possible unexpected " +
                    "error? (Typical or expected login exceptions should extend from AuthenticationException).";
            ae = new AuthenticationException(msg, t);
            if (log.isWarnEnabled())
                log.warn(msg, t);
        }
        try {
            notifyFailure(token, ae);
        } catch (Throwable t2) {
            if (log.isWarnEnabled()) {
                String msg = "Unable to send notification for failed authentication attempt - listener error?.  " +
                        "Please check your AuthenticationListener implementation(s).  Logging sending exception " +
                        "and propagating original AuthenticationException instead...";
                log.warn(msg, t2);
            }
        }


        throw ae;
    }

    log.debug("Authentication successful for token [{}].  Returned account [{}]", token, info);

    notifySuccess(token, info);

    return info;
}
 
protected abstract AuthenticationInfo doAuthenticate(AuthenticationToken token)
        throws AuthenticationException;
 
 
 
}

ModularRealmAuthenticator 源碼分析

public class ModularRealmAuthenticator extends AbstractAuthenticator {
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
    assertRealmsConfigured();
    Collection<Realm> realms = getRealms();
    if (realms.size() == 1) {
        return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);
    } else {
        return doMultiRealmAuthentication(realms, authenticationToken);
    }
}
}
在這里插入圖片描述
①當(dāng)realm==1的時候
public class ModularRealmAuthenticator extends AbstractAuthenticator {
 
protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) {
    if (!realm.supports(token)) {
        String msg = "Realm [" + realm + "] does not support authentication token [" +
                token + "].  Please ensure that the appropriate Realm implementation is " +
                "configured correctly or that the realm accepts AuthenticationTokens of this type.";
        throw new UnsupportedTokenException(msg);
    }
    // 去調(diào)用自定義realm 中的認(rèn)證方法
    AuthenticationInfo info = realm.getAuthenticationInfo(token);
    if (info == null) {
        String msg = "Realm [" + realm + "] was unable to find account data for the " +
                "submitted AuthenticationToken [" + token + "].";
        throw new UnknownAccountException(msg);
    }
    return info;
}
 }

當(dāng)realm個數(shù)大于1 的時候 realms!=1 這里會涉及到>AuthenticationStrategy(身份驗證策略
根據(jù)策略進(jìn)行認(rèn)證結(jié)果

public class ModularRealmAuthenticator extends AbstractAuthenticator {
 
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
// 獲得認(rèn)證策略
    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;
}
 }

// 去調(diào)用自定義realm 中的認(rèn)證方法
AuthenticationInfo info = realm.getAuthenticationInfo(token);
多realm 就是for循環(huán)調(diào)用 getAuthenticationInfo(token);

public class MyRealm extends AuthorizingRealm {
//public class MyRealm extends AuthenticatingRealm {
 
 
/**
 * 認(rèn)證
 *
 * @param token
 * @return
 * @throws AuthenticationException
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
    String username = usernamePasswordToken.getUsername();
    String password = String.valueOf(usernamePasswordToken.getPassword());

    ByteSource solt = ByteSource.Util.bytes(username);

    if (username.equals("username") && password.equals("password")) {
        return new SimpleAuthenticationInfo(username, password, getName());
    }
    return null;
}
}

進(jìn)行密碼比較

 public abstract class AuthenticatingRealm extends CachingRealm implements Initializable {
 
protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
    CredentialsMatcher cm = getCredentialsMatcher();
    if (cm != null) {
        if (!cm.doCredentialsMatch(token, info)) {
            //not successful - throw an exception to indicate this:
            String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
            throw new IncorrectCredentialsException(msg);
        }
    } else {
        throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " +
                "credentials during authentication.  If you do not wish for credentials to be examined, you " +
                "can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
    }
}
 
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末伯顶,一起剝皮案震驚了整個濱河市囚灼,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌祭衩,老刑警劉巖灶体,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異掐暮,居然都是意外死亡蝎抽,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門路克,熙熙樓的掌柜王于貴愁眉苦臉地迎上來樟结,“玉大人,你說我怎么就攤上這事衷戈∠梁穑” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵殖妇,是天一觀的道長刁笙。 經(jīng)常有香客問我,道長谦趣,這世上最難降的妖魔是什么疲吸? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮前鹅,結(jié)果婚禮上摘悴,老公的妹妹穿的比我還像新娘。我一直安慰自己舰绘,他們只是感情好蹂喻,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捂寿,像睡著了一般口四。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秦陋,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天蔓彩,我揣著相機與錄音,去河邊找鬼。 笑死赤嚼,一個胖子當(dāng)著我的面吹牛旷赖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播更卒,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼等孵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了逞壁?” 一聲冷哼從身側(cè)響起流济,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎腌闯,沒想到半個月后绳瘟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡姿骏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年糖声,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片分瘦。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡蘸泻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嘲玫,到底是詐尸還是另有隱情悦施,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布去团,位于F島的核電站抡诞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏土陪。R本人自食惡果不足惜昼汗,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鬼雀。 院中可真熱鬧顷窒,春花似錦、人聲如沸源哩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽励烦。三九已至谓着,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崩侠,已是汗流浹背漆魔。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留却音,地道東北人改抡。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像系瓢,于是被迫代替她去往敵國和親阿纤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容