一直以为给定的下面配置是短路方式的,即defaultJdbcRealm可以成功认证,backDoorJdbcRealm就不会被调用。
其实不然,org.apache.shiro.authc.pam.FirstSuccessfulStrategy并不是这个意思,所有的realm依然都会被调用。
只不过是第一个认证成功的AuthenticationInfo作为最后的结果返回。
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 其他配置 --> <property name="authenticator" ref="authenticator" /> <property name="realms"> <list> <ref bean="defaultJdbcRealm" /> <ref bean="backDoorJdbcRealm" /> </list> </property> </bean> <bean id="defaultJdbcRealm" class="..." /> <bean id="backDoorJdbcRealm" class="..." /> <bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"> <property name="authenticationStrategy"> <bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy" /> </property> </bean>
为了实现目的,必须对org.apache.shiro.authc.pam.ModularRealmAuthenticator改造。
package xxx.yyy.security; import java.util.Collection; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.pam.AuthenticationStrategy; import org.apache.shiro.realm.Realm; import org.apache.shiro.util.CollectionUtils; public class ModularRealmAuthenticator extends org.apache.shiro.authc.pam.ModularRealmAuthenticator { @Override protected AuthenticationInfo doMultiRealmAuthentication(Collection<Realm> realms, AuthenticationToken token) { AuthenticationStrategy strategy = getAuthenticationStrategy(); AuthenticationInfo aggregate = strategy.beforeAllAttempts(realms, token); for (Realm realm : realms) { aggregate = strategy.beforeAttempt(realm, token, aggregate); if (realm.supports(token)) { AuthenticationInfo info = null; Throwable t = null; try { info = realm.getAuthenticationInfo(token); } catch (Throwable throwable) { t = throwable; } 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 { } } aggregate = strategy.afterAllAttempts(token, aggregate); return aggregate; } }
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 其他配置 --> <property name="authenticator" ref="authenticator" /> <property name="realms"> <list> <ref bean="defaultJdbcRealm" /> <ref bean="backDoorJdbcRealm" /> </list> </property> </bean> <bean id="defaultJdbcRealm" class="..." /> <bean id="backDoorJdbcRealm" class="..." /> <bean id="authenticator" class="xxx.yyy.security.ModularRealmAuthenticator"> <property name="authenticationStrategy"> <bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy" /> </property> </bean>