| [[requestmapInstances]] |
| === Requestmap Instances Stored in the Database |
| |
| With this approach you use the `Requestmap` domain class to store mapping entries in the database. `Requestmap` has a `url` property that contains the secured URL pattern and a `configAttribute` property containing a comma-delimited list of required roles, SpEL expressions, and/or tokens such as `IS_AUTHENTICATED_FULLY`, `IS_AUTHENTICATED_REMEMBERED`, and `IS_AUTHENTICATED_ANONYMOUSLY`. |
| |
| To use `Requestmap` entries, specify `securityConfigType="Requestmap"`: |
| |
| [source,groovy] |
| .Listing {counter:listing}. Specifying `securityConfigType` as "`Requestmap`" |
| ---- |
| grails.plugin.springsecurity.securityConfigType = "Requestmap" |
| ---- |
| |
| You create `Requestmap` entries as you create entries in any Grails domain class: |
| |
| [source,groovy] |
| .Listing {counter:listing}. Creating `Requestmap` entries |
| ---- |
| for (String url in [ |
| '/', '/error', '/index', '/index.gsp', '/**/favicon.ico', '/shutdown', |
| '/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: '/login/impersonate', |
| configAttribute: 'ROLE_SWITCH_USER,IS_AUTHENTICATED_FULLY').save() |
| springSecurityService.clearCachedRequestmaps() |
| ---- |
| |
| The `configAttribute` value can have a single value or have multiple comma-delimited values. In this example only users with `ROLE_ADMIN` or `ROLE_SUPERVISOR` can access `/admin/user/pass:[**]` urls, and only users with `ROLE_SWITCH_USER` can access the switch-user url (`/login/impersonate`) and in addition must be authenticated fully, i.e. not using a remember-me cookie. Note that when specifying multiple roles, the user must have at least one of them, but when combining `IS_AUTHENTICATED_FULLY`, `IS_AUTHENTICATED_REMEMBERED`, or `IS_AUTHENTICATED_ANONYMOUSLY` with one or more roles means the user must have one of the roles and satisty the `IS_AUTHENTICATED` rule. |
| |
| Unlike the `application.groovy` Map approach (<<configGroovyMap>>), you do not need to revise the `Requestmap` entry order because the plugin calculates the most specific rule that applies to the current request. |
| |
| ==== Requestmap Cache |
| |
| `Requestmap` entries are cached for performance, but caching affects runtime configurability. If you create, edit, or delete an instance, the cache must be flushed and repopulated to be consistent with the database. You can call `springSecurityService.clearCachedRequestmaps()` to do this. For example, if you create a `RequestmapController` the `save` action should look like this (and the update and delete actions should similarly call `clearCachedRequestmaps()`): |
| |
| [source,groovy] |
| .Listing {counter:listing}. Calling `clearCachedRequestmaps()` |
| ---- |
| class RequestmapController { |
| |
| def springSecurityService |
| |
| ... |
| |
| def save(Requestmap requestmap) { |
| if (!requestmap.save(flush: true)) { |
| render view: 'create', model: [requestmapInstance: requestmap] |
| return |
| } |
| |
| springSecurityService.clearCachedRequestmaps() |
| |
| flash.message = ... |
| redirect action: 'show', id: requestmap.id |
| } |
| } |
| ---- |