Merge branch '5.7.x' into 5.8.x

Closes gh-13405
This commit is contained in:
Rob Winch
2023-06-18 21:32:35 -05:00
108 changed files with 5712 additions and 3422 deletions

View File

@@ -29,8 +29,10 @@ For earlier versions, please read about similar support with <<jc-enable-global-
For example, the following would enable Spring Security's `@PreAuthorize` annotation:
.Method Security Configuration
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableMethodSecurity
@@ -39,7 +41,8 @@ public class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableMethodSecurity
@@ -48,20 +51,23 @@ class MethodSecurityConfig {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security/>
----
====
======
Adding an annotation to a method (on a class or interface) would then limit the access to that method accordingly.
Spring Security's native annotation support defines a set of attributes for the method.
These will be passed to the `DefaultAuthorizationMethodInterceptorChain` for it to make the actual decision:
.Method Security Annotation Usage
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
public interface BankService {
@@ -76,7 +82,8 @@ public interface BankService {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
interface BankService {
@@ -90,13 +97,15 @@ interface BankService {
fun post(account : Account, amount : Double) : Account
}
----
====
======
You can enable support for Spring Security's `@Secured` annotation using:
.@Secured Configuration
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableMethodSecurity(securedEnabled = true)
@@ -105,7 +114,8 @@ public class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableMethodSecurity(securedEnabled = true)
@@ -114,18 +124,21 @@ class MethodSecurityConfig {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security secured-enabled="true"/>
----
====
======
or JSR-250 using:
.JSR-250 Configuration
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableMethodSecurity(jsr250Enabled = true)
@@ -134,7 +147,8 @@ public class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableMethodSecurity(jsr250Enabled = true)
@@ -143,12 +157,13 @@ class MethodSecurityConfig {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security jsr250-enabled="true"/>
----
====
======
=== Customizing Authorization
@@ -158,8 +173,10 @@ Spring Security's `@PreAuthorize`, `@PostAuthorize`, `@PreFilter`, and `@PostFil
If you need to customize the way that expressions are handled, you can expose a custom `MethodSecurityExpressionHandler`, like so:
.Custom MethodSecurityExpressionHandler
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@Bean
@@ -170,7 +187,8 @@ static MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
companion object {
@@ -183,7 +201,8 @@ companion object {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security>
@@ -195,7 +214,7 @@ companion object {
<property name="trustResolver" ref="myCustomTrustResolver"/>
</bean>
----
====
======
[TIP]
====
@@ -208,8 +227,10 @@ Also, for role-based authorization, Spring Security adds a default `ROLE_` prefi
You can configure the authorization rules to use a different prefix by exposing a `GrantedAuthorityDefaults` bean, like so:
.Custom MethodSecurityExpressionHandler
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@Bean
@@ -218,7 +239,8 @@ static GrantedAuthorityDefaults grantedAuthorityDefaults() {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
companion object {
@@ -229,7 +251,8 @@ companion object {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security/>
@@ -238,7 +261,7 @@ companion object {
<constructor-arg value="MYPREFIX_"/>
</bean>
----
====
======
[TIP]
====
@@ -261,8 +284,10 @@ If that authorization denies access, the value is not returned, and an `AccessDe
To recreate what adding `@EnableMethodSecurity` does by default, you would publish the following configuration:
.Full Pre-post Method Security Configuration
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableMethodSecurity(prePostEnabled = false)
@@ -293,7 +318,8 @@ class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableMethodSecurity(prePostEnabled = false)
@@ -324,7 +350,8 @@ class MethodSecurityConfig {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security pre-post-enabled="false"/>
@@ -342,15 +369,17 @@ class MethodSecurityConfig {
<bean id="postFilterAuthorizationMethodInterceptor"
class="org.springframework.security.authorization.method.PostFilterAuthorizationMethodInterceptor"/>
----
====
======
Notice that Spring Security's method security is built using Spring AOP.
So, interceptors are invoked based on the order specified.
This can be customized by calling `setOrder` on the interceptor instances like so:
.Publish Custom Advisor
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@Bean
@@ -362,7 +391,8 @@ Advisor postFilterAuthorizationMethodInterceptor() {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@Bean
@@ -374,7 +404,8 @@ fun postFilterAuthorizationMethodInterceptor() : Advisor {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<bean id="postFilterAuthorizationMethodInterceptor"
@@ -383,14 +414,16 @@ fun postFilterAuthorizationMethodInterceptor() : Advisor {
value="#{T(org.springframework.security.authorization.method.AuthorizationInterceptorsOrder).POST_AUTHORIZE.getOrder() -1}"/>
</bean>
----
====
======
You may want to only support `@PreAuthorize` in your application, in which case you can do the following:
.Only @PreAuthorize Configuration
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableMethodSecurity(prePostEnabled = false)
@@ -403,7 +436,8 @@ class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableMethodSecurity(prePostEnabled = false)
@@ -416,7 +450,8 @@ class MethodSecurityConfig {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security pre-post-enabled="false"/>
@@ -427,7 +462,7 @@ class MethodSecurityConfig {
class="org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor"
factory-method="preAuthorize"/>
----
====
======
Or, you may have a custom before-method `AuthorizationManager` that you want to add to the list.
@@ -436,9 +471,11 @@ In this case, you will need to tell Spring Security both the `AuthorizationManag
Thus, you can configure Spring Security to invoke your `AuthorizationManager` in between `@PreAuthorize` and `@PostAuthorize` like so:
.Custom Before Advisor
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableMethodSecurity
@@ -456,7 +493,8 @@ class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableMethodSecurity
@@ -474,7 +512,8 @@ class MethodSecurityConfig {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security/>
@@ -496,7 +535,7 @@ class MethodSecurityConfig {
value="#{T(org.springframework.security.authorization.method.AuthorizationInterceptorsOrder).PRE_AUTHORIZE_ADVISOR_ORDER.getOrder() + 1}"/>
</bean>
----
====
======
[TIP]
====
@@ -509,8 +548,10 @@ After-method authorization is generally concerned with analysing the return valu
For example, you might have a method that confirms that the account requested actually belongs to the logged-in user like so:
.@PostAuthorize example
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
public interface BankService {
@@ -521,7 +562,8 @@ public interface BankService {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
interface BankService {
@@ -531,7 +573,7 @@ interface BankService {
fun readAccount(id : Long) : Account
}
----
====
======
You can supply your own `AuthorizationMethodInterceptor` to customize how access to the return value is evaluated.
@@ -539,8 +581,10 @@ For example, if you have your own custom annotation, you can configure it like s
.Custom After Advisor
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableMethodSecurity
@@ -556,7 +600,8 @@ class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableMethodSecurity
@@ -572,7 +617,8 @@ class MethodSecurityConfig {
}
----
.Xml
Xml::
+
[source,xml,role="secondary"]
----
<sec:method-security/>
@@ -594,7 +640,7 @@ class MethodSecurityConfig {
value="#{T(org.springframework.security.authorization.method.AuthorizationInterceptorsOrder).PRE_AUTHORIZE_ADVISOR_ORDER.getOrder() + 1}"/>
</bean>
----
====
======
and it will be invoked after the `@PostAuthorize` interceptor.
@@ -604,8 +650,10 @@ and it will be invoked after the `@PostAuthorize` interceptor.
We can enable annotation-based security using the `@EnableGlobalMethodSecurity` annotation on any `@Configuration` instance.
For example, the following would enable Spring Security's `@Secured` annotation.
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableGlobalMethodSecurity(securedEnabled = true)
@@ -614,7 +662,8 @@ public class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableGlobalMethodSecurity(securedEnabled = true)
@@ -622,14 +671,16 @@ open class MethodSecurityConfig {
// ...
}
----
====
======
Adding an annotation to a method (on a class or interface) would then limit the access to that method accordingly.
Spring Security's native annotation support defines a set of attributes for the method.
These will be passed to the AccessDecisionManager for it to make the actual decision:
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
public interface BankService {
@@ -645,7 +696,8 @@ public Account post(Account account, double amount);
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
interface BankService {
@@ -659,12 +711,14 @@ interface BankService {
fun post(account: Account, amount: Double): Account
}
----
====
======
Support for JSR-250 annotations can be enabled using
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@@ -673,7 +727,8 @@ public class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@@ -681,13 +736,15 @@ open class MethodSecurityConfig {
// ...
}
----
====
======
These are standards-based and allow simple role-based constraints to be applied but do not have the power Spring Security's native annotations.
To use the new expression-based syntax, you would use
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableGlobalMethodSecurity(prePostEnabled = true)
@@ -696,7 +753,8 @@ public class MethodSecurityConfig {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableGlobalMethodSecurity(prePostEnabled = true)
@@ -704,12 +762,14 @@ open class MethodSecurityConfig {
// ...
}
----
====
======
and the equivalent Java code would be
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
public interface BankService {
@@ -725,7 +785,8 @@ public Account post(Account account, double amount);
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
interface BankService {
@@ -739,7 +800,7 @@ interface BankService {
fun post(account: Account, amount: Double): Account
}
----
====
======
== GlobalMethodSecurityConfiguration
@@ -747,8 +808,10 @@ Sometimes you may need to perform operations that are more complicated than are
For these instances, you can extend the `GlobalMethodSecurityConfiguration` ensuring that the `@EnableGlobalMethodSecurity` annotation is present on your subclass.
For example, if you wanted to provide a custom `MethodSecurityExpressionHandler`, you could use the following configuration:
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
@EnableGlobalMethodSecurity(prePostEnabled = true)
@@ -761,7 +824,8 @@ public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
@EnableGlobalMethodSecurity(prePostEnabled = true)
@@ -772,7 +836,7 @@ open class MethodSecurityConfig : GlobalMethodSecurityConfiguration() {
}
}
----
====
======
For additional information about methods that can be overridden, refer to the `GlobalMethodSecurityConfiguration` Javadoc.
@@ -791,8 +855,10 @@ Adding an annotation to a method (on an class or interface) would then limit the
Spring Security's native annotation support defines a set of attributes for the method.
These will be passed to the `AccessDecisionManager` for it to make the actual decision:
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
public interface BankService {
@@ -809,7 +875,8 @@ public Account post(Account account, double amount);
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
interface BankService {
@@ -823,7 +890,7 @@ interface BankService {
fun post(account: Account, amount: Double): Account
}
----
====
======
Support for JSR-250 annotations can be enabled using
@@ -842,8 +909,10 @@ To use the new expression-based syntax, you would use
and the equivalent Java code would be
====
.Java
[tabs]
======
Java::
+
[source,java,role="primary"]
----
public interface BankService {
@@ -859,7 +928,8 @@ public Account post(Account account, double amount);
}
----
.Kotlin
Kotlin::
+
[source,kotlin,role="secondary"]
----
interface BankService {
@@ -873,7 +943,7 @@ interface BankService {
fun post(account: Account, amount: Double): Account
}
----
====
======
Expression-based annotations are a good choice if you need to define simple rules that go beyond checking the role names against the user's list of authorities.