如果是多個(gè)Realm,ModularRealmAuthenticator將會(huì)根據(jù)認(rèn)證策略來確定認(rèn)證是否成功。
例如,如果只有一個(gè)Realm驗(yàn)證成功,而其他Realm驗(yàn)證失敗,那么這次認(rèn)證是否成功呢?如果大多數(shù)的Realm驗(yàn)證成功了,認(rèn)證是否就認(rèn)為成功呢?或者,一個(gè)Realm驗(yàn)證成功后,是否還需要判斷其他Realm的結(jié)果?認(rèn)證策略就是根據(jù)應(yīng)用程序的需要對這些問題作出決斷。
AuthenticationStrategy 是個(gè)無狀態(tài)的組件,在認(rèn)證過程中會(huì)進(jìn)行4次調(diào)用。
1.在所有Realm被調(diào)用之前
2.在調(diào)用Realm的getAuthenticationInfo方法之前
3.在調(diào)用Realm的getAuthenticationInfo 方法之后
4.在所有Realm被調(diào)用之后
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
AuthenticationStrategy strategy = getAuthenticationStrategy();
//1*
AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
if (log.isTraceEnabled()) {
log.trace("Iterating through {} realms for PAM authentication", realms.size());
}
for (Realm realm : realms) {
//2*
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);
}
}
//3*
aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);
} else {
log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token);
}
}
//4*
aggregate = strategy.afterAllAttempts(token, aggregate);
return aggregate;
}
認(rèn)證策略的另外一項(xiàng)工作就是聚合所有Realm的結(jié)果信息封裝至一個(gè)AuthenticationInfo實(shí)例中,并將此信息返回,以此作為Subject的身份信息。
Shiro有3中認(rèn)證策略的具體實(shí)現(xiàn)
AuthenticationStrategy類:
AtLeastOneSuccessfulStrategy(默認(rèn))
只要一個(gè)或者多個(gè)Realm認(rèn)證通過,則整體身份認(rèn)證就會(huì)視為成功。
FirstSuccessfulStrategy
只有第一個(gè)驗(yàn)證通過,才會(huì)視為整體認(rèn)證通過。其他的會(huì)被忽略。
AllSuccessfulStrategy
只有所有的Realm認(rèn)證成功,才會(huì)被視為認(rèn)證通過。
自定義策略:繼承org.apache.shiro.authc.pam.AbstractAuthenticationStrategy。
Realm的順序
Realm順序?qū)φJ(rèn)證是有影響的。
默認(rèn)順序是按照定義的順序,例如配置文件 中這樣配置:
#自定義realm
myRealm1 = com.api6.shiro.demo1.Realm.UserRealm1
myRealm2 = com.api6.shiro.demo1.Realm.UserRealm2
#指定realm的順序
securityManager.realms = $myRealm1,$myRealm2
#策略
#authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy
#authcStrategy = org.apache.shiro.authc.pam.AllSuccessfulStrategy
authcStrategy = org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
securityManager.authenticator.authenticationStrategy = $authcStrategy<
那么將會(huì)按照 myRealm1,myRealm2 的順序依次調(diào)用。