2013-03-29 60 views
3

在基於spring的web應用程序中,我一直在使用shiro 1.2.1進行authenticationStrategy設置。我有2個領域。一個針對database進行身份驗證,另一個針對ldap。兩個realms工作正常,只是我想要一個FirstSuccessfulStrategy但似乎兩個領域仍被稱爲。這裏是我的安全應用上下文:apache shiro:如何使用spring applicationcontext設置authenticationStrategy?

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

有沒有什麼我沒有做好?

回答

2

FirstSuccessfulStrategy意味着您的身份驗證器會嘗試所有領域來驗證用戶身份,直到第一次成功爲止。您的領域按順序配置:ldapRealm,SaltedSha512JPARealm。所以如果lapRealm將失敗,認證者會嘗試第二個。爲了解決這個問題,你可以嘗試配置最成功或最快的領域,例如你可以改變你的領域爲了SaltedSha512JPARealmldapRealm

<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; 
} 
+0

感謝你的答案會工作。我的問題是,即使對'stuart ldap server'(http://blog.stuartlewis.com/2008/07/07/test-ldap-service/)進行了成功的身份驗證,它也會嘗試使用'SaltedSha512JPARealm'對數據庫進行身份驗證。這就是爲什麼我的配置有問題。知道ldapRealm是首先添加它不應該發生的權利? –

+0

你說得對。看起來'ModularRealmAuthenticator'的設計是爲了讓它始終嘗試對所有領域的用戶進行身份驗證。只是更新了答案。 – sody

+0

嗨,很抱歉,遲到的迴應。我已經嘗試過使用不同的令牌,並基於我放在UI上的組合框創建它們,就像MS windows登錄切換域一樣。這是我現在快速修復的問題。我將在下一次迭代中嘗試這個解決方案,我被限期截獲。因此修復工作對於UI用戶和管理人員來說很好。 –

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

然後按預期

相關問題