BuildConfig.groovy
plugins {
...
compile ":spring-security-core:2.0-RC4"
}
s2-quickstart
grails s2-quickstart es.ua.expertojava.todo Person Role RequestMap
Config.groovy
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'es.ua.expertojava.todo.Person'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'es.ua.expertojava.todo.PersonRole'
grails.plugin.springsecurity.authority.className = 'es.ua.expertojava.todo.Role'
grails.plugin.springsecurity.requestMap.className = 'es.ua.expertojava.todo.RequestMap'
grails.plugin.springsecurity.securityConfigType = 'Requestmap'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll'],
'/login/**': ['permitAll'],
'/logout/**': ['permitAll']
]
Config.groovy
grails.plugin.springsecurity.password.algorithm='SHA-512'
package es.ua.expertojava.todo
class Person {
transient springSecurityService
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static transients = ['springSecurityService']
static constraints = {
username blank: false, unique: true
password blank: false
}
static mapping = {
password column: '`password`'
}
Set getAuthorities() {
PersonRole.findAllByPerson(this).collect { it.role }
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}
}
package es.ua.expertojava.todo
class User extends Person{
String name
String surnames
String confirmPassword
String email
Date dateOfBirth
String description
static hasMany = [todos:Todo]
static constraints = {
name(blank:false)
surnames(blank:false)
confirmPassword(blank:false, password:true)
email(blank:false, email:true)
dateOfBirth(nullable:true, validator: {
if (it?.compareTo(new Date()) < 0)
return true
return false
})
description(maxSize:1000,nullable:true)
}
static transients = ["confirmPassword"]
String toString(){
"@${username}"
}
}
package es.ua.expertojava.todo
class Todo {
...
User user
...
}
grails generate-all es.ua.expertojava.todo.User
package es.ua.expertojava.todo
class Role {
String authority
static mapping = {
cache true
}
static constraints = {
authority blank: false, unique: true
}
}
package es.ua.expertojava.todo
import org.apache.commons.lang.builder.HashCodeBuilder
class PersonRole implements Serializable {
private static final long serialVersionUID = 1
Person person
Role role
boolean equals(other) {
if (!(other instanceof PersonRole)) {
return false
}
other.person?.id == person?.id &&
other.role?.id == role?.id
}
int hashCode() {
def builder = new HashCodeBuilder()
if (person) builder.append(person.id)
if (role) builder.append(role.id)
builder.toHashCode()
}
static PersonRole get(long personId, long roleId) {
PersonRole.where {
person == Person.load(personId) &&
role == Role.load(roleId)
}.get()
}
static boolean exists(long personId, long roleId) {
PersonRole.where {
person == Person.load(personId) &&
role == Role.load(roleId)
}.count() > 0
}
static PersonRole create(Person person, Role role, boolean flush = false) {
def instance = new PersonRole(person: person, role: role)
instance.save(flush: flush, insert: true)
instance
}
static boolean remove(Person u, Role r, boolean flush = false) {
if (u == null || r == null) return false
int rowCount = PersonRole.where {
person == Person.load(u.id) &&
role == Role.load(r.id)
}.deleteAll()
if (flush) { PersonRole.withSession { it.flush() } }
rowCount > 0
}
static void removeAll(Person u, boolean flush = false) {
if (u == null) return
PersonRole.where {
person == Person.load(u.id)
}.deleteAll()
if (flush) { PersonRole.withSession { it.flush() } }
}
static void removeAll(Role r, boolean flush = false) {
if (r == null) return
PersonRole.where {
role == Role.load(r.id)
}.deleteAll()
if (flush) { PersonRole.withSession { it.flush() } }
}
static constraints = {
role validator: { Role r, PersonRole ur ->
if (ur.person == null) return
boolean existing = false
PersonRole.withNewSession {
existing = PersonRole.exists(ur.person.id, r.id)
}
if (existing) {
return 'userRole.exists'
}
}
}
static mapping = {
id composite: ['role', 'person']
version false
}
}
Person user = ...
Role role = ...
//Asignación de rol a un usuario
PersonRole.create user, role
//Asignación de un rol a un usuario indicándole el atributo flush
PersonRole.create user, role, true
//Revocación de un rol a un usuario
Person user = ...
Role role = ...
PersonRole.remove user, role
//Revocación de un rol a un usuario indicándole el atributo flush
PersonRole.remove user, role, true
package es.ua.expertojava.todo
import org.springframework.http.HttpMethod
class RequestMap {
String url
String configAttribute
HttpMethod httpMethod
static mapping = {
cache true
}
static constraints = {
url blank: false, unique: 'httpMethod'
configAttribute blank: false
httpMethod nullable: true
}
}
grails.plugin.springsecurity.securityConfigType = "Annotation"
package com.mycompany.myapp
import grails.plugin.springsecurity.annotation.Secured
class SecureAnnotatedController {
@Secured(['ROLE_ADMIN'])
def index() {
render 'you have ROLE_ADMIN'
}
@Secured(['ROLE_ADMIN', 'ROLE_SUPERUSER'])
def adminEither() {
render 'you have ROLE_ADMIN or SUPERUSER'
}
def anybody() {
render 'anyone can see this'
}
}
package com.mycompany.myapp
import grails.plugin.springsecurity.annotation.Secured
@Secured(['ROLE_ADMIN'])
class SecureClassAnnotatedController {
def index() {
render 'index: you have ROLE_ADMIN'
}
def otherAction() {
render 'otherAction: you have ROLE_ADMIN'
}
@Secured(['ROLE_SUPERUSER'])
def super() {
render 'super: you have ROLE_SUPERUSER'
}
}
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/js/admin/**': ['ROLE_ADMIN'],
'/images/**': ['ROLE_ADMIN']
]
grails.plugin.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugin.springsecurity.interceptUrlMap = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll'],
'/login/**': ['permitAll'],
'/logout/**': ['permitAll'],
'/secure/**': ['ROLE_ADMIN'],
'/finance/**': ['ROLE_FINANCE', 'isFullyAuthenticated()'],
]
'/secure/**': ['ROLE_ADMIN', 'ROLE_SUPERUSER'],
'/secure/reallysecure/**': ['ROLE_SUPERUSER']
'/secure/reallysecure/**': ['ROLE_SUPERUSER']
'/secure/**': ['ROLE_ADMIN', 'ROLE_SUPERUSER']
grails.plugin.springsecurity.securityConfigType = "Requestmap"
for (String url in [
'/', '/index', '/index.gsp', '/**/favicon.ico',
'/assets/**', '/**/js/**', '/**/css/**', '/**/images/**',
'/login', '/login.*', '/login/*',
'/logout', '/logout.*', '/logout/*']) {
new Requestmap(url: url, configAttribute: 'permitAll').save()
}
new Requestmap(url: '/profile/**', configAttribute: 'ROLE_USER').save()
new Requestmap(url: '/admin/**', configAttribute: 'ROLE_ADMIN').save()
new Requestmap(url: '/admin/role/**', configAttribute: 'ROLE_SUPERVISOR').save()
new Requestmap(url: '/admin/user/**', configAttribute: 'ROLE_ADMIN,ROLE_SUPERVISOR').save()
new Requestmap(url: '/j_spring_security_switch_user',
configAttribute: 'ROLE_SWITCH_USER,isFullyAuthenticated()').save()
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 = "${message(code: 'default.created.message', args: [message(code: 'requestmap.label', default: 'Requestmap'), requestmapInstance.id])}"
redirect action: 'show', id: requestmapInstance.id
}
}
package com.yourcompany.yourapp
import grails.plugin.springsecurity.annotation.Secured
class SecureController {
@Secured(["hasRole('ROLE_ADMIN')"])
def someAction() {
...
}
@Secured(["authentication.name == 'ralph'"])
def someOtherAction() {
...
}
}
new Requestmap(url: "/secure/someAction",
configAttribute: "hasRole('ROLE_ADMIN')").save()
new Requestmap(url: "/secure/someOtherAction",
configAttribute: "authentication.name == 'ralph'").save()
grails.plugin.springsecurity.interceptUrlMap = [
'/secure/someAction': ["hasRole('ROLE_ADMIN')"],
'/secure/someOtherAction': ["authentication.name == 'ralph'"]
]
grails.plugin.springsecurity.securityConfigType = 'Annotation'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll'],
'/login/**': ['permitAll'],
'/logout/**': ['permitAll'],
'/dbconsole/**': ['permitAll']
]
grails.plugin.springsecurity.securityConfigType = 'Requestmap'
/* Esto debe ir en el archivo BootStrap.groovy */
for (String url in [
'/', '/index', '/index.gsp', '/assets/**',
'/**/js/**', '/**/css/**', '/**/images/**',
'/**/favicon.ico', '/login/**', '/logout/**', '/dbconsole/**']) {
new RequestMap(url: url, configAttribute: 'permitAll').save()
}
grails.plugin.springsecurity.securityConfigType = 'InterceptUrlMap'
grails.plugin.springsecurity.interceptUrlMap = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll'],
'/login/**': ['permitAll'],
'/logout/**': ['permitAll'],
'/dbconsole/**': ['permitAll']
]
package grails.plugin.springsecurity
import grails.converters.JSON
import javax.servlet.http.HttpServletResponse
import org.springframework.security.access.annotation.Secured
import org.springframework.security.authentication.AccountExpiredException
import org.springframework.security.authentication.CredentialsExpiredException
import org.springframework.security.authentication.DisabledException
import org.springframework.security.authentication.LockedException
import org.springframework.security.core.context.SecurityContextHolder as SCH
import org.springframework.security.web.WebAttributes
@Secured('permitAll')
class LoginController {
/**
* Dependency injection for the authenticationTrustResolver.
*/
def authenticationTrustResolver
/**
* Dependency injection for the springSecurityService.
*/
def springSecurityService
/**
* Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise.
*/
def index() {
if (springSecurityService.isLoggedIn()) {
redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl
}
else {
redirect action: 'auth', params: params
}
}
/**
* Show the login page.
*/
def auth() {
def config = SpringSecurityUtils.securityConfig
if (springSecurityService.isLoggedIn()) {
redirect uri: config.successHandler.defaultTargetUrl
return
}
String view = 'auth'
String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}"
render view: view, model: [postUrl: postUrl,
rememberMeParameter: config.rememberMe.parameter]
}
/**
* The redirect action for Ajax requests.
*/
def authAjax() {
response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl
response.sendError HttpServletResponse.SC_UNAUTHORIZED
}
/**
* Show denied page.
*/
def denied() {
if (springSecurityService.isLoggedIn() &&
authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) {
// have cookie but the page is guarded with IS_AUTHENTICATED_FULLY
redirect action: 'full', params: params
}
}
/**
* Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page.
*/
def full() {
def config = SpringSecurityUtils.securityConfig
render view: 'auth', params: params,
model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication),
postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"]
}
/**
* Callback after a failed login. Redirects to the auth page with a warning message.
*/
def authfail() {
String msg = ''
def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION]
if (exception) {
if (exception instanceof AccountExpiredException) {
msg = g.message(code: "springSecurity.errors.login.expired")
}
else if (exception instanceof CredentialsExpiredException) {
msg = g.message(code: "springSecurity.errors.login.passwordExpired")
}
else if (exception instanceof DisabledException) {
msg = g.message(code: "springSecurity.errors.login.disabled")
}
else if (exception instanceof LockedException) {
msg = g.message(code: "springSecurity.errors.login.locked")
}
else {
msg = g.message(code: "springSecurity.errors.login.fail")
}
}
if (springSecurityService.isAjax(request)) {
render([error: msg] as JSON)
}
else {
flash.message = msg
redirect action: 'auth', params: params
}
}
/**
* The Ajax success redirect url.
*/
def ajaxSuccess() {
render([success: true, username: springSecurityService.authentication.name] as JSON)
}
/**
* The Ajax denied redirect url.
*/
def ajaxDenied() {
render([error: 'access denied'] as JSON)
}
}
package grails.plugin.springsecurity
import javax.servlet.http.HttpServletResponse
import org.springframework.security.access.annotation.Secured
@Secured('permitAll')
class LogoutController {
/**
* Index action. Redirects to the Spring security logout uri.
*/
def index() {
if (!request.post && SpringSecurityUtils.getSecurityConfig().logout.postOnly) {
response.sendError HttpServletResponse.SC_METHOD_NOT_ALLOWED // 405
return
}
// TODO put any pre-logout code here
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
}
<sec:ifLoggedIn>
Welcome Back!
</sec:ifLoggedIn>
<sec:ifNotLoggedIn>
<g:link controller='login' action='auth'>
Login
</g:link>
</sec:ifNotLoggedIn>
<sec:ifAllGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">secure stuff here</sec:ifAllGranted>
<sec:ifAnyGranted roles="ROLE_ADMIN,ROLE_SUPERVISOR">secure stuff here</sec:ifAnyGranted>
<sec:ifNotGranted roles="ROLE_USER">non-user stuff here</sec:ifNotGranted>
<sec:loggedInUserInfo field="username"/>
<sec:ifLoggedIn>
Welcome Back <sec:username/>!
</sec:ifLoggedIn>
<sec:ifNotLoggedIn>
<g:link controller='login' action='auth'>Login</g:link>
</sec:ifNotLoggedIn>
<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>
<sec:access controller='admin' action='user'>
<g:link controller='admin' action='user'>
Manage Users
</g:link>
</sec:access>
<sec:noAccess expression="hasRole('ROLE_USER')">
You're not a user
</sec:noAccess>
class SomeController {
def springSecurityService
def someAction() {
def user = springSecurityService.currentUser
...
}
}
class SomeController {
def springSecurityService
def someAction() {
if (springSecurityService.isLoggedIn()) {
...
}
else {
...
}
}
}
class SomeController {
def springSecurityService
def someAction() {
def auth = springSecurityService.authentication
String username = auth.username
def authorities = auth.authorities // a Collection of GrantedAuthority
boolean authenticated = auth.authenticated
...
}
}
class SomeController {
def springSecurityService
def someAction() {
def principal = springSecurityService.principal
String username = principal.username
def authorities = principal.authorities // a Collection of GrantedAuthority
boolean enabled = principal.enabled
…
}
}
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 some 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
}
}
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
}
}
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
}
}
}
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
}
}
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 some 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
}
}
grails.plugin.springsecurity.ipRestrictions = [
'/pattern1/**': '123.234.345.456',
'/pattern2/**': '10.0.0.0/8',
'/pattern3/**': ['10.10.200.42', '10.10.200.63']
]