(Quick Reference)

5 Helper Classes - Reference Documentation

Authors: Burt Beckwith, Beverley Talbott

Version: 2.0.0

5 Helper Classes

Use the plugin helper classes in your application to avoid dealing with some lower-level details of Spring Security.

5.1 SecurityTagLib

The plugin includes GSP tags to support conditional display based on whether the user is authenticated, and/or has the required role to perform a particular action. These tags are in the sec namespace and are implemented in grails.plugin.springsecurity.SecurityTagLib.

ifLoggedIn

Displays the inner body content if the user is authenticated.

Example:

<sec:ifLoggedIn>
Welcome Back!
</sec:ifLoggedIn>

ifNotLoggedIn

Displays the inner body content if the user is not authenticated.

Example:

<sec:ifNotLoggedIn>
<g:link controller='login' action='auth'>Login</g:link>
</sec:ifNotLoggedIn>

ifAllGranted

Displays the inner body content only if all of the listed roles are granted.

Example:

<sec:ifAllGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">secure stuff here</sec:ifAllGranted>

ifAnyGranted

Displays the inner body content if at least one of the listed roles are granted.

Example:

<sec:ifAnyGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">secure stuff here</sec:ifAnyGranted>

ifNotGranted

Displays the inner body content if none of the listed roles are granted.

Example:

<sec:ifNotGranted roles="ROLE_USER">non-user stuff here</sec:ifNotGranted>

loggedInUserInfo

Displays the value of the specified UserDetails field if logged in. For example, to show the username property:

<sec:loggedInUserInfo field="username"/>

If you have customized the UserDetails (e.g. with a custom UserDetailsService) to add a fullName property, you access it as follows:

Welcome Back <sec:loggedInUserInfo field="fullName"/>

username

Displays the value of the UserDetails username field if logged in.

<sec:ifLoggedIn>
Welcome Back <sec:username/>!
</sec:ifLoggedIn>
<sec:ifNotLoggedIn>
<g:link controller='login' action='auth'>Login</g:link>
</sec:ifNotLoggedIn>

ifSwitched

Displays the inner body content only if the current user switched from another user. (See also Switch User.)

<sec:ifLoggedIn>
Logged in as <sec:username/>
</sec:ifLoggedIn>

<sec:ifSwitched> <a href='${request.contextPath}/j_spring_security_exit_user'> Resume as <sec:switchedUserOriginalUsername/> </a> </sec:ifSwitched>

<sec:ifNotSwitched>

<sec:ifAllGranted roles='ROLE_SWITCH_USER'>

<form action='${request.contextPath}/j_spring_security_switch_user' method='POST'>

Switch to user: <input type='text' name='j_username'/><br/>

<input type='submit' value='Switch'/> </form>

</sec:ifAllGranted>

</sec:ifNotSwitched>

ifNotSwitched

Displays the inner body content only if the current user has not switched from another user.

switchedUserOriginalUsername

Renders the original user's username if the current user switched from another user.

<sec:ifSwitched>
<a href='${request.contextPath}/j_spring_security_exit_user'>
   Resume as <sec:switchedUserOriginalUsername/>
</a>
</sec:ifSwitched>

access

Renders the body if the specified expression evaluates to true or specified URL is allowed.

<sec:access expression="hasRole('ROLE_USER')">

You're a user

</sec:access>

<sec:access url="/admin/user">

<g:link controller='admin' action='user'>Manage Users</g:link>

</sec:access>

You can also guard access to links generated from controller and action names or named URL mappings instead of hard-coding the values, for example

<sec:access controller='admin' action='user'>

<g:link controller='admin' action='user'>Manage Users</g:link>

</sec:access>

or if you have a named URL mapping you can refer to that:

<sec:access mapping='manageUsers'>

<g:link mapping='manageUsers'>Manage Users</g:link>

</sec:access>

For even more control of the generated URL (still avoiding hard-coding) you can use createLink to build the URL, for example

<sec:access url='${createLink(controller: 'admin', action: 'user', base: "/")}'>

<g:link controller='admin' action='user'>Manage Users</g:link>

</sec:access>

Be sure to include the base: "/" attribute in this case to avoid appending the context name to the URL.

noAccess

Renders the body if the specified expression evaluates to false or URL isn't allowed.

<sec:noAccess expression="hasRole('ROLE_USER')">

You're not a user

</sec:noAccess>

link

A wrapper around the standard Grails link tag that renders if the specified expression evaluates to true or URL is allowed.

To define the expression to evaluate within the tag itself:

<sec:link controller="myController" action="myAction" expression="hasRole('ROLE_USER')">My link text</sec:link>

To use access controls defined, for example, in the interceptUrlMap:

<sec:link controller="myController" action="myAction">My link text</sec:link>

5.2 SpringSecurityService

grails.plugin.springsecurity.SpringSecurityService provides security utility functions. It is a regular Grails service, so you use dependency injection to inject it into a controller, service, taglib, and so on:

def springSecurityService

getCurrentUser()

Retrieves a domain class instance for the currently authenticated user. During authentication a user/person domain class instance is retrieved to get the user's password, roles, etc. and the id of the instance is saved. This method uses the id and the domain class to re-load the instance, or the username if the UserDetails instance is not a GrailsUser.

If you do not need domain class data other than the id, you should use the loadCurrentUser method instead.

Example:

class SomeController {

def springSecurityService

def someAction() { def user = springSecurityService.currentUser … } }

loadCurrentUser()

Often it is not necessary to retrieve the entire domain class instance, for example when using it in a query where only the id is needed as a foreign key. This method uses the GORM load method to create a proxy instance. This will never be null, but can be invalid if the id doesn't correspond to a row in the database, although this is very unlikely in this scenario because the instance would have been there during authentication.

If you need other data than just the id, use the getCurrentUser method instead.

Example:

class SomeController {

def springSecurityService

def someAction() { def user = springSecurityService.isLoggedIn() ? springSecurityService.loadCurrentUser() : null if (user) { CreditCard card = CreditCard.findByIdAndUser( params.id as Long, user) … } … } }

isLoggedIn()

Checks whether there is a currently logged-in user.

Example:

class SomeController {

def springSecurityService

def someAction() { if (springSecurityService.isLoggedIn()) { … } else { … } } }

getAuthentication()

Retrieves the current user's Authentication. If authenticated, this will typically be a UsernamePasswordAuthenticationToken.

If not authenticated and the AnonymousAuthenticationFilter is active (true by default) then the anonymous user's authentication will be returned. This 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.

Example:

class SomeController {

def springSecurityService

def someAction() { def auth = springSecurityService.authentication String username = auth.username // a Collection of GrantedAuthority def authorities = auth.authorities boolean authenticated = auth.authenticated … } }

getPrincipal()

Retrieves the currently logged in user's Principal. If authenticated, the principal will be a grails.plugin.springsecurity.userdetails.GrailsUser, unless you have created a custom UserDetailsService, in which case it will be whatever implementation of UserDetails you use there.

If not authenticated and the AnonymousAuthenticationFilter is active (true by default) then a standard org.springframework.security.core.userdetails.User is used.

Example:

class SomeController {

def springSecurityService

def someAction() { def principal = springSecurityService.principal String username = principal.username // a Collection of GrantedAuthority def authorities = principal.authorities boolean enabled = principal.enabled … } }

encodePassword()

Hashes a password with the configured hashing scheme. By default the plugin uses bcrypt, but you can configure the scheme with the grails.plugin.springsecurity.password.algorithm attribute in Config.groovy. The supported values are 'bcrypt' to use bcrypt, 'pbkdf2' to use PBKDF2, or any message digest algorithm that is supported in your JDK; see this Java page for the available algorithms.
You are strongly discouraged from using MD5 or SHA-1 algorithms because of their well-known vulnerabilities. You should also use a salt for your passwords, which greatly increases the computational complexity of computing passwords if your database gets compromised. See Salted Passwords.

Example:

class PersonController {

def springSecurityService

def updateAction() { def person = Person.get(params.id)

params.salt = person.salt if (person.password != params.password) { params.password = springSecurityService.encodePassword( password, salt) def salt = … // e.g. randomly generated using a utility method params.salt = salt } person.properties = params if (!person.save(flush: true)) { render view: 'edit', model: [person: person] return } redirect action: 'show', id: person.id } }

If you are hashing the password in the User domain class (using beforeInsert and encodePassword) then don't call springSecurityService.encodePassword() in your controller since you'll double-hash the password and users won't be able to log in. It's best to encapsulate the password handling logic in the domain class.

updateRole()

Updates a role and, if you use Requestmap instances to secure URLs, updates the role name in all affected Requestmap definitions if the name was changed.

Example:

class RoleController {

def springSecurityService

def update() { def roleInstance = Role.get(params.id) if (!springSecurityService.updateRole(roleInstance, params)) { render view: 'edit', model: [roleInstance: roleInstance] return }

flash.message = "The role was updated" redirect action: show, id: roleInstance.id } }

deleteRole()

Deletes a role and, if you use Requestmap instances to secure URLs, removes the role from all affected Requestmap definitions. If a Requestmap's config attribute is only the role name (for example, "/foo/bar/**=ROLE_FOO"), it is deleted.

Example:

class RoleController {

def springSecurityService

def delete() { def roleInstance = Role.get(params.id) try { springSecurityService.deleteRole (roleInstance flash.message = "The role was deleted" redirect action: list } catch (DataIntegrityViolationException e) { flash.message = "Unable to delete the role" redirect action: show, id: params.id } } }

clearCachedRequestmaps()

Flushes the Requestmaps cache and triggers a complete reload. If you use Requestmap instances to secure URLs, the plugin loads and caches all Requestmap instances as a performance optimization. This action saves database activity because the requestmaps are checked for each request. Do not allow the cache to become stale. When you create, edit or delete a Requestmap, flush the cache. Both updateRole() and deleteRole() call clearCachedRequestmaps()for you. Call this method when you create a new Requestmap or do other Requestmap work that affects the cache.

Example:

class RequestmapController {

def springSecurityService

def save() { def requestmapInstance = new Requestmap(params) if (!requestmapInstance.save(flush: true)) { render view: 'create', model: [requestmapInstance: requestmapInstance] return }

springSecurityService.clearCachedRequestmaps() flash.message = "Requestmap created" redirect action: show, id: requestmapInstance.id } }

reauthenticate()

Rebuilds an Authentication for the given username and registers it in the security context. You typically use this method after updating a user's authorities or other data that is cached in the Authentication or Principal. It also removes the user from the user cache to force a refresh at next login.

Example:

class UserController {

def springSecurityService

def update() { def userInstance = User.get(params.id)

params.salt = person.salt if (params.password) { params.password = springSecurityService.encodePassword( params.password, salt) def salt = … // e.g. randomly generated using a utility method params.salt = salt } userInstance.properties = params if (!userInstance.save(flush: true)) { render view: 'edit', model: [userInstance: userInstance] return }

if (springSecurityService.loggedIn && springSecurityService.principal.username == userInstance.username) { springSecurityService.reauthenticate userInstance.username }

flash.message = "The user was updated" redirect action: show, id: userInstance.id } }

5.3 SpringSecurityUtils

grails.plugin.springsecurity.SpringSecurityUtils is a utility class with static methods that you can call directly without using dependency injection. It is primarily an internal class but can be called from application code.

authoritiesToRoles()

Extracts role names from an array or Collection of GrantedAuthority.

getPrincipalAuthorities()

Retrieves the currently logged-in user's authorities. It is empty (but never null) if the user is not logged in.

parseAuthoritiesString()

Splits a comma-delimited String containing role names into a List of GrantedAuthority.

ifAllGranted()

Checks whether the current user has all specified roles (a comma-delimited String of role names). Primarily used by SecurityTagLib.ifAllGranted.

ifNotGranted()

Checks whether the current user has none of the specified roles (a comma-delimited String of role names). Primarily used by SecurityTagLib.ifNotGranted.

ifAnyGranted()

Checks whether the current user has any of the specified roles (a comma-delimited String of role names). Primarily used by SecurityTagLib.ifAnyGranted.

getSecurityConfig()

Retrieves the security part of the Configuration (from grails-app/conf/Config.groovy).

loadSecondaryConfig()

Used by dependent plugins to add configuration attributes.

reloadSecurityConfig()

Forces a reload of the security configuration.

isAjax()

Checks whether the request was triggered by an Ajax call. The standard way is to determine whether X-Requested-With request header is set and has the value XMLHttpRequest. In addition, you can configure the name of the header with the grails.plugin.springsecurity.ajaxHeader configuration attribute, but this is not recommended because all major JavaScript toolkits use the standard name. Further, you can register a closure in Config.groovy with the name ajaxCheckClosure that will be used to check if a request is an Ajax request. It is passed the request as its single argument, e.g.

grails.plugin.springsecurity.ajaxCheckClosure = { request ->
   // return true or false
}

You can also force the request to be treated as Ajax by appending &ajax=true to your request query string.

registerProvider()

Used by dependent plugins to register an AuthenticationProvider bean name.

registerFilter()

Used by dependent plugins to register a filter bean name in a specified position in the filter chain.

isSwitched()

Checks whether the current user switched from another user.

getSwitchedUserOriginalUsername()

Gets the original user's username if the current user switched from another user.

doWithAuth()

Executes a Closure with the current authentication. The one-parameter version which takes just a Closure assumes that there's an authentication in the HTTP Session and that the Closure is running in a separate thread from the web request, so the SecurityContext and Authentication aren't available to the standard ThreadLocal. This is primarily of use when you explicitly launch a new thread from a controller action or service called in request scope, not from a Quartz job which isn't associated with an authentication in any thread.

The two-parameter version takes a username and a Closure to authenticate as. This is will authenticate as the specified user and execute the closure with that authentication. It restores the authentication to the one that was active if it exists, or clears the context otherwise. This is similar to run-as and switch-user but is only local to the Closure.