From e61544c3976b92b0c7ba132120da291e8e4f8f42 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Fri, 18 Apr 2025 17:07:17 +0800 Subject: [PATCH 1/8] Improve OAuth2ResourceServerConfigurer to eliminate deprecated operations Signed-off-by: Yanming Zhou --- .../resource/OAuth2ResourceServerConfigurer.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java index e9a425d46d..f5ed36f790 100644 --- a/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java +++ b/config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/resource/OAuth2ResourceServerConfigurer.java @@ -138,6 +138,7 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy; * @author Josh Cummings * @author Evgeniy Cheban * @author Jerome Wacongne <ch4mp@c4-soft.com> + * @author Yanming Zhou * @since 5.1 * @see BearerTokenAuthenticationFilter * @see JwtAuthenticationProvider @@ -490,8 +491,10 @@ public final class OAuth2ResourceServerConfigurer new SpringOpaqueTokenIntrospector(this.introspectionUri, this.clientId, - this.clientSecret); + this.introspector = () -> SpringOpaqueTokenIntrospector.withIntrospectionUri(this.introspectionUri) + .clientId(this.clientId) + .clientSecret(this.clientSecret) + .build(); return this; } @@ -500,8 +503,10 @@ public final class OAuth2ResourceServerConfigurer new SpringOpaqueTokenIntrospector(this.introspectionUri, this.clientId, - this.clientSecret); + this.introspector = () -> SpringOpaqueTokenIntrospector.withIntrospectionUri(this.introspectionUri) + .clientId(this.clientId) + .clientSecret(this.clientSecret) + .build(); return this; } From 45b453f59b21816f9576d608c0ec8be956ae6175 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 6 May 2025 16:38:19 -0600 Subject: [PATCH 2/8] Add ACL Migration Steps --- docs/modules/ROOT/pages/migration-7/acl.adoc | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/modules/ROOT/pages/migration-7/acl.adoc diff --git a/docs/modules/ROOT/pages/migration-7/acl.adoc b/docs/modules/ROOT/pages/migration-7/acl.adoc new file mode 100644 index 0000000000..97c79e768f --- /dev/null +++ b/docs/modules/ROOT/pages/migration-7/acl.adoc @@ -0,0 +1,7 @@ += ACL + +== Favor `AclPermissionEvaluator` + +`AclEntryVoter`, `AclEntryAfterInvocationProvider`, and `AclPermissionEvaluator` provide the same service, plugged into different Spring Security APIs. Now that `AccessDecisionVoter` and `AfterInvocationProvider` are both deprecated, the corresponding ACL plugins are obsolete. + +As such, begin using `AclPermissionEvaluator` before updating to Spring Security 7. From c6bba384580303700bf641dbd64aafa8412a5ce2 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 6 May 2025 16:38:32 -0600 Subject: [PATCH 3/8] Update SAML 2.0 Migration Steps --- .../modules/ROOT/pages/migration-7/saml2.adoc | 239 ++++++++++++++++++ 1 file changed, 239 insertions(+) diff --git a/docs/modules/ROOT/pages/migration-7/saml2.adoc b/docs/modules/ROOT/pages/migration-7/saml2.adoc index eed236a64b..43da1be2b0 100644 --- a/docs/modules/ROOT/pages/migration-7/saml2.adoc +++ b/docs/modules/ROOT/pages/migration-7/saml2.adoc @@ -1,5 +1,17 @@ = Saml 2.0 Migrations +== Use OpenSAML 5 By Default + +OpenSAML 4.x is no longer supported by the OpenSAML team. +As such, Spring Security will default to using its `OpenSaml5` components in all cases. + +If you want to see how well your application will respond to this, do the following: + +1. Update your OpenSAML dependencies to 5.x +2. If you are constructing an `OpenSaml4XXX` Spring Security component, change it to `OpenSaml5`. + +If you cannot opt-in, then add the `opensaml-saml-api` and `opensaml-saml-impl` 4.x dependencies and exclude the 5.x dependencies from `spring-security-saml2-service-provider`. + == Continue Filter Chain When No Relying Party Found In Spring Security 6, `Saml2WebSsoAuthenticationFilter` throws an exception when the request URI matches, but no relying party registration is found. @@ -163,3 +175,230 @@ val responseValidator = ResponseValidator.withDefaults { responseToken: Response provider.setResponseValidator(responseValidator) ---- ====== + +== `RelyingPartyRegistration` Improvements + +`RelyingPartyRegistration` links metadata from a relying party to metadata from an asserting party. + +To prepare for some improvements to the API, please take the following steps: + +1. If you are mutating a registration by using `RelyingPartyRegistration#withRelyingPartyRegistration`, instead call `RelyingPartyRegistration#mutate` +2. If you are providing or retrieving `AssertingPartyDetails`, use `getAssertingPartyMetadata` or `withAssertingPartyMetadata` instead. + +== `OpenSaml5AuthenticationProvider` Improvements + +Spring Security 7 will remove a handful of static factories from `OpenSaml5AuthenticationProvider` in favor of inner classes. +These inner classes simplify customization of the response validator, the assertion validator, and the response authentication converter. + +=== Response Validation + +Instead of doing: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +OpenSaml5AuthenticationProvider saml2AuthenticationProvider() { + OpenSaml5AuthenticationProvider saml2 = new OpenSaml5AuthenticationProvider(); + saml2.setResponseValidator((responseToken) -> OpenSamlAuthenticationProvider.createDefaultResponseValidator() + .andThen((result) -> result + .concat(myCustomValidator.convert(responseToken)) + )); + return saml2; +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun saml2AuthenticationProvider(): OpenSaml5AuthenticationProvider { + val saml2 = OpenSaml5AuthenticationProvider() + saml2.setResponseValidator { responseToken -> OpenSamlAuthenticationProvider.createDefaultResponseValidator() + .andThen { result -> result + .concat(myCustomValidator.convert(responseToken)) + } + } + return saml2 +} +---- +====== + +use `OpenSaml5AuthenticationProvider.ResponseValidator`: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +OpenSaml5AuthenticationProvider saml2AuthenticationProvider() { + OpenSaml5AuthenticationProvider saml2 = new OpenSaml5AuthenticationProvider(); + saml2.setResponseValidator(ResponseValidator.withDefaults(myCustomValidator)); + return saml2; +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun saml2AuthenticationProvider(): OpenSaml5AuthenticationProvider { + val saml2 = OpenSaml5AuthenticationProvider() + saml2.setResponseValidator(ResponseValidator.withDefaults(myCustomValidator)) + return saml2 +} +---- +====== + +=== Assertion Validation + +Instead of doing: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +OpenSaml5AuthenticationProvider saml2AuthenticationProvider() { + OpenSaml5AuthenticationProvider saml2 = new OpenSaml5AuthenticationProvider(); + authenticationProvider.setAssertionValidator(OpenSaml5AuthenticationProvider + .createDefaultAssertionValidatorWithParameters(assertionToken -> { + Map params = new HashMap<>(); + params.put(CLOCK_SKEW, Duration.ofMinutes(10).toMillis()); + // ... other validation parameters + return new ValidationContext(params); + }) + ); + return saml2; +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun saml2AuthenticationProvider(): OpenSaml5AuthenticationProvider { + val saml2 = OpenSaml5AuthenticationProvider() + authenticationProvider.setAssertionValidator(OpenSaml5AuthenticationProvider + .createDefaultAssertionValidatorWithParameters { -> + val params = HashMap() + params.put(CLOCK_SKEW, Duration.ofMinutes(10).toMillis()) + // ... other validation parameters + return ValidationContext(params) + } + ) + return saml2 +} +---- +====== + +use `OpenSaml5AuthenticationProvider.AssertionValidator`: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +OpenSaml5AuthenticationProvider saml2AuthenticationProvider() { + OpenSaml5AuthenticationProvider saml2 = new OpenSaml5AuthenticationProvider(); + Duration tenMinutes = Duration.ofMinutes(10); + authenticationProvider.setAssertionValidator(AssertionValidator.builder().clockSkew(tenMinutes).build()); + return saml2; +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun saml2AuthenticationProvider(): OpenSaml5AuthenticationProvider { + val saml2 = OpenSaml5AuthenticationProvider() + val tenMinutes = Duration.ofMinutes(10) + authenticationProvider.setAssertionValidator(AssertionValidator.builder().clockSkew(tenMinutes).build()) + return saml2 +} +---- +====== + +== Response Authentication Converter + +Instead of doing: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +Converter authenticationConverter() { + return (responseToken) -> { + Saml2Authentication authentication = OpenSaml5AutnenticationProvider.createDefaultResponseAuthenticationConverter() + .convert(responseToken); + // ... work with OpenSAML's Assertion object to extract the principal + return new Saml2Authentication(myPrincipal, authentication.getSaml2Response(), authentication.getAuthorities()); + }; +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun authenticationConverter(): Converter { + return { responseToken -> + val authentication = + OpenSaml5AutnenticationProvider.createDefaultResponseAuthenticationConverter().convert(responseToken) + // ... work with OpenSAML's Assertion object to extract the principal + return Saml2Authentication(myPrincipal, authentication.getSaml2Response(), authentication.getAuthorities()) + } +} +---- +====== + +use `OpenSaml5AuthenticationProvider.ResponseAuthenticationConverter`: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +ResponseAuthenticationConverter authenticationConverter() { + ResponseAuthenticationConverter authenticationConverter = new ResponseAuthenticationConverter(); + authenticationConverter.setPrincipalNameConverter((assertion) -> { + // ... work with OpenSAML's Assertion object to extract the principal + }); + return authenticationConverter; +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun authenticationConverter(): ResponseAuthenticationConverter { + val authenticationConverter = ResponseAuthenticationConverter() + authenticationConverter.setPrincipalNameConverter { assertion -> + // ... work with OpenSAML's Assertion object to extract the principal + } + return authenticationConverter +} +---- +====== From 084990736e55f5dea2e9edc825bfba72329a4342 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 6 May 2025 16:39:16 -0600 Subject: [PATCH 4/8] Move Opaque Token Migration Steps --- .../pages/migration-7/authentication.adoc | 66 ------------------ .../ROOT/pages/migration-7/oauth2.adoc | 67 +++++++++++++++++++ 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/docs/modules/ROOT/pages/migration-7/authentication.adoc b/docs/modules/ROOT/pages/migration-7/authentication.adoc index 9c5407ae00..7034702b5a 100644 --- a/docs/modules/ROOT/pages/migration-7/authentication.adoc +++ b/docs/modules/ROOT/pages/migration-7/authentication.adoc @@ -1,68 +1,2 @@ = Authentication Changes -== Opaque Token Credentials Will Be Encoded For You - -In order to comply more closely with the Introspection RFC, Spring Security's opaque token support will encode the client id and secret before creating the authorization header. -This change means you will no longer have to encode the client id and secret yourself. - -If your client id or secret contain URL-unsafe characters, then you can prepare yourself for this change by doing the following: - -=== Replace Usage of `introspectionClientCredentials` - -Since Spring Security can now do the encoding for you, replace xref:servlet/oauth2/resource-server/opaque-token.adoc#oauth2resourceserver-opaque-introspectionuri-dsl[using `introspectionClientCredentials`] with publishing the following `@Bean`: - -[tabs] -====== -Java:: -+ -[source,java,role="primary"] ----- -@Bean -OpaqueTokenIntrospector introspector() { - return SpringOpaqueTokenIntrospector.withIntrospectionUri(introspectionUri) - .clientId(unencodedClientId).clientSecret(unencodedClientSecret).build(); -} ----- - -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -@Bean -fun introspector(): OpaqueTokenIntrospector { - return SpringOpaqueTokenIntrospector.withIntrospectionUri(introspectionUri) - .clientId(unencodedClientId).clientSecret(unencodedClientSecret).build() -} ----- -====== - -The above will be the default in 7.0. - -If this setting gives you trouble or you cannot apply it for now, you can use the `RestOperations` constructor instead: - -[tabs] -====== -Java:: -+ -[source,java,role="primary"] ----- -@Bean -OpaqueTokenIntrospector introspector() { - RestTemplate rest = new RestTemplate(); - rest.addInterceptor(new BasicAuthenticationInterceptor(encodedClientId, encodedClientSecret)); - return new SpringOpaqueTokenIntrospector(introspectionUri, rest); -} ----- - -Kotlin:: -+ -[source,kotlin,role="secondary"] ----- -@Bean -fun introspector(): OpaqueTokenIntrospector { - val rest = RestTemplate() - rest.addInterceptor(BasicAuthenticationInterceptor(encodedClientId, encodedClientSecret)) - return SpringOpaqueTokenIntrospector(introspectionUri, rest) -} ----- -====== diff --git a/docs/modules/ROOT/pages/migration-7/oauth2.adoc b/docs/modules/ROOT/pages/migration-7/oauth2.adoc index 1c3b9b43e2..95cdc1bf71 100644 --- a/docs/modules/ROOT/pages/migration-7/oauth2.adoc +++ b/docs/modules/ROOT/pages/migration-7/oauth2.adoc @@ -170,3 +170,70 @@ fun jwtDecoder(): JwtDecoder { <2> - specify the list of validators you need, excluding `JwtTypeValidator` For additional guidance, please see the xref:servlet/oauth2/resource-server/jwt.adoc#oauth2resourceserver-jwt-validation[JwtDecoder Validators] section in the reference. + +== Opaque Token Credentials Will Be Encoded For You + +In order to comply more closely with the Introspection RFC, Spring Security's opaque token support will encode the client id and secret before creating the authorization header. +This change means you will no longer have to encode the client id and secret yourself. + +If your client id or secret contain URL-unsafe characters, then you can prepare yourself for this change by doing the following: + +=== Replace Usage of `introspectionClientCredentials` + +Since Spring Security can now do the encoding for you, replace xref:servlet/oauth2/resource-server/opaque-token.adoc#oauth2resourceserver-opaque-introspectionuri-dsl[using `introspectionClientCredentials`] with publishing the following `@Bean`: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +OpaqueTokenIntrospector introspector() { + return SpringOpaqueTokenIntrospector.withIntrospectionUri(introspectionUri) + .clientId(unencodedClientId).clientSecret(unencodedClientSecret).build(); +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun introspector(): OpaqueTokenIntrospector { + return SpringOpaqueTokenIntrospector.withIntrospectionUri(introspectionUri) + .clientId(unencodedClientId).clientSecret(unencodedClientSecret).build() +} +---- +====== + +The above will be the default in 7.0. + +If this setting gives you trouble or you cannot apply it for now, you can use the `RestOperations` constructor instead: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +OpaqueTokenIntrospector introspector() { + RestTemplate rest = new RestTemplate(); + rest.addInterceptor(new BasicAuthenticationInterceptor(encodedClientId, encodedClientSecret)); + return new SpringOpaqueTokenIntrospector(introspectionUri, rest); +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +@Bean +fun introspector(): OpaqueTokenIntrospector { + val rest = RestTemplate() + rest.addInterceptor(BasicAuthenticationInterceptor(encodedClientId, encodedClientSecret)) + return SpringOpaqueTokenIntrospector(introspectionUri, rest) +} +---- +====== From 74a25c3fc18901853f5c59f173a935d861aff681 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 6 May 2025 16:40:10 -0600 Subject: [PATCH 5/8] Add shouldFilterAllDispatcherTypes Migration Steps --- .../ROOT/pages/migration-7/configuration.adoc | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/docs/modules/ROOT/pages/migration-7/configuration.adoc b/docs/modules/ROOT/pages/migration-7/configuration.adoc index 0a06694f95..8d84e04ab4 100644 --- a/docs/modules/ROOT/pages/migration-7/configuration.adoc +++ b/docs/modules/ROOT/pages/migration-7/configuration.adoc @@ -123,3 +123,60 @@ In versions prior to 6.2, if you had a xref:servlet/configuration/java.adoc#jc-c However, starting from version 6.2, this method is deprecated and will be removed in 7.0 because it will no longer be possible to chain configurations using `.and()` once `.and()` is removed (see https://github.com/spring-projects/spring-security/issues/13067). Instead, it is recommended to use the new `.with(...)` method. For more information about how to use `.with(...)` please refer to the xref:servlet/configuration/java.adoc#jc-custom-dsls[Custom DSLs section]. + +== Use `dispatcherTypeMatchers` instead of `shouldFilterAllDispatcherTypes` + +If you are permitting the ERROR dispatch, you may be using `shouldFilterAllDispatcherTypes(false)` in the `auhorizeHttpRequests` DSL: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +http + .authorizeHttpRequests((authorize) -> authorize + .shouldFilterAllDispatcherTypes(false) + // ... + ) +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +http { + authorizeHttpRequests { + shouldFilterAllDispatcherTypes = false + // ... + } +} +---- +====== + +In preparation for 7, change this to use `dispatcherTypeMatchers`: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +http + .authorizHttpRequests((authorize) -> authorize + .dispatcherTypeMatchers(DispatcherType.ERROR).permitAll() + // ... + ) +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +http { + authorizeHttpRequests { + authorize(new DispatcherTypeRequestMatcher(DispatcherType.ERROR), permitAll()) + } +} +---- +====== From 84db5bb312d6afb2db38ab89278c350f48a0017d Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 6 May 2025 16:43:04 -0600 Subject: [PATCH 6/8] Add Cookie Customizer Migration Steps --- docs/modules/ROOT/pages/migration-7/web.adoc | 46 ++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/docs/modules/ROOT/pages/migration-7/web.adoc b/docs/modules/ROOT/pages/migration-7/web.adoc index 467f2663e8..248b719c0e 100644 --- a/docs/modules/ROOT/pages/migration-7/web.adoc +++ b/docs/modules/ROOT/pages/migration-7/web.adoc @@ -521,3 +521,49 @@ Xml:: ===== If you have several circumstances where HTTP is needed, consider using `OrRequestMatcher` to combine them into a single `RequestMatcher` instance. ===== + +== Use `setCookieCustomizer` instead of individual setters + +In favor of a simpler API, `CookieCsrfTokenRepository#setCookieCustomizer` allows you to change any aspect of the cookie, replacing `setCookieHttpOnly`, `setCookieMaxAge`, `setSecure`, and `setCookieDomain`. + +Change this: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +CookeCsrfTokenRepository csrf = CookeCsrfTokenRepository.withHttpOnlyFalse(); +csrf.setCookieMaxAge(86400) +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +val csrf = CookeCsrfTokenRepository.withHttpOnlyFalse() +csrf.setCookieMaxAge(86400) +---- +====== + +to this: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +CookeCsrfTokenRepository csrf = CookeCsrfTokenRepository.withHttpOnlyFalse(); +csrf.setCookieCustomizer((c) -> c.maxAge(86400)); +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +val csrf = CookeCsrfTokenRepository.withHttpOnlyFalse() +csrf.setCookieCustomizer { -> it.maxAge(86400) } +---- +====== From 211b1b7285f2994fc1dd24a442d15bde20e4b1ab Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 6 May 2025 16:44:20 -0600 Subject: [PATCH 7/8] Update Method Security Migration Steps --- .../ROOT/pages/migration-7/authorization.adoc | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/docs/modules/ROOT/pages/migration-7/authorization.adoc b/docs/modules/ROOT/pages/migration-7/authorization.adoc index 031c8a8bfb..0c0801285c 100644 --- a/docs/modules/ROOT/pages/migration-7/authorization.adoc +++ b/docs/modules/ROOT/pages/migration-7/authorization.adoc @@ -22,3 +22,82 @@ public void doSomething(Long id) { You must compile with `-parameters` to ensure that the parameter names are available at runtime. For more information about this, please visit the https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x#core-container[Upgrading to Spring Framework 6.1 page]. + +=== Favor `AnnotationTemplateExpressionDefaults` over `PrePostTemplateDefaults` + +In Spring Security 7, `AnnotationTemplateExpressionDefaults` will be included by default. + +If you are customizing `PrePostTemplateDefaults` or simply want to see how your application responds to `AnnotationTemplateExpressionDefaults`, you can publish an `AnnotationTemplateExpressionDefaults` bean instead of a `PrePostTemplateDefaults` method: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +static AnnotationTemplateExpressionDefaults templateExpressionDefaults() { + return new AnnotationTemplateExpressionDefaults(); +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +companion object { + @Bean + fun templateExpressionDefaults() = AnnotationTemplateExpressionDefaults() +} +---- + +Xml:: ++ +[source,xml,role="secondary"] +---- + +---- +====== + +==== I Am Publishing an AuthorizationAdvisor Bean + +If you are publishing an `AuthorizationAdvisor` bean, like `AuthorizationManagerBeforeMethodInterceptor`, `AuthorizationManagerAfterMethodInterceptor`, `PreFilterAuthorizationMethodInterceptor`, or `PostFilterAuthorizationMethodInterceptor`, you can do the same by calling `setTemplateDefaults` with an `AnnotationTemplateExpressionDefaults` instance instead: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +@Bean +@Role(BeanDescription.ROLE_INFRASTRUCTURE) +static Advisor preFilter() { + PreFilterAuthorizationMethodInterceptor interceptor = new PreFilterAuthorizationMethodInterceptor(); + interceptor.setTemplateDefaults(new AnnotationTemplateExpressionDefaults()); + return interceptor; +} +---- + +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +companion object { + @Bean + @Role(BeanDescription.ROLE_INFRASTRUCTURE) + fun preFilter(): Advisor { + val interceptor = PreFilterAuthorizationMethodInterceptor() + interceptor.setTemplateDefaults(AnnotationTemplateExpressionDefaults) + return interceptor + } +} +---- +====== + +=== Publish `AuthorizationAdvisor` instances instead of adding them in a `Customizer` + +While the ability to customize the `AuthorizationAdvisorProxyFactory` instance will remain in Spring Security 7, the ability to add advisors will be removed in favor of picking up published `AuthorizationAdvisor` beans. + +If you are not calling `AuthorizationAdvisorProxyFactory#setAdvisors` or `AuthorizationAdvisorProxyFactory#addAdvisor`, you need do nothing. + +If you are, publish the `AuthorizationAdvisor` bean instead and Spring Security will pick it up and apply it automatically. From 1ec084886a6585dc159c609aeff7e7917a7ed330 Mon Sep 17 00:00:00 2001 From: Josh Cummings <3627351+jzheaux@users.noreply.github.com> Date: Tue, 6 May 2025 16:55:22 -0600 Subject: [PATCH 8/8] Revert "Bump com.fasterxml.jackson:jackson-bom from 2.18.3 to 2.19.0" This reverts commit 226e81d7f55d38603f3f179d3e32caf3e7ed6a20. Given that we are in the RC phase, we do not want to do minor version upgrades --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 56d8410fd6..1a547b7152 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ org-springframework = "6.2.6" [libraries] ch-qos-logback-logback-classic = "ch.qos.logback:logback-classic:1.5.18" -com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.19.0" +com-fasterxml-jackson-jackson-bom = "com.fasterxml.jackson:jackson-bom:2.18.3" com-google-inject-guice = "com.google.inject:guice:3.0" com-netflix-nebula-nebula-project-plugin = "com.netflix.nebula:nebula-project-plugin:8.2.0" com-nimbusds-nimbus-jose-jwt = "com.nimbusds:nimbus-jose-jwt:9.37.3"