在上一篇中介绍了一下关于多个realm的配置,那么随之而来的疑问是,当我们配置好多个realm之后,当用户进行登录操作时,是同时满足所有realm才算认证成功还是说,只要有一个或者部分realm即可?这就涉及到了认证策略的问题。所以这里也说一下。
关于AuthenticationStategy:
- FirstSuccessfulStrategy:只要第一个realm验证成功即可,只返回第一个realm验证成功的信息,其他的忽略;
- AtLeastOneSuccessfulStrategy:至少有一个realm验证成功即可,和FirstSuccessfulStrategy不同的是,该策略将会返回所有验证成功的认证信息;
- AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有验证成功的信息,有一个失败,那么整个验证失败。
Shiro默认的验证策略是AtLeastOneSuccessfulStrategy。
AtLeastOneSuccessfuleStrategy
查看ModularRealmAuthenticator的源码,其中有一个doMultiRealmAuthentication(Collection< Realm > realms, AuthenticationToken token)方法:
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) {
//这是ModularRealmAuthenticator的一个属性
AuthenticationStrategy strategy = this.getAuthenticationStrategy();
AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
if (log.isTraceEnabled()) {
log.trace("Iterating through {} realms for PAM authentication", realms.size());
}
Iterator var5 = realms.iterator();
while(var5.hasNext()) {
Realm realm = (Realm)var5.next();
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 var11) {
t = var11;
if (log.isDebugEnabled()) {
String msg = "Realm [" + realm + "] threw an exception during a multi-realm authentication attempt:";
log.debug(msg, var11);
}
}
aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);
} else {
log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token);
}
}
strategy是ModularRealmAuthenticator的一个成员变量,即认证策略。我们可以在spring配置文件中更改相应的认证器bean属性,如下:
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
<property name="realms">
<list>
<ref bean="myrealm"/>
<ref bean="secondRealm"/>
</list>
</property>
<!-- 修改策略属性 -->
<property name="authenticationStrategy" ref="allSuccessfulStrategy"/>
</bean>
<!--给定一个策略bean -->
<bean id="allSuccessfulStrategy" class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"/>