2011-10-05 137 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> 
相关问题