举个例子:
移动端有用户名密码、手机验证码、邮箱验证码与人脸识别等各种登陆方式。
自定义4个Realm时,需要设置认证策略(也可以认为是Realm的执行顺序)。
ModularRealmAuthenticator的AuthenticationStrategy的策略为
1. AtLeastOneSuccessfulStrategy :如果一个(或更多)Realm 验证成功,则整体的尝试被认为是成功的。如果没有一个验证成功,则整体尝试失败。
FirstSuccessfulStrategy 只有第一个成功地验证的Realm 返回的信息将被使用。后面的realm会被忽略,如果一个都没有成功则失败。
AllSucessfulStrategy 为了整体的尝试成功,所有配置的Realm 必须验证成功。如果没有一个验证成功,则整体尝试失败。
ModularRealmAuthenticator 默认的是AtLeastOneSuccessfulStrategy
查看shiro-core-1.6.0的源码
protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token)
{
AuthenticationStrategy strategy = getAuthenticationStrategy();
AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token);
if (log.isTraceEnabled()) {
log.trace("Iterating through {} realms for PAM authentication", Integer.valueOf(realms.size()));
}
for (Iterator localIterator = realms.iterator(); localIterator.hasNext(); ) { Realm realm = (Realm)localIterator.next();
try
{
aggregate = strategy.beforeAttempt(realm, token, aggregate);
}
catch (ShortCircuitIterationException shortCircuitSignal)
{
break label231:
}
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);
}
}
label231: aggregate = strategy.afterAllAttempts(token, aggregate);
return aggregate;
}
如上代码中有两种返回:
一种是异常,另外一种是 if (realm.supports(token))中的正常执行。
shirocofing中的设置
public AbstractAuthenticator abstractAuthenticator(UserRealm userRealm, PhoneAndVerificationCodeShiroRealm phoneShiroRealm){
// 自定义模块化认证器,用于解决多realm抛出异常问题
//开始没用自定义异常问题,发现不管是账号密码错误还是什么错误
//shiro只会抛出一个AuthenticationException异常
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator ();
// 认证策略:AtLeastOneSuccessfulStrategy(默认),AllSuccessfulStrategy,FirstSuccessfulStrategy
authenticator.setAuthenticationStrategy(new FirstSuccessfulStrategy());
// 加入realms
List<Realm> realms = new ArrayList<>();
realms.add(phoneShiroRealm);
realms.add(userRealm);
authenticator.setRealms(realms);
return authenticator;
}
if(realm.supports(token)) 会生效。所以不管定义多少个Realm,这里只会执行一个Realm。
** 但是 我这边phoneShiroRealm认证成功后还是会执行userRealm。
请问各位大神 如何做到第一个认证成功后不在执行后边的Realm。因为后边的Realm在参数不足的情况下会认证失败,且会把认证失败的信息记录至数据库。看着就不好。**