我一直在努力在基于 spring 的 Web 应用程序中使用 shiro 1.2.1 进行 authenticationStrategy 设置。我有2个 Realm 。一种针对 database
进行身份验证,另一种针对 ldap。两个 realms
都工作正常,只是我想要一个 FirstSuccessfulStrategy
但似乎两个 Realm 仍在被调用。这是我的安全应用程序上下文:
<bean id="passwordService" class="org.apache.shiro.authc.credential.DefaultPasswordService">
<property name="hashService" ref="hashService" />
</bean>
<bean id="hashService" class="org.apache.shiro.crypto.hash.DefaultHashService">
<property name="hashAlgorithmName" value="SHA-512" />
<property name="hashIterations" value="500000" />
</bean>
<bean id="SaltedSha512JPARealm" class="bla.bla.webapp.security.SaltedSha512JPARealm">
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.PasswordMatcher">
<property name="passwordService" ref="passwordService"/>
</bean>
</property>
</bean>
<bean id="ldapContextFactory" class="org.apache.shiro.realm.ldap.JndiLdapContextFactory">
<property name="url" value="${user.ldap.connection.url}"/>
<property name="authenticationMechanism" value="${user.ldap.connection.auth_mecanism}"/>
</bean>
<bean id="ldapRealm" class="bla.bla.webapp.security.LDAPRealm">
<property name="userDnTemplate" value="${user.ldap.connection.userDnTemplate}"/>
<property name="contextFactory" ref="ldapContextFactory" />
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" depends-on="roleRepository,roleRightRepository,rightRepository,userRepository">
<property name="realms">
<list>
<ref local="ldapRealm"/>
<ref local="SaltedSha512JPARealm"/>
</list>
</property>
<property name="authenticator.authenticationStrategy">
<bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>
</property>
</bean>
我有什么地方做的不好吗?
最佳答案
FirstSuccessfulStrategy
表示您的验证器将尝试您所有的 Realm 来验证用户,直到第一次成功为止。您的 Realm 按顺序配置:ldapRealm
、SaltedSha512JPARealm
。因此,如果 lapRealm
将失败,验证器将尝试第二个。要解决这个问题,您可以尝试将最成功或最快的 Realm 配置为第一个,例如您可以将 Realm 顺序更改为 SaltedSha512JPARealm
、ldapRealm
:
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" depends-on="roleRepository,roleRightRepository,rightRepository,userRepository">
<property name="realms">
<list>
<ref local="SaltedSha512JPARealm"/>
<ref local="ldapRealm"/>
</list>
</property>
<property name="authenticator.authenticationStrategy">
<bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>
</property>
</bean>
但您应该明白,对于此配置,如果 SaltedSha512JPARealm
失败,验证器将尝试 ldapRealm
。
或者您可以尝试为该 Realm 使用不同的 token 类别。但只有当您对它们中的每一个都有不同的身份验证入口点时,它才会起作用。
UPD
似乎 ModularRealmAuthenticator
的设计使其始终尝试通过所有 Realm 对用户进行身份验证。 FirstSuccessfulStrategy
只能影响认证结果。它将首先返回成功的 AuthenticationInfo
。要实现您的目标,您需要覆盖 ModularRealmAuthenticator#doMultiRealmAuthentication
方法。它可能看起来像这样:
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", realms.size());
}
for (Realm realm : realms) {
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);
}
}
aggregate = strategy.afterAttempt(realm, token, info, aggregate, t);
// dirty dirty hack
if (aggregate != null && !CollectionUtils.isEmpty(aggregate.getPrincipals())) {
return aggregate;
}
// end dirty dirty hack
} else {
log.debug("Realm [{}] does not support token {}. Skipping realm.", realm, token);
}
}
aggregate = strategy.afterAllAttempts(token, aggregate);
return aggregate;
}
关于spring - Apache 四郎 : how to set the authenticationStrategy using spring applicationcontext?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15705910/