The Spring Security plugin uses hashed passwords and a digest algorithm that you specify. For enhanced protection against dictionary attacks, you should use a salt in addition to digest hashing.
Note
|
Note that if you use bcrypt (the default setting) or pbkdf2, do not configure a salt (e.g. the |
There are two approaches to using salted passwords in the plugin - defining a property in the UserDetails
class to access by reflection, or by directly implementing {apidocs}org/springframework/security/authentication/dao/SaltSource.html[SaltSource] yourself.
Set the dao.reflectionSaltSourceProperty
configuration property:
grails.plugin.springsecurity.dao.reflectionSaltSourceProperty = 'username'
This property belongs to the UserDetails
class. By default it is an instance of grails.plugin.springsecurity.userdetails.GrailsUser
, which extends the standard Spring Security {apidocs}org/springframework/security/core/userdetails/User.html[User class] and not your “person” domain class. This limits the available properties unless you use a custom UserDetailsService ([userDetailsService]).
As long as the username does not change, this approach works well for the salt. If you choose a property that the user can change, the user cannot log in again after changing it unless you re-hash the password with the new value. So it’s best to use a property that doesn’t change.
Another option is to generate a random salt when creating users and store this in the database by adding a new property to the “person” class. This approach requires a custom UserDetailsService
because you need a custom UserDetails
implementation that also has a “salt” property, but this is more flexible and works in cases where users can change their username.
Spring Security supplies a simple SaltSource
implementation, {apidocs}org/springframework/security/authentication/dao/SystemWideSaltSource.html[SystemWideSaltSource], which uses the same salt for each user. It’s less robust than using a different value for each user but still better than no salt at all.
An example override of the salt source bean using SystemWideSaltSource would look like this:
SystemWideSaltSource
as the saltSource
bean in application.groovy
import org.springframework.security.authentication.dao.SystemWideSaltSource
beans = {
saltSource(SystemWideSaltSource) {
systemWideSalt = 'the_salt_value'
}
}
To have full control over the process, you can implement the SaltSource
interface and replace the plugin’s implementation with your own by defining a bean in grails-app/conf/spring/resources.groovy
with the name saltSource
:
saltSource
bean in application.groovy
import com.foo.bar.MySaltSource
beans = {
saltSource(MySaltSource) {
// set properties
}
}
Regardless of the implementation, you need to be aware of what value to use for a salt when creating or updating users, for example, in a save
or update
action in a UserController
. When hashing the password, use the two-parameter version of springSecurityService.encodePassword()
:
class UserController {
def springSecurityService
def save(User user) {
user.password = springSecurityService.encodePassword(
params.password, user.username)
if (!user.save(flush: true)) {
render view: 'create', model: [userInstance: user]
return
}
flash.message = "The user was created"
redirect action: show, id: user.id
}
def update(User user) {
if (params.password) {
params.password = springSecurityService.encodePassword(
params.password, user.username)
}
if (!user.save(flush: true)) {
render view: 'edit', model: [userInstance: user]
return
}
if (springSecurityService.loggedIn &&
springSecurityService.principal.username == user.username) {
springSecurityService.reauthenticate user.username
}
flash.message = "The user was updated"
redirect action: show, id: user.id
}
}
Note
|
If you are encoding the password in the User domain class (using |