如果是多個(gè)Realm,ModularRealmAuthenticator將會(huì)根據(jù)認(rèn)證策略來(lái)確定認(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)用程序的需要對(duì)這些問(wèn)題作出決斷。
AuthenticationStrategy 是個(gè)無(wú)狀態(tài)的組件氧苍,在認(rèn)證過(guò)程中會(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)證通過(guò),則整體身份認(rèn)證就會(huì)視為成功赡突。
FirstSuccessfulStrategy
只有第一個(gè)驗(yàn)證通過(guò)对扶,才會(huì)視為整體認(rèn)證通過(guò)。其他的會(huì)被忽略惭缰。
AllSuccessfulStrategy
只有所有的Realm認(rèn)證成功浪南,才會(huì)被視為認(rèn)證通過(guò)。
自定義策略:繼承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)用喷众。