Skip to content

Commit 3205671

Browse files
committed
Add expression based Kotlin samples
Issue gh-8172
1 parent 0286d36 commit 3205671

File tree

1 file changed

+115
-9
lines changed

1 file changed

+115
-9
lines changed

docs/manual/src/docs/asciidoc/_includes/servlet/authorization/expression-based.adoc

Lines changed: 115 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ So if you aren't using the namespace and want to use expressions, you will have
114114
If you wish to extend the expressions that are available, you can easily refer to any Spring Bean you expose.
115115
For example, assuming you have a Bean with the name of `webSecurity` that contains the following method signature:
116116

117-
[source,java]
117+
====
118+
.Java
119+
[source,java,role="primary"]
118120
----
119121
public class WebSecurity {
120122
public boolean check(Authentication authentication, HttpServletRequest request) {
@@ -123,6 +125,17 @@ public class WebSecurity {
123125
}
124126
----
125127
128+
.Kotlin
129+
[source,kotlin,role="secondary"]
130+
----
131+
class WebSecurity {
132+
fun check(authentication: Authentication?, request: HttpServletRequest?): Boolean {
133+
// ...
134+
}
135+
}
136+
----
137+
====
138+
126139
You could refer to the method using:
127140

128141
.Refer to method
@@ -167,7 +180,9 @@ For example, consider a RESTful application that looks up a user by id from the
167180
You can easily refer to the path variable by placing it in the pattern.
168181
For example, if you had a Bean with the name of `webSecurity` that contains the following method signature:
169182

170-
[source,java]
183+
====
184+
.Java
185+
[source,java,role="primary"]
171186
----
172187
public class WebSecurity {
173188
public boolean checkUserId(Authentication authentication, int id) {
@@ -176,6 +191,17 @@ public class WebSecurity {
176191
}
177192
----
178193
194+
.Kotlin
195+
[source,kotlin,role="secondary"]
196+
----
197+
class WebSecurity {
198+
fun checkUserId(authentication: Authentication?, id: Int): Boolean {
199+
// ...
200+
}
201+
}
202+
----
203+
====
204+
179205
You could refer to the method using:
180206

181207
.Path Variables
@@ -234,22 +260,42 @@ Their use is enabled through the `global-method-security` namespace element:
234260
The most obviously useful annotation is `@PreAuthorize` which decides whether a method can actually be invoked or not.
235261
For example (from the "Contacts" sample application)
236262

237-
[source,java]
263+
====
264+
.Java
265+
[source,java,role="primary"]
238266
----
239267
@PreAuthorize("hasRole('USER')")
240268
public void create(Contact contact);
241269
----
242270
271+
.Kotlin
272+
[source,kotlin,role="secondary"]
273+
----
274+
@PreAuthorize("hasRole('USER')")
275+
fun create(contact: Contact?)
276+
----
277+
====
278+
243279
which means that access will only be allowed for users with the role "ROLE_USER".
244280
Obviously the same thing could easily be achieved using a traditional configuration and a simple configuration attribute for the required role.
245281
But what about:
246282

247-
[source,java]
283+
====
284+
.Java
285+
[source,java,role="primary"]
248286
----
249287
@PreAuthorize("hasPermission(#contact, 'admin')")
250288
public void deletePermission(Contact contact, Sid recipient, Permission permission);
251289
----
252290
291+
.Kotlin
292+
[source,kotlin,role="secondary"]
293+
----
294+
@PreAuthorize("hasPermission(#contact, 'admin')")
295+
fun deletePermission(contact: Contact?, recipient: Sid?, permission: Permission?)
296+
----
297+
====
298+
253299
Here we're actually using a method argument as part of the expression to decide whether the current user has the "admin"permission for the given contact.
254300
The built-in `hasPermission()` expression is linked into the Spring Security ACL module through the application context, as we'll <<el-permission-evaluator,see below>>.
255301
You can access any of the method arguments by name as expression variables.
@@ -264,7 +310,9 @@ For example:
264310

265311
+
266312

267-
[source,java]
313+
====
314+
.Java
315+
[source,java,role="primary"]
268316
----
269317
import org.springframework.security.access.method.P;
270318
@@ -274,6 +322,18 @@ import org.springframework.security.access.method.P;
274322
public void doSomething(@P("c") Contact contact);
275323
----
276324
325+
.Kotlin
326+
[source,kotlin,role="secondary"]
327+
----
328+
import org.springframework.security.access.method.P
329+
330+
...
331+
332+
@PreAuthorize("#c.name == authentication.name")
333+
fun doSomething(@P("c") contact: Contact?)
334+
----
335+
====
336+
277337
+
278338

279339
Behind the scenes this is implemented using `AnnotationParameterNameDiscoverer` which can be customized to support the value attribute of any specified annotation.
@@ -284,7 +344,9 @@ For example:
284344

285345
+
286346

287-
[source,java]
347+
====
348+
.Java
349+
[source,java,role="primary"]
288350
----
289351
import org.springframework.data.repository.query.Param;
290352
@@ -294,6 +356,18 @@ import org.springframework.data.repository.query.Param;
294356
Contact findContactByName(@Param("n") String name);
295357
----
296358
359+
.Kotlin
360+
[source,kotlin,role="secondary"]
361+
----
362+
import org.springframework.data.repository.query.Param
363+
364+
...
365+
366+
@PreAuthorize("#n == authentication.name")
367+
fun findContactByName(@Param("n") name: String?): Contact?
368+
----
369+
====
370+
297371
+
298372

299373
Behind the scenes this is implemented using `AnnotationParameterNameDiscoverer` which can be customized to support the value attribute of any specified annotation.
@@ -311,12 +385,22 @@ Any Spring-EL functionality is available within the expression, so you can also
311385
For example, if you wanted a particular method to only allow access to a user whose username matched that of the contact, you could write
312386
--
313387

314-
[source,java]
388+
====
389+
.Java
390+
[source,java,role="primary"]
315391
----
316392
@PreAuthorize("#contact.name == authentication.name")
317393
public void doSomething(Contact contact);
318394
----
319395
396+
.Kotlin
397+
[source,kotlin,role="secondary"]
398+
----
399+
@PreAuthorize("#contact.name == authentication.name")
400+
fun doSomething(contact: Contact?)
401+
----
402+
====
403+
320404
Here we are accessing another built-in expression, `authentication`, which is the `Authentication` stored in the security context.
321405
You can also access its "principal" property directly, using the expression `principal`.
322406
The value will often be a `UserDetails` instance, so you might use an expression like `principal.username` or `principal.enabled`.
@@ -333,13 +417,24 @@ Spring Security supports filtering of collections, arrays, maps and streams usin
333417
This is most commonly performed on the return value of a method.
334418
For example:
335419

336-
[source,java]
420+
====
421+
.Java
422+
[source,java,role="primary"]
337423
----
338424
@PreAuthorize("hasRole('USER')")
339425
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
340426
public List<Contact> getAll();
341427
----
342428
429+
.Kotlin
430+
[source,kotlin,role="secondary"]
431+
----
432+
@PreAuthorize("hasRole('USER')")
433+
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
434+
fun getAll(): List<Contact?>
435+
----
436+
====
437+
343438
When using the `@PostFilter` annotation, Spring Security iterates through the returned collection or map and removes any elements for which the supplied expression is false.
344439
For an array, a new array instance will be returned containing filtered elements.
345440
The name `filterObject` refers to the current object in the collection.
@@ -412,13 +507,24 @@ For example, consider the following:
412507

413508
Instead of repeating this everywhere, we can create a meta annotation that can be used instead.
414509

415-
[source,java]
510+
====
511+
.Java
512+
[source,java,role="primary"]
416513
----
417514
@Retention(RetentionPolicy.RUNTIME)
418515
@PreAuthorize("#contact.name == authentication.name")
419516
public @interface ContactPermission {}
420517
----
421518
519+
.Kotlin
520+
[source,kotlin,role="secondary"]
521+
----
522+
@Retention(AnnotationRetention.RUNTIME)
523+
@PreAuthorize("#contact.name == authentication.name")
524+
annotation class ContactPermission
525+
----
526+
====
527+
422528
Meta annotations can be used for any of the Spring Security method security annotations.
423529
In order to remain compliant with the specification JSR-250 annotations do not support meta annotations.
424530

0 commit comments

Comments
 (0)