Skip to content

Commit cdf0cb6

Browse files
authored
Merge pull request #1187 from bkoehm/bkoehm.7.0.x.1179
Specify a domain class name when securityConfigType is Requestmap
2 parents 08ddb18 + 4e90cdf commit cdf0cb6

File tree

2 files changed

+51
-39
lines changed

2 files changed

+51
-39
lines changed

plugin-core/docs/src/docs/domainClasses/requestmapClass.adoc

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,37 @@ under the License.
1818
////
1919

2020
[[requestmapClass]]
21-
=== Requestmap Class
21+
=== Requestmap Domain Class
2222

23-
Optionally, use this class to store request mapping entries in the database instead of defining them with annotations or in `application.groovy`. This option makes the class configurable at runtime; you can add, remove and edit rules without restarting your application.
23+
Create and use a domain class to store request mapping entries in the database instead of defining them with annotations
24+
or in `application.groovy`. This option makes the rules configurable at runtime; you can add, remove and edit rules
25+
without restarting your application.
2426

2527
.Requestmap class configuration options
2628
[cols="30,30,40"]
2729
|====================
2830
| *Property* | *Default Value* | *Meaning*
2931

3032
|requestMap.className
31-
|_none_
32-
|requestmap class name
33+
|_none_ - set to your implementation
34+
|requestmap domain class
3335

3436
|requestMap.urlField
35-
|"`url`"
37+
|"url"
3638
|URL pattern property name
3739

3840
|requestMap.configAttributeField
39-
|"`configAttribute`"
41+
|"configAttribute"
4042
|authority pattern property name
4143

4244
|requestMap.httpMethodField
43-
|"`httpMethod`"
45+
|"httpMethod"
4446
|HTTP method property name (optional, does not have to exist in the class if you don't require URL/method security)
4547
|====================
4648

47-
Assuming you choose `com.mycompany.myapp` as your package, and `Requestmap` as your class name, you'll generate this class:
49+
Assuming you choose `com.mycompany.myapp` as your package, and `SecurityMapping` as your class name, you'll generate this class:
4850

4951
[source, groovy]
50-
.`Requestmap.groovy`
5152
----
5253
package com.mycompany.myapp
5354
@@ -60,7 +61,7 @@ import grails.compiler.GrailsCompileStatic
6061
@GrailsCompileStatic
6162
@EqualsAndHashCode(includes=['configAttribute', 'httpMethod', 'url'])
6263
@ToString(includes=['configAttribute', 'httpMethod', 'url'], cache=true, includeNames=true, includePackage=false)
63-
class RequestMap implements Serializable {
64+
class SecurityMapping implements Serializable {
6465
6566
private static final long serialVersionUID = 1
6667
@@ -69,15 +70,15 @@ class RequestMap implements Serializable {
6970
String url
7071
7172
static constraints = {
72-
configAttribute blank: false
73-
httpMethod nullable: true
74-
url blank: false, unique: 'httpMethod'
73+
configAttribute(blank: false)
74+
httpMethod(nullable: true)
75+
url(blank: false, unique: 'httpMethod')
7576
}
7677
7778
static mapping = {
78-
cache true
79+
cache(true)
7980
}
8081
}
8182
----
8283

83-
To use Requestmap entries to guard URLs, see <<requestmapInstances>>.
84+
To use database entries to guard URLs, see <<requestmapInstances>>.

plugin-core/docs/src/docs/requestMappings/requestmapInstances.adoc

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,68 +18,79 @@ under the License.
1818
////
1919

2020
[[requestmapInstances]]
21-
=== Requestmap Instances Stored in the Database
21+
=== Request Mappings Stored in the Database
2222

23-
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`.
23+
With this approach you create and use a domain class to store security mapping entries in the database.
2424

25-
To use `Requestmap` entries, specify `securityConfigType="Requestmap"`:
25+
The domain class must have the following properties:
26+
27+
* `url` - the secured URL pattern
28+
* `httpMethod` - the http method for which the rule applies (or null for all methods)
29+
* `configAttribute` - containing a comma-delimited list of required roles,
30+
SpEL expressions, and/or tokens such as `IS_AUTHENTICATED_FULLY`, `IS_AUTHENTICATED_REMEMBERED`,
31+
and `IS_AUTHENTICATED_ANONYMOUSLY`
32+
33+
To use database-backed url security mappings, use the following configuration:
2634

2735
[source,groovy]
28-
.Listing {counter:listing}. Specifying `securityConfigType` as "`Requestmap`"
36+
.Listing {counter:listing}. Configuring database-backed url security rules
2937
----
30-
grails.plugin.springsecurity.securityConfigType = "Requestmap"
38+
grails.plugin.springsecurity.securityConfigType = 'Requestmap'
39+
grails.plugin.springsecurity.requestMap.className = 'com.mycompany.myapp.SecurityMapping'
3140
----
3241

33-
You create `Requestmap` entries as you create entries in any Grails domain class:
42+
See <<requestmapClass>> for an example request map domain class.
43+
44+
You create request map entries as you create entries in any Grails domain class:
3445

3546
[source,groovy]
36-
.Listing {counter:listing}. Creating `Requestmap` entries
47+
.Listing {counter:listing}. Creating request map entries
3748
----
3849
for (String url in [
3950
'/', '/error', '/index', '/index.gsp', '/**/favicon.ico', '/shutdown',
4051
'/assets/**', '/**/js/**', '/**/css/**', '/**/images/**',
4152
'/login', '/login.*', '/login/*',
4253
'/logout', '/logout.*', '/logout/*']) {
43-
new Requestmap(url: url, configAttribute: 'permitAll').save()
54+
new SecurityMapping(url: url, configAttribute: 'permitAll').save()
4455
}
4556
46-
new Requestmap(url: '/profile/**', configAttribute: 'ROLE_USER').save()
47-
new Requestmap(url: '/admin/**', configAttribute: 'ROLE_ADMIN').save()
48-
new Requestmap(url: '/admin/role/**', configAttribute: 'ROLE_SUPERVISOR').save()
49-
new Requestmap(url: '/admin/user/**',
57+
new SecurityMapping(url: '/profile/**', configAttribute: 'ROLE_USER').save()
58+
new SecurityMapping(url: '/admin/**', configAttribute: 'ROLE_ADMIN').save()
59+
new SecurityMapping(url: '/admin/role/**', configAttribute: 'ROLE_SUPERVISOR').save()
60+
new SecurityMapping(url: '/admin/user/**',
5061
configAttribute: 'ROLE_ADMIN,ROLE_SUPERVISOR').save()
51-
new Requestmap(url: '/login/impersonate',
62+
new SecurityMapping(url: '/login/impersonate',
5263
configAttribute: 'ROLE_SWITCH_USER,IS_AUTHENTICATED_FULLY').save()
5364
springSecurityService.clearCachedRequestmaps()
5465
----
5566

56-
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.
67+
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 satisfy the `IS_AUTHENTICATED` rule.
5768

58-
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.
69+
Unlike the `application.groovy` map approach (<<configGroovyMap>>), you do not need to revise the request map entry order because the plugin calculates the most specific rule that applies to the current request.
5970

60-
==== Requestmap Cache
71+
==== Request Map Cache
6172

62-
`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()`):
73+
Request map 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 `RequestSecurityRuleController` the `save` action should look like this (and the update and delete actions should similarly call `clearCachedRequestmaps()`):
6374

6475
[source,groovy]
6576
.Listing {counter:listing}. Calling `clearCachedRequestmaps()`
6677
----
67-
class RequestmapController {
78+
class SecurityMappingController {
6879
6980
def springSecurityService
7081
71-
...
82+
//...
7283
73-
def save(Requestmap requestmap) {
74-
if (!requestmap.save(flush: true)) {
75-
render view: 'create', model: [requestmapInstance: requestmap]
84+
def save(SecurityMapping mapping) {
85+
if (!mapping.save(flush: true)) {
86+
render(view: 'create', model: [instance: mapping])
7687
return
7788
}
7889
7990
springSecurityService.clearCachedRequestmaps()
8091
81-
flash.message = ...
82-
redirect action: 'show', id: requestmap.id
92+
flash.message = 'Mapping saved'
93+
redirect(action: 'show', id: mapping.id)
8394
}
8495
}
8596
----

0 commit comments

Comments
 (0)