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 = falsebcrypt 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.groovyenvironments {
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.groovyimport com.mycompany.MyAuthenticationDetailsSourcebeans = {
authenticationDetailsSource(MyAuthenticationDetailsSource) {
// any required properties
}
}