diff --git a/docs/modules/ROOT/pages/migration/web.adoc b/docs/modules/ROOT/pages/migration/web.adoc index 8b92d2166b..6e99fd87df 100644 --- a/docs/modules/ROOT/pages/migration/web.adoc +++ b/docs/modules/ROOT/pages/migration/web.adoc @@ -42,21 +42,57 @@ This will tell the Spring Security DSL to use `PathPatternRequestMatcher` for al In the event that you are directly constructing an object (as opposed to having the DSL construct it) that has a `setRequestMatcher` method. you should also proactively specify a `PathPatternRequestMatcher` there as well. -For example, in the case of `LogoutFilter`, it constructs an `AntPathRequestMatcher` in Spring Security 6: +=== Migrate `exitUserUrl` and `switchUserUrl` Request Matchers in `SwitchUserFilter` -[method,java] +`SwitchUserFilter`, constructs an `AntPathRequestMatcher` in its `setExitUserUrl` and `setSwitchUserUrl` methods. +This will change to use `PathPatternRequestMatcher` in Spring Security 7. + +To prepare for this change, call `setExitUserMatcher` and `setSwithcUserMatcher` to provide this `PathPatternRequestMatcher` in advance. +That is, change this: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] ---- -private RequestMatcher logoutUrl = new AntPathRequestMatcher("/logout"); +SwitchUserFilter switchUser = new SwitchUserFilter(); +// ... other configuration +switchUser.setExitUserUrl("/exit/impersonate"); ---- -and will change this to a `PathPatternRequestMatcher` in 7: - -[method,java] +Kotlin:: ++ +[source,kotlin,role="secondary"] ---- -private RequestMatcher logoutUrl = PathPatternRequestMatcher.path().matcher("/logout"); +val switchUser = SwitchUserFilter() +// ... other configuration +switchUser.setExitUserUrl("/exit/impersonate") +---- +====== + +to this: + +[tabs] +====== +Java:: ++ +[source,java,role="primary"] +---- +SwitchUserFilter switchUser = new SwitchUserFilter(); +// ... other configuration +switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/exit/impersonate")); ---- -If you are constructing your own `LogoutFilter`, consider calling `setLogoutRequestMatcher` to provide this `PathPatternRequestMatcher` in advance. +Kotlin:: ++ +[source,kotlin,role="secondary"] +---- +val switchUser = SwitchUserFilter() +// ... other configuration +switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/exit/impersonate")) +---- +====== == Include the Servlet Path Prefix in Authorization Rules diff --git a/web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java b/web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java index 8018f33d96..335262b05c 100644 --- a/web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java +++ b/web/src/main/java/org/springframework/security/web/authentication/switchuser/SwitchUserFilter.java @@ -35,6 +35,7 @@ import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.core.log.LogMessage; +import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AccountExpiredException; import org.springframework.security.authentication.AccountStatusUserDetailsChecker; import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; @@ -62,6 +63,7 @@ import org.springframework.security.web.authentication.WebAuthenticationDetailsS import org.springframework.security.web.context.HttpSessionSecurityContextRepository; import org.springframework.security.web.context.RequestAttributeSecurityContextRepository; import org.springframework.security.web.context.SecurityContextRepository; +import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.UrlUtils; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; @@ -127,9 +129,9 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); - private RequestMatcher exitUserMatcher = createMatcher("/logout/impersonate"); + private RequestMatcher exitUserMatcher = createMatcher("/logout/impersonate", true); - private RequestMatcher switchUserMatcher = createMatcher("/login/impersonate"); + private RequestMatcher switchUserMatcher = createMatcher("/login/impersonate", true); private String targetUrl; @@ -406,7 +408,7 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv public void setExitUserUrl(String exitUserUrl) { Assert.isTrue(UrlUtils.isValidRedirectUrl(exitUserUrl), "exitUserUrl cannot be empty and must be a valid redirect URL"); - this.exitUserMatcher = createMatcher(exitUserUrl); + this.exitUserMatcher = createMatcher(exitUserUrl, false); } /** @@ -426,7 +428,7 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv public void setSwitchUserUrl(String switchUserUrl) { Assert.isTrue(UrlUtils.isValidRedirectUrl(switchUserUrl), "switchUserUrl cannot be empty and must be a valid redirect URL"); - this.switchUserMatcher = createMatcher(switchUserUrl); + this.switchUserMatcher = createMatcher(switchUserUrl, false); } /** @@ -545,7 +547,10 @@ public class SwitchUserFilter extends GenericFilterBean implements ApplicationEv this.securityContextRepository = securityContextRepository; } - private static RequestMatcher createMatcher(String pattern) { + private static RequestMatcher createMatcher(String pattern, boolean usePathPatterns) { + if (usePathPatterns) { + return PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, pattern); + } return new AntPathRequestMatcher(pattern, "POST", true, new UrlPathHelper()); }