2011-10-05 114 views
50

有沒有教程或沒有人有指示如何使用Spring-Security做以下事情?Spring Security自定義身份驗證和密碼編碼

任務:

我需要從我的數據庫認證的用戶名得到鹽,並用它來加密提供的密碼(從登錄頁面),將其與存儲的加密密碼(又名認證用戶)。

附加信息:

我使用自定義的數據庫結構。一個UserDetails對象是通過自定義UserDetailsService創建的,該自定義對象使用自定義DAOProvider從數據庫獲取信息。

security.xml文件至今:

<authentication-manager> 
    <authentication-provider user-service-ref="userDetailsService"> 
    </authentication-provider> 
</authentication-manager> 

現在我想我需要

 <password-encoder hash="sha" /> 

但還有什麼?我如何告訴spring security使用數據庫提供的鹽來編碼密碼?


編輯

我發現This SO後是informatative但不是充分的:如果我在XML定義鹽源由密碼編碼器一起使用,例如:

 <password-encoder ref="passwordEncoder">     
      <salt-source ref="saltSource"/> 
     </password-encoder> 

我將不得不編寫一個自定義SaltSource來使用我的自定義鹽。但是這不是在UserDetails對象內部找到的。所以......

選擇1:

我可以使用的UserDetails的自定義實現然後可能具有鹽的財產?

<beans:bean id="saltSource" class="path.to.MySaltSource" 
    p:userPropertyToUse="salt"/> 

@Service("userDetailsService") 
public class UserDetailsServiceImpl implements UserDetailsService { 
    public UserDetails loadUserByUsername(String username) 
      throws UsernameNotFoundException, DataAccessException { 

     // ... 
     return buildUserFromAccount(account); 
    } 

    @Transactional(readOnly = true) 

    UserDetailsImpl buildUserFromAccount(Account account){ 

     // ... build User object that contains salt property 
} 

定製用戶類別:

public class UserDetailsImpl extends User{ 

    // ... 

    private String salt; 

    public String getSalt() { return salt; } 

    public void setSalt(String salt) { this.salt = salt; } 
} 

的security.xml:

<authentication-manager> 
    <authentication-provider user-service-ref="userDetailsService"> 
     <password-encoder hash="sha">     
     <salt-source ref="saltSource"/> 
    </password-encoder> 
    </authentication-provider> 
</authentication-manager> 

<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource" p:userPropertyToUse="salt"/> 


備選方案2:

否則我不得不注入我accountDAO到SaltSource提取鹽從數據庫中給定的userName

但是:Spring Security如何調用SaltSource?始終與saltSource.getSalt(userDetails)

然後,我只需要確保我的SaltSource在我的accountDAO上使用userDetails.accountName來檢索鹽。


EDIT2:

剛剛得知,我的做法是..遺留.. :(所以我想我就用StandardPasswordEncoder(我仍然要弄清楚如何準確使用)

順便說一句:我實現了第一個選項,用一個自定義的UserDetails類來擴展User類,然後添加一個salt屬性,然後將它作爲userPropertyToUse傳遞給SaltSource,就像它在SO後面提到的那樣在編輯1 ...


編輯3:

剛拿到StandardPasswordEncoder工作,所以我會在這裏留下一些指針:

使用StandardPasswordEncoder進行身份驗證:

<beans:bean id="encoder" 
    class="org.springframework.security.crypto.password.StandardPasswordEncoder"> 
</beans:bean> 


<authentication-manager> 
    <authentication-provider user-service-ref="userDetailsService"> 
     <password-encoder ref="encoder" />   
    </authentication-provider> 
</authentication-manager> 

這就要求3.1.0.RC中的spring-security-crypto模塊?我所知道的。找不到任何具有3.0的存儲庫。版本(即使它包含3.0.6版本等列出的版本)。此外,文件談到了春季安全3.1,所以我認爲,我會隨之而去。

當創建一個用戶(對我來說只有一個管理員可以做到這一點),我只是用

 StandardPasswordEncoder encoder = new StandardPasswordEncoder(); 
     String result = encoder.encode(password); 

和我做。

Spring Security將隨機創建一個salt並將其添加到密碼字符串中,然後將其存儲在數據庫中,所以不再需要salt column

人們可以但是也可以提供一個全球性的鹽作爲構造函數的參數(new StandardPasswordEncoder("12345");),但我不知道如何設置我的安全配置,以檢索一個bean是價值,而不是與<constructor-arg name="secret" value "12345" />提供靜字符串。但是我不知道需要多少。

回答

34

我還是選這個作爲回答,我解決我的問題,並沒有給出其他意見或答案:

編輯1 - 替代1回答了原來的問題

我瞭解到定製密碼salting是一種傳統方法,在Spring Security 3.1中不再需要,正如我在

中所描述的那樣

編輯3我在這裏留下了一些關於如何將StandardPasswordEncoder用於與密碼一起存儲的自動鹽。

+1

您的文章真的幫助我,我有非常類似的問題。 +1自我解決^^ – user1431729

+4

我會建議BCryptPasswordEncoder而不是StandardPasswordEncoder。在安全性和與其他語言的互操作性方面,BCryptPasswordEncoder是更好的選擇 – Farm

0

要從豆檢索全球鹽,使用Spring表達式語言或規劃環境地政司。

<beans:bean id="encoder" 
     class="org.springframework.security.crypto.password.StandardPasswordEncoder"> 
    <constructor-arg value="#{someotherBean.somePropertyWithAGetterMethod"/> 
</beans:bean> 
相關問題