此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.5! |
Web 迁移
偏爱相对 URI
重定向到登录端点时, Spring Security 过去偏爱绝对 URI。 例如,如果您像这样设置登录页面:
-
Java
-
Kotlin
-
Xml
http
// ...
.formLogin((form) -> form.loginPage("/my-login"))
// ...
http {
formLogin {
loginPage = "/my-login"
}
}
<http ...>
<form-login login-page="/my-login"/>
</http>
然后,当重定向到/my-login
Spring Security 将使用Location:
如下所示:
302 Found
// ...
Location: https://myapp.example.org/my-login
但是,鉴于 RFC 所基于的 RFC 现已过时,这不再是必需的。
在 Spring Security 7 中,这被更改为使用相对 URI,如下所示:
302 Found
// ...
Location: /my-login
大多数应用程序不会注意到差异。
但是,如果此更改导致问题,则可以通过将favorRelativeUrls
价值:
-
Java
-
Kotlin
-
Xml
LoginUrlAuthenticationEntryPoint entryPoint = new LoginUrlAuthenticationEntryPoint("/my-login");
entryPoint.setFavorRelativeUris(false);
http
// ...
.exceptionHandling((exceptions) -> exceptions.authenticaitonEntryPoint(entryPoint))
// ...
LoginUrlAuthenticationEntryPoint entryPoint = LoginUrlAuthenticationEntryPoint("/my-login")
entryPoint.setFavorRelativeUris(false)
http {
exceptionHandling {
authenticationEntryPoint = entryPoint
}
}
<http entry-point-ref="myEntryPoint">
<!-- ... -->
</http>
<b:bean id="myEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<b:property name="favorRelativeUris" value="true"/>
</b:bean>
端口解析器
Spring Security 使用一个名为PortResolver
为 Internet Explorer 中的错误提供解决方法。
该解决方法不再需要,并且在某些情况下可能会给用户带来问题。
因此,Spring Security 7 将删除PortResolver
接口。
要为此更改做好准备,用户应公开PortResolver.NO_OP
作为名为portResolver
.
这可确保PortResolver
使用的 implementation 是一个 no-op (例如,什么都不做),它模拟了PortResolver
.
可以在下面找到示例配置:
-
Java
-
Kotlin
-
Xml
@Bean
PortResolver portResolver() {
return PortResolver.NO_OP;
}
@Bean
open fun portResolver(): PortResolver {
return PortResolver.NO_OP
}
<util:constant id="portResolver"
static-field="org.springframework.security.web.PortResolver.NO_OP">
默认使用 PathPatternRequestMatcher
在 Spring Security 7 中,AntPathRequestMatcher
和MvcRequestMatcher
不再受支持,并且 Java DSL 要求所有 URI 都是绝对的(减去任何上下文根)。
届时,Spring Security 7 将使用PathPatternRequestMatcher
默认情况下。
要检查您对此更改的准备情况,可以发布此 bean:
-
Java
-
Kotlin
-
Xml
@Bean
PathPatternRequestMatcherBuilderFactoryBean requestMatcherBuilder() {
return new PathPatternRequestMatcherBuilderFactoryBean();
}
@Bean
fun requestMatcherBuilder(): PathPatternRequestMatcherBuilderFactoryBean {
return PathPatternRequestMatcherBuilderFactoryBean()
}
<b:bean class="org.springframework.security.config.web.PathPatternRequestMatcherBuilderFactoryBean"/>
这将告诉 Spring Security DSL 使用PathPatternRequestMatcher
对于它构造的所有请求匹配器。
如果你直接构造一个对象(而不是让 DSL 构造它),并且具有setRequestMatcher
方法。您还应主动指定PathPatternRequestMatcher
那里也有。
迁移exitUserUrl
和switchUserUrl
请求匹配器SwitchUserFilter
SwitchUserFilter
,构造一个AntPathRequestMatcher
在其setExitUserUrl
和setSwitchUserUrl
方法。
这将更改为使用PathPatternRequestMatcher
在 Spring Security 7 中。
要为此更改做好准备,请调用setExitUserMatcher
和setSwithcUserMatcher
提供此PathPatternRequestMatcher
提前。
也就是说,更改以下内容:
-
Java
-
Kotlin
SwitchUserFilter switchUser = new SwitchUserFilter();
// ... other configuration
switchUser.setExitUserUrl("/exit/impersonate");
val switchUser = SwitchUserFilter()
// ... other configuration
switchUser.setExitUserUrl("/exit/impersonate")
到这个:
-
Java
-
Kotlin
SwitchUserFilter switchUser = new SwitchUserFilter();
// ... other configuration
switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/exit/impersonate"));
val switchUser = SwitchUserFilter()
// ... other configuration
switchUser.setExitUserMatcher(PathPatternRequestMatcher.withDefaults().matcher(HttpMethod.POST, "/exit/impersonate"))
迁移filterProcessingUrl
请求 MatcherAbstractAuthenticationProcessingFilter
实现
Spring Security 6 转换通过setFilterProcessingUrl
更改为AntPathRequestMatcher
.
在 Spring Security 7 中,这将更改为PathPatternRequestMatcher
.
如果你直接调用setFilterProcessingUrl
在扩展AbstractAuthenticationProcessingFilter
喜欢UsernamePasswordAuthenticationFilter
,OAuth2LoginAuthenticationFilter
,Saml2WebSsoAuthenticationFilter
,OneTimeTokenAuthenticationFilter
或WebAuthnAuthenticationFilter
叫setRequiredAuthenticationRequestMatcher
而是提供此PathPatternRequestMatcher
提前。
也就是说,更改以下内容:
-
Java
-
Kotlin
UsernamePasswordAuthenticationFilter usernamePassword = new UsernamePasswordAuthenticationFilter(authenticationManager);
usernamePassword.setFilterProcessingUrl("/my/processing/url");
val usernamePassword = UsernamePasswordAuthenticationFilter(authenticationManager)
usernamePassword.setFilterProcessingUrl("/my/processing/url")
到这个:
-
Java
-
Kotlin
UsernamePasswordAuthenticationFilter usernamePassword = new UsernamePasswordAuthenticationFilter(authenticationManager);
RequestMatcher requestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/my/processing/url");
usernamePassword.setRequest(requestMatcher);
val usernamePassword = UsernamePasswordAuthenticationFilter(authenticationManager)
val requestMatcher = PathPatternRequestMatcher.withDefaults().matcher("/my/processing/url")
usernamePassword.setRequest(requestMatcher)
Most applications use the DSL instead of setting the `filterProcessingUrl` directly on a filter instance.
迁移 CAS 代理接收器请求匹配程序
Spring Security 6 可转换任何已配置的proxyReceptorUrl
到与请求末尾匹配的请求匹配器,即/**/proxy/receptor
.
在 Spring Security 7 中,不允许使用此模式,并将更改为使用PathPatternRequestMatcher
.
同样在 Spring Security 7m 中,URL 应该是绝对的,不包括任何上下文路径,如下所示:/proxy/receptor
.
因此,为了准备这些更改,您可以使用setProxyReceptorRequestMatcher
而不是setProxyReceptorUrl
.
也就是说,更改以下内容:
-
Java
-
Kotlin
casAuthentication.setProxyReceptorUrl("/proxy/receptor");
casAuthentication.setProxyReceptorUrl("/proxy/receptor")
到这个:
-
Java
-
Kotlin
casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor"));
casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor"))
迁移 WebInvocationPrivilegeEvaluator
如果您使用的是 Spring Security 的 JSP Taglibs 或正在使用WebInvocationPrivilegeEvaluator
直接请注意以下更改:
-
RequestMatcherWebInvocationPrivilegeEvaluator
已弃用,取而代之的是AuthorizationManagerWebInvocationPrivilegeEvaluator
-
HandlerMappingIntrospectorRequestTransformer
已弃用,取而代之的是PathPatternRequestTransformer
如果您不直接构建这些更改,则可以提前选择加入这两个更改,方法是发布PathPatternRequestTransformer
这样:
-
Java
-
Kotlin
-
Xml
@Bean
HttpServletRequestTransformer pathPatternRequestTransformer() {
return new PathPatternRequestTransformer();
}
@Bean
fun pathPatternRequestTransformer(): HttpServletRequestTransformer {
return PathPatternRequestTransformer()
}
<b:bean class="org.springframework.security.web.access.PathPatternRequestTransformer"/>
Spring Security 会将此视为使用新实现的信号。
One difference you may notice is that `AuthorizationManagerWebPrivilegeInvocationEvaluator` allows the authentication to be `null` if the authorization rule is `permitAll`. Test your endpoints that `permitAll` in case JSP requests using this same require should not, in fact, be permitted.
在授权规则中包含 Servlet 路径前缀
对于许多应用程序,上述内容没有区别,因为大多数情况下,列出的所有 URI 都与默认 servlet 匹配。
但是,如果您有其他具有 Servlet 路径前缀的 Servlet,则现在需要单独提供这些路径。
例如,如果我有一个 Spring MVC 控制器,其中@RequestMapping("/orders")
并且我的 MVC 应用程序被部署到/mvc
(而不是默认 servlet),则此端点的 URI 为/mvc/orders
.
从历史上看,Java DSL 没有一种简单的方法来指定 servlet 路径前缀,Spring Security 试图推断它。
随着时间的推移,我们了解到这些推理会让开发人员感到惊讶。 现在,指定 servlet 路径前缀更简单,而不是将这一责任从开发人员手中移开,如下所示:
PathPatternRequestParser.Builder servlet = PathPatternRequestParser.servletPath("/mvc"); http .authorizeHttpRequests((authorize) -> authorize .requestMatchers(servlet.pattern("/orders/**").matcher()).authenticated() )
对于属于默认 Servlet 的路径,请使用PathPatternRequestParser.path()
相反:
PathPatternRequestParser.Builder request = PathPatternRequestParser.path(); http .authorizeHttpRequests((authorize) -> authorize .requestMatchers(request.pattern("/js/**").matcher()).authenticated() )
请注意,这并未涉及所有类型的 Servlet,因为并非所有 Servlet 都有路径前缀。
例如,与 JSP Servlet 匹配的表达式可能使用 ant 模式/*/.jsp
.
目前还没有通用的替代品,因此我们鼓励您使用RegexRequestMatcher
这样:regexMatcher("\\.jsp$")
.
对于许多应用程序,这没有区别,因为大多数情况下,列出的所有 URI 都与默认 servlet 匹配。
使用 RedirectToHttps 而不是通道安全性
几年前,HTTPS 总体上已经足够关注性能和配置问题,以至于应用程序希望能够决定应用程序的哪些部分需要 HTTPS。
requires-channel
在 XML 中和requiresChannel
在 Java Config 中,允许在配置应用程序时牢记这一点:
-
Java
-
Kotlin
-
Xml
http
.requiresChannel((channel) -> channel
.requestMatchers("/secure/**").requiresSecureChannel()
.requestMatchers("/insecure/**").requiresInsecureChannel()
)
http {
requiresChannel {
secure("/secure/**")
seccure("/insecure/**", "REQUIRES_INSECURE_CHANNEL")
}
}
<http>
<intercept-url pattern="/secure/**" access="authenticated" requires-channel="REQUIRES_SECURE_CHANNEL"/>
<intercept-url pattern="/insecure/**" access="authenticated" requires-channel="REQUIRES_INSECURE_CHANNEL"/>
</http>
现代应用程序应始终需要 HTTPS。 但是,有时(例如在本地开发时)希望应用程序使用 HTTP。 或者,您可能有持续的情况要求应用程序的一部分是 HTTP。
在任何情况下,您都可以迁移到redirect-to-https-request-matcher-ref
和redirectToHttps
首先构造一个RequestMatcher
,其中包含需要重定向到 HTTPS 的所有情况。
然后,您可以像这样引用该请求匹配器:
-
Java
-
Kotlin
-
Xml
http
.redirectToHttps((https) -> https.requestMatchers("/secure/**"))
// ...
var secure: RequestMatcher = PathPatternRequestMatcher.withDefaults().pattern("/secure/**")
http {
redirectToHttps {
requestMatchers = secure
}
// ...
}
<b:bean id="builder" class="org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher$Builder"/>
<b:bean id="secure" class="org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher" factory-bean="builder" factory-method="matcher">
<b:constructor-arg value="/secure/**"/>
</b:bean>
<http redirect-to-https-request-matcher-ref="secure">
<intercept-url pattern="/secure/**" access="authenticated"/>
<intercept-url pattern="/insecure/**" access="authenticated"/>
<!-- ... -->
</http>
如果您有多种需要 HTTP 的情况,请考虑使用 |