parent
0286d368c3
commit
320567128a
|
@ -114,7 +114,9 @@ So if you aren't using the namespace and want to use expressions, you will have
|
||||||
If you wish to extend the expressions that are available, you can easily refer to any Spring Bean you expose.
|
If you wish to extend the expressions that are available, you can easily refer to any Spring Bean you expose.
|
||||||
For example, assuming you have a Bean with the name of `webSecurity` that contains the following method signature:
|
For example, assuming you have a Bean with the name of `webSecurity` that contains the following method signature:
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
public class WebSecurity {
|
public class WebSecurity {
|
||||||
public boolean check(Authentication authentication, HttpServletRequest request) {
|
public boolean check(Authentication authentication, HttpServletRequest request) {
|
||||||
|
@ -123,6 +125,17 @@ public class WebSecurity {
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
class WebSecurity {
|
||||||
|
fun check(authentication: Authentication?, request: HttpServletRequest?): Boolean {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
You could refer to the method using:
|
You could refer to the method using:
|
||||||
|
|
||||||
.Refer to method
|
.Refer to method
|
||||||
|
@ -167,7 +180,9 @@ For example, consider a RESTful application that looks up a user by id from the
|
||||||
You can easily refer to the path variable by placing it in the pattern.
|
You can easily refer to the path variable by placing it in the pattern.
|
||||||
For example, if you had a Bean with the name of `webSecurity` that contains the following method signature:
|
For example, if you had a Bean with the name of `webSecurity` that contains the following method signature:
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
public class WebSecurity {
|
public class WebSecurity {
|
||||||
public boolean checkUserId(Authentication authentication, int id) {
|
public boolean checkUserId(Authentication authentication, int id) {
|
||||||
|
@ -176,6 +191,17 @@ public class WebSecurity {
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
class WebSecurity {
|
||||||
|
fun checkUserId(authentication: Authentication?, id: Int): Boolean {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
You could refer to the method using:
|
You could refer to the method using:
|
||||||
|
|
||||||
.Path Variables
|
.Path Variables
|
||||||
|
@ -234,22 +260,42 @@ Their use is enabled through the `global-method-security` namespace element:
|
||||||
The most obviously useful annotation is `@PreAuthorize` which decides whether a method can actually be invoked or not.
|
The most obviously useful annotation is `@PreAuthorize` which decides whether a method can actually be invoked or not.
|
||||||
For example (from the "Contacts" sample application)
|
For example (from the "Contacts" sample application)
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
@PreAuthorize("hasRole('USER')")
|
@PreAuthorize("hasRole('USER')")
|
||||||
public void create(Contact contact);
|
public void create(Contact contact);
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
@PreAuthorize("hasRole('USER')")
|
||||||
|
fun create(contact: Contact?)
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
which means that access will only be allowed for users with the role "ROLE_USER".
|
which means that access will only be allowed for users with the role "ROLE_USER".
|
||||||
Obviously the same thing could easily be achieved using a traditional configuration and a simple configuration attribute for the required role.
|
Obviously the same thing could easily be achieved using a traditional configuration and a simple configuration attribute for the required role.
|
||||||
But what about:
|
But what about:
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
@PreAuthorize("hasPermission(#contact, 'admin')")
|
@PreAuthorize("hasPermission(#contact, 'admin')")
|
||||||
public void deletePermission(Contact contact, Sid recipient, Permission permission);
|
public void deletePermission(Contact contact, Sid recipient, Permission permission);
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
@PreAuthorize("hasPermission(#contact, 'admin')")
|
||||||
|
fun deletePermission(contact: Contact?, recipient: Sid?, permission: Permission?)
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
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.
|
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.
|
||||||
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>>.
|
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>>.
|
||||||
You can access any of the method arguments by name as expression variables.
|
You can access any of the method arguments by name as expression variables.
|
||||||
|
@ -264,7 +310,9 @@ For example:
|
||||||
|
|
||||||
+
|
+
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
import org.springframework.security.access.method.P;
|
import org.springframework.security.access.method.P;
|
||||||
|
|
||||||
|
@ -274,6 +322,18 @@ import org.springframework.security.access.method.P;
|
||||||
public void doSomething(@P("c") Contact contact);
|
public void doSomething(@P("c") Contact contact);
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
import org.springframework.security.access.method.P
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
@PreAuthorize("#c.name == authentication.name")
|
||||||
|
fun doSomething(@P("c") contact: Contact?)
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
+
|
+
|
||||||
|
|
||||||
Behind the scenes this is implemented using `AnnotationParameterNameDiscoverer` which can be customized to support the value attribute of any specified annotation.
|
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:
|
||||||
|
|
||||||
+
|
+
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
@ -294,6 +356,18 @@ import org.springframework.data.repository.query.Param;
|
||||||
Contact findContactByName(@Param("n") String name);
|
Contact findContactByName(@Param("n") String name);
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
import org.springframework.data.repository.query.Param
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
@PreAuthorize("#n == authentication.name")
|
||||||
|
fun findContactByName(@Param("n") name: String?): Contact?
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
+
|
+
|
||||||
|
|
||||||
Behind the scenes this is implemented using `AnnotationParameterNameDiscoverer` which can be customized to support the value attribute of any specified annotation.
|
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
|
||||||
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
|
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
|
||||||
--
|
--
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
@PreAuthorize("#contact.name == authentication.name")
|
@PreAuthorize("#contact.name == authentication.name")
|
||||||
public void doSomething(Contact contact);
|
public void doSomething(Contact contact);
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
@PreAuthorize("#contact.name == authentication.name")
|
||||||
|
fun doSomething(contact: Contact?)
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
Here we are accessing another built-in expression, `authentication`, which is the `Authentication` stored in the security context.
|
Here we are accessing another built-in expression, `authentication`, which is the `Authentication` stored in the security context.
|
||||||
You can also access its "principal" property directly, using the expression `principal`.
|
You can also access its "principal" property directly, using the expression `principal`.
|
||||||
The value will often be a `UserDetails` instance, so you might use an expression like `principal.username` or `principal.enabled`.
|
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
|
||||||
This is most commonly performed on the return value of a method.
|
This is most commonly performed on the return value of a method.
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
@PreAuthorize("hasRole('USER')")
|
@PreAuthorize("hasRole('USER')")
|
||||||
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
|
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
|
||||||
public List<Contact> getAll();
|
public List<Contact> getAll();
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
@PreAuthorize("hasRole('USER')")
|
||||||
|
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
|
||||||
|
fun getAll(): List<Contact?>
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
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.
|
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.
|
||||||
For an array, a new array instance will be returned containing filtered elements.
|
For an array, a new array instance will be returned containing filtered elements.
|
||||||
The name `filterObject` refers to the current object in the collection.
|
The name `filterObject` refers to the current object in the collection.
|
||||||
|
@ -412,13 +507,24 @@ For example, consider the following:
|
||||||
|
|
||||||
Instead of repeating this everywhere, we can create a meta annotation that can be used instead.
|
Instead of repeating this everywhere, we can create a meta annotation that can be used instead.
|
||||||
|
|
||||||
[source,java]
|
====
|
||||||
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@PreAuthorize("#contact.name == authentication.name")
|
@PreAuthorize("#contact.name == authentication.name")
|
||||||
public @interface ContactPermission {}
|
public @interface ContactPermission {}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.Kotlin
|
||||||
|
[source,kotlin,role="secondary"]
|
||||||
|
----
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@PreAuthorize("#contact.name == authentication.name")
|
||||||
|
annotation class ContactPermission
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
Meta annotations can be used for any of the Spring Security method security annotations.
|
Meta annotations can be used for any of the Spring Security method security annotations.
|
||||||
In order to remain compliant with the specification JSR-250 annotations do not support meta annotations.
|
In order to remain compliant with the specification JSR-250 annotations do not support meta annotations.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue