6

I would like to add salt like:

PasswordEncoder encoder = new ShaPasswordEncoder();
        userDetails.setPassword(encoder.encodePassword(userDetails.getPassword(),saltSource.getSalt(userDetails));

as far userDetails is instance of my custom UserDetail class,i obliged to cast it to this spring class:UserDetails ,but as it's logically expected i got in Runtime:

java.lang.ClassCastException: model.UserDetails cannot be cast to org.springframework.security.core.userdetails.UserDetails

config:

<beans:bean id="saultSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource">
        <beans:property name="userPropertyToUse" value="username"/>
</beans:bean>

<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder hash="sha">
    <salt-source user-property="username"/>
</password-encoder>
    <jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
</authentication-manager>

How can I configure salt correctly in this case?

Toto
  • 89,455
  • 62
  • 89
  • 125
sergionni
  • 13,290
  • 42
  • 132
  • 189

3 Answers3

3

ReflectionSaltSource only works with a UserDetails object (I'm assuming that's where you get the class-cast exception?), so you would have to either implement UserDetails or create your own SaltSource implementation which works with your object.

However, I wouldn't use a property of the user as the salt unless you are working with a legacy system which already does this. The username is not a very good salt value. It's much better to use a random salt which is stored with the password. A good example is the BCrypt algorithm. See my answer to this question for an example of using it with Spring Security 3.1. As explained there, BCrypt automatically generates a random salt which it stores in the same string as the hashed password.

Note that there is actually a new PasswordEncoder interface in the Spring Security 3.1 "crypto" package (in org.springframework.security.crypto.password). This doesn't include a salt in the API methods, since it assumes the salt is internally generated (as it is with the BCrypt implementation). The framework will generally accept one of these or the legacy org.springframework.security.authentication.encoding.PasswordEncoder.

Community
  • 1
  • 1
Shaun the Sheep
  • 22,353
  • 1
  • 72
  • 100
  • @Luke, as I understand from your linked post,`BCrypt` already contains Salt.How can I configure Salt in this case? Is it configurable at all,when using `BCrypt`?There said:"This automatically generates a salt and concatenates it with the hash value in a single String" – sergionni Dec 29 '11 at 14:54
  • 1
    @sergionni: notice the API change in Spring Security! In 3.0.x the [PasswordEncoder](http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/authentication/encoding/PasswordEncoder.html) uses the salt to encode password. But in 3.1.x the [PasswordEncoder](http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/crypto/password/PasswordEncoder.html) doesn't use the salt. Luke's advice is for version 3.1.x **only**. – Roadrunner Dec 29 '11 at 16:55
  • @Roadrunner, my version is 3.0.0.RC1.Thank you for hint. – sergionni Dec 29 '11 at 17:03
  • 1
    @sergionni: Why RC1? RELEASE version is there for months. You should seriously consider the latest 3.0.x version: [3.0.7.RELEASE](http://mvnrepository.com/artifact/org.springframework.security/spring-security-core/3.0.7.RELEASE). – Roadrunner Dec 29 '11 at 18:23
  • @Roadrunner ,I have one more question.I've specified 3.1.0.RELEASE in my pom file. Is salt generated by default with this construction:`userDetails.setPassword(encoder.encodePassword(userDetails.getPassword(), null));` – sergionni Dec 30 '11 at 13:42
  • @sergionni: this doesn't even compile with 3.1.0.RELEASE - the method signature is: [PasswordEncoder.encode(CharSequence)](http://static.springsource.org/spring-security/site/docs/3.1.x/apidocs/org/springframework/security/crypto/password/PasswordEncoder.html#encode(java.lang.CharSequence))! Just do `userDetails.setPassword(encoder.encodePassword(plainTextPwd));` and this will generate a hash using a random salt. Password checking is than done by `encoder.matches(rawPassword, encodedPassword)`. Just have a look at the reference documentation / API documentation / sources. – Roadrunner Dec 30 '11 at 19:07
  • I should have made it clearer that there is actually a new PasswordEncoder interface in 3.1 which is now preferred over the former one. I've updated the answer to clarify this. – Shaun the Sheep Dec 30 '11 at 20:11
1

Your model.UserDetails class must implement the interface org.springframework.security.core.userdetails.UserDetails - it does not need to be a class org.springframework.security.core.userdetails.User.

You can also have a look at this answer to see how to set up a ReflectionSaltSource for both encoding and decoding passwords, or help You get the bigger picture to follow Luke's great tip on BCryptPasswordEncoder.

Community
  • 1
  • 1
Roadrunner
  • 6,661
  • 1
  • 29
  • 38
  • I saw your post earlier.As I understand,the class `CustomUserDetails` in it implements spring's `UserDetails`,isn't it?The case is that,I needn't implement it for now.My custom `UserDetails` is quite tiny and it's enough. – sergionni Dec 29 '11 at 14:56
  • 1
    @sergionni: This was just an example placeholder - You can use any implementation of `org.springframework.security.core.userdetails.UserDetails` in place of 'CustomUserDetails' - it may be Your own, either tiny or featureful, or the one provided with the framework `org.springframework.security.core.userdetails.User`. The main part of my post was about configuring the `SaltSource` though. – Roadrunner Dec 29 '11 at 16:42
0

I've written a blog post about some of these details here: http://rtimothy.tumblr.com/post/26527448708/spring-3-1-security-and-salting-passwords Luke wrote the code so he certainly knows what he's talking about, but I see a number of people including myself having a hard time groking this information, hopefully that like will help.

rooftop
  • 3,031
  • 1
  • 22
  • 33