3

Spring ベースの Web アプリケーションで、shiro 1.2.1 を使用した authenticationStrategy 設定に苦労しています。私は2つの領域を持っています。1 つは LDAP に対して認証し、もう 1 つは LDAP に対して認証しdatabaseます。どちらrealmsも私が欲しかっただけでうまく機能していますFirstSuccessfulStrategyが、両方のレルムがまだ呼び出されているようです。ここに私のセキュリティアプリケーションコンテキストがあります:

<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>

私がうまくやっていないことはありますか?

4

2 に答える 2

2

FirstSuccessfulStrategyオーセンティケーターは、最初に成功するまでユーザーを認証するためにすべてのレルムを試行することを意味します。レルムは次の順序で構成されました: ldapRealmSaltedSha512JPARealmlapRealmそのため、オーセンティケーターが失敗した場合、 2 つ目の認証を試みます。これを解決するには、最も成功したレルムまたは最も速いレルムが最初になるように設定することができます。たとえば、レルムの順序を , に変更でき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

または、このレルムに別のトークン クラスを使用することもできます。ただし、それぞれに異なる認証エントリ ポイントがある場合にのみ機能します。

UPD

ModularRealmAuthenticator常にすべてのレルムでユーザーを認証しようとするように設計されているようです。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;
}
于 2013-03-30T12:59:31.323 に答える
0
<property name="authenticator.authenticationStrategy">
    <bean class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>
</property>

上記の定義は間違っています。次のように定義します

<property name="authenticator.authenticationStrategy" ref="authcStrategy"/>

そして、以下のBean定義を個別に定義します

<bean id="authcStrategy"     class="org.apache.shiro.authc.pam.FirstSuccessfulStrategy"/>

その後、期待どおりに動作します

于 2015-01-30T12:35:04.697 に答える