如果是多个Realm,ModularRealmAuthenticator将会根据认证策略来确定认证是否成功。
例如,如果只有一个Realm验证成功,而其他Realm验证失败,那么这次认证是否成功呢?如果大多数的Realm验证成功了,认证是否就认为成功呢?或者,一个Realm验证成功后,是否还需要判断其他Realm的结果?认证策略就是根据应用程序的需要对这些问题作出决断。
AuthenticationStrategy 是个无状态的组件,在认证过程中会进行4次调用。
1.在所有Realm被调用之前
2.在调用Realm的getAuthenticationInfo方法之前
3.在调用Realm的getAuthenticationInfo 方法之后
4.在所有Realm被调用之后
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;
}
认证策略的另外一项工作就是聚合所有Realm的结果信息封装至一个AuthenticationInfo实例中,并将此信息返回,以此作为Subject的身份信息。
Shiro有3中认证策略的具体实现
AuthenticationStrategy类:
AtLeastOneSuccessfulStrategy(默认)
只要一个或者多个Realm认证通过,则整体身份认证就会视为成功。
FirstSuccessfulStrategy
只有第一个验证通过,才会视为整体认证通过。其他的会被忽略。
AllSuccessfulStrategy
只有所有的Realm认证成功,才会被视为认证通过。
自定义策略:继承org.apache.shiro.authc.pam.AbstractAuthenticationStrategy。
Realm的顺序
Realm顺序对认证是有影响的。
默认顺序是按照定义的顺序,例如配置文件 中这样配置:
#自定义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<
那么将会按照 myRealm1,myRealm2 的顺序依次调用。
网友评论