2 What's New in Version 2.0 - Reference Documentation
Authors: Burt Beckwith, Beverley Talbott
Version: 2.0.0
2 What's New in Version 2.0
There are many changes in the 2.x versions of the plugin from the older approaches in 1.x.Package changes
All classes are now in thegrails.plugin.springsecurity
package or a subpackage. The names tend to correspond to the analagous Spring Security classes where appropriate, for example MutableLogoutFilter
is in the grails.plugin.springsecurity.web.authentication.logout
package to correspond with the org.springframework.security.web.authentication.logout
package.Some of the changes were more subtle though; for example all classes in the old grails.plugins.springsecurity
packages and subpackages are now in grails.plugin.springsecurity
, only one character different. This will result in a non-trivial upgrade process for your applications, but that is a benefit as it will hopefully point you at other important changes you might have otherwise missed.Configuration prefix changes
The prefix used inConfig.groovy
for the plugin's configuration settings has changed from grails.plugins.springsecurity
to grails.plugin.springsecurity
.More aggressively secure by default
In 1.x it was assumed that defaulting pages to not be secured, and configuring guarded URLs as needed, was a more pragmatic approach. Now however, all URLs are initially blocked unless there is a request mapping rule, even if that rule allows all access. The assumption behind this change is that if you forget to guard a new URL, it can take a long time to discover that users had access, whereas if you forget to open access for allowed users when using the "pessimistic" approach, nobody can access the URL and the error will be quickly discovered. This approach is more work, but much safer.This is described in more detail here.Logout POST only
By default only POST requests are allowed to trigger a logout. To allow GET access, add thisgrails.plugin.springsecurity.logout.postOnly = false
bcrypt by default
The default password hashing algorithm is now bcrypt since it is a very robust hashing approach. PBKDF2 is similar and is also supported. You can still use any message digest algorithm that is supported in your JDK; see this Java page for the available algorithms.New applications should use bcrypt or PBKDF2, but if you didn't change the default settings in previous versions of the plugin and want to continue using the same algorithm, use these settings:grails.plugin.springsecurity.password.algorithm = 'SHA-256' grails.plugin.springsecurity.password.hash.iterations = 1
Session Fixation Prevention by default
Session Fixation Prevention is now enabled by default, but can be disabled withgrails.plugin.springsecurity.useSessionFixationPrevention = false
@Secured annotation
As of Grails 2.0, controller actions can be defined as closures or methods, with methods being preferred. The @Secured annotation no longer supports being defined on controller action closures, so you will need to convert them to real methods.You can also specify the HTTP method that an annotation is defined for (e.g. when using REST). When doing this you must explicitly name thevalue
attribute, e.g.@Secured(value=["hasRole('ROLE_ADMIN')"], httpMethod='POST')
def someMethod() {
…
}
true
or false
and has all of the methods and properties that are available when using SpEL expressions, since the closure's delegate
is set to a subclass of WebSecurityExpressionRoot
, and also the Spring ApplicationContext
as the ctx
property:@Secured(closure = { assert request assert ctx authentication.name == 'admin1' }) def someMethod() { … }
Anonymous authentication
In standard Spring Security and older versions of the plugin, there is support for an "anonymous" authentication. This is implemented by a filter that registers a simpleAuthentication
in the SecurityContext
to remove the need for null checks, since there will always be an Authentication
available. This approach is still problematic though because the Principal of the anonymous authentication is a String, whereas it is a UserDetails
instance when there is a non-anonymous authentication.Since you still have to be careful to differentiate between anonymous and non-anonymous authentications, the plugin now creates an anonymous Authentication
which will be an instance of grails.plugin.springsecurity.authentication. GrailsAnonymousAuthenticationToken
with a standard org.springframework.security.core.userdetails.User
instance as its Principal. The authentication will have a single granted role, ROLE_ANONYMOUS
.No HQL
Some parts of the code used HQL queries, for example in the generatedUserRole
class and in SpringSecurityService.findRequestmapsByRole
. These have been replaced by "where" queries to make data access more portable across GORM implementatioins.Changes in generated classes
Theenabled
property in the generated User
class now defaults to true
. This will make creating instances a bit more DRY:def u = new User(username: 'me', password: 'itsasecret').save()
grails.plugin.springsecurity.LoginController.groovy
and grails.plugin.springsecurity.LogoutController.groovy
controllers, and grails-app/views/auth.gsp
and grails-app/views/denied.gsp
GSPs. If you had no need previously to change these you can delete your files and the plugins' files will be used instead. If you do want to change them, copy each as needed to your application and make the required changes, and yours will be used instead.One small change is that there is no longer a default value for the domain class name properties (userLookup.userDomainClassName
, authority.className
, requestMap.className
, rememberMe.persistentToken.domainClassName
). This was of little use and tended to cause confusing error messages when there was a misconfiguration.SecurityContextHolder strategy
You can now define theSecurityContextHolder
strategy. By default it is stored in a ThreadLocal
, but you can also configure it to use an InheritableThreadLocal
to maintain the context in new threads, or a custom class that implements the org.springframework.security.core.context.SecurityContextHolderStrategy
interface. To change the strategy, set the grails.plugin.springsecurity.sch.strategyName
config property to "MODE_THREADLOCAL"
(the default) to use a ThreadLocal
, "MODE_INHERITABLETHREADLOCAL"
to use an InheritableThreadLocal
, or the name of a class that implements SecurityContextHolderStrategy
.Debug filter
You can enable a "debug" filter based on theorg.springframework.security.config.debug.DebugFilter
class. It will log security information at the "info" level and can help when debugging configuration issues. This should only be enabled in development mode so consider adding the property that enables it inside an environments
block in Config.groovy
environments { development { grails.logging.jul.usebridge = true grails.plugin.springsecurity.debug.useFilter = true } production { grails.logging.jul.usebridge = false } }
info 'grails.plugin.springsecurity.web.filter.DebugFilter'
Storing usernames in the session
In Spring Security 3.0 and earlier, the username was stored in the HTTP session under the key "SPRING_SECURITY_LAST_USERNAME". This no longer done, but the plugin will use the old behavior if thegrails.plugin.springsecurity.apf.storeLastUsername
setting is set to true
(the default is false
). Further, the name is no longer escaped before storing, it is stored exactly as entered by the user, so you must escape it when redisplaying to avoid XSS attacks.@Authorities annotation
You can use the new @Authorities annotation to make your annotations more DRY. See this blog post for a description about the motivation and implementation details. Note that the package for the annotation in the plugin isgrails.plugin.springsecurity.annotation
, not grails.plugins.springsecurity.annotation
as described in the blog post.Miscellaneous changes
AuthenticationDetailsSource
Previously you could configure the details class that was constructed by theauthenticationDetailsSource
bean by setting the authenticationDetails.authClass
property. In Spring Security 3.2 this isn't possible because WebAuthenticationDetailsSource
always returns a WebAuthenticationDetails
. But you can still customize the details class by creating a class that implements the AuthenticationDetailsSource interface, e.g.:package com.mycompany;import javax.servlet.http.HttpServletRequest;import org.springframework.security.authentication.AuthenticationDetailsSource;public class MyAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, MyWebAuthenticationDetails> { public MyWebAuthenticationDetails buildDetails(HttpServletRequest context) { // build a MyWebAuthenticationDetails } }
authenticationDetailsSource
bean in resources.groovy
import com.mycompany.MyAuthenticationDetailsSourcebeans = {
authenticationDetailsSource(MyAuthenticationDetailsSource) {
// any required properties
}
}