此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Security 6.5.3spring-doc.cadn.net.cn

Web 迁移

支持相对 URI

当重定向到登录端点时,Spring Security 过去更喜欢绝对 URI。 例如,如果您按如下方式设置登录页面:spring-doc.cadn.net.cn

http
    // ...
    .formLogin((form) -> form.loginPage("/my-login"))
    // ...
http {
    formLogin {
        loginPage = "/my-login"
    }
}
<http ...>
    <form-login login-page="/my-login"/>
</http>

然后当重定向到/my-loginSpring Security 将使用Location:如下所示:spring-doc.cadn.net.cn

302 Found
// ...
Location: https://myapp.example.org/my-login

但是,鉴于 RFC 所基于的 RFC 现已过时,因此不再需要这样做。spring-doc.cadn.net.cn

在 Spring Security 7 中,这已更改为使用相对 URI,如下所示:spring-doc.cadn.net.cn

302 Found
// ...
Location: /my-login

大多数应用程序不会注意到差异。 但是,如果此更改导致问题,您可以通过将favorRelativeUrls价值:spring-doc.cadn.net.cn

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 中的 bug 提供解决方法。 该解决方法不再需要,并且在某些情况下可能会导致用户出现问题。 因此,Spring Security 7 将删除PortResolver接口。spring-doc.cadn.net.cn

为了准备此更改,用户应公开PortResolver.NO_OP作为名为portResolver. 这确保了PortResolver使用的实现是无作(例如,什么都不做),它模拟删除PortResolver. 示例配置如下:spring-doc.cadn.net.cn

@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 中,AntPathRequestMatcherMvcRequestMatcher不再受支持,Java DSL 要求所有 URI 都是绝对的(减去任何上下文根)。 届时,Spring Security 7 将使用PathPatternRequestMatcher默认情况下。spring-doc.cadn.net.cn

要检查您对此更改的准备情况,您可以发布此 Bean:spring-doc.cadn.net.cn

@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对于它构造的所有请求匹配器。spring-doc.cadn.net.cn

如果您直接构造一个对象(而不是让 DSL 构造它),则具有setRequestMatcher方法。您还应该主动指定一个PathPatternRequestMatcher那里也有。spring-doc.cadn.net.cn

迁移exitUserUrlswitchUserUrl请求匹配器SwitchUserFilter

SwitchUserFilter,构造一个AntPathRequestMatcher在其setExitUserUrlsetSwitchUserUrl方法。 这将更改为PathPatternRequestMatcher在 Spring Security 7 中。spring-doc.cadn.net.cn

要准备此更改,请调用setExitUserMatchersetSwithcUserMatcher提供此PathPatternRequestMatcher提前。 也就是说,更改以下内容:spring-doc.cadn.net.cn

SwitchUserFilter switchUser = new SwitchUserFilter();
// ... other configuration
switchUser.setExitUserUrl("/exit/impersonate");
val switchUser = SwitchUserFilter()
// ... other configuration
switchUser.setExitUserUrl("/exit/impersonate")
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请求匹配器AbstractAuthenticationProcessingFilter实现

Spring Security 6 转换通过setFilterProcessingUrl设置为AntPathRequestMatcher. 在 Spring Security 7 中,这将更改为PathPatternRequestMatcher.spring-doc.cadn.net.cn

如果您直接调用setFilterProcessingUrl在扩展的过滤器上AbstractAuthenticationProcessingFilter喜欢UsernamePasswordAuthenticationFilter,OAuth2LoginAuthenticationFilter,Saml2WebSsoAuthenticationFilter,OneTimeTokenAuthenticationFilterWebAuthnAuthenticationFiltersetRequiredAuthenticationRequestMatcher而是提供PathPatternRequestMatcher提前。spring-doc.cadn.net.cn

也就是说,更改以下内容:spring-doc.cadn.net.cn

UsernamePasswordAuthenticationFilter usernamePassword = new UsernamePasswordAuthenticationFilter(authenticationManager);
usernamePassword.setFilterProcessingUrl("/my/processing/url");
val usernamePassword = UsernamePasswordAuthenticationFilter(authenticationManager)
usernamePassword.setFilterProcessingUrl("/my/processing/url")
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.spring-doc.cadn.net.cn

因此,为了准备这些变化,您可以使用setProxyReceptorRequestMatcher而不是setProxyReceptorUrl.spring-doc.cadn.net.cn

也就是说,更改以下内容:spring-doc.cadn.net.cn

casAuthentication.setProxyReceptorUrl("/proxy/receptor");
casAuthentication.setProxyReceptorUrl("/proxy/receptor")
casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor"));
casAuthentication.setProxyReceptorUrl(PathPatternRequestMatcher.withDefaults().matcher("/proxy/receptor"))

迁移 WebInvocationPrivilegeEvaluator

如果您使用的是 Spring Security 的 JSP Taglibs 或正在使用WebInvocationPrivilegeEvaluator直接注意以下更改:spring-doc.cadn.net.cn

  1. RequestMatcherWebInvocationPrivilegeEvaluator被弃用,取而代之的是AuthorizationManagerWebInvocationPrivilegeEvaluatorspring-doc.cadn.net.cn

  2. HandlerMappingIntrospectorRequestTransformer被弃用,取而代之的是PathPatternRequestTransformerspring-doc.cadn.net.cn

如果您不直接构建这些更改,您可以通过发布PathPatternRequestTransformer这样:spring-doc.cadn.net.cn

@Bean
HttpServletRequestTransformer pathPatternRequestTransformer() {
	return new PathPatternRequestTransformer();
}
@Bean
fun pathPatternRequestTransformer(): HttpServletRequestTransformer {
    return PathPatternRequestTransformer()
}
<b:bean class="org.springframework.security.web.access.PathPatternRequestTransformer"/>

Spring Security 将以此为使用新实现的信号。spring-doc.cadn.net.cn

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 匹配。spring-doc.cadn.net.cn

但是,如果您有其他具有 servlet 路径前缀的 servlet,那么现在需要单独提供这些路径spring-doc.cadn.net.cn

例如,如果我有一个 Spring MVC 控制器,其中@RequestMapping("/orders")并且我的 MVC 应用程序被部署到/mvc(而不是默认的 servlet),则此端点的 URI 为/mvc/orders. 从历史上看,Java DSL 没有一种简单的方法来指定 servlet 路径前缀,Spring Security 试图推断它。spring-doc.cadn.net.cn

随着时间的推移,我们了解到这些推理会让开发人员感到惊讶。 现在,无需将此责任从开发人员身上移开,而是更简单地指定 servlet 路径前缀,如下所示:spring-doc.cadn.net.cn

PathPatternRequestParser.Builder servlet = PathPatternRequestParser.withDefaults().basePath("/mvc");
http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers(servlet.pattern("/orders/**").matcher()).authenticated()
    )

对于属于默认 servlet 的路径,请使用PathPatternRequestParser.withDefaults()相反:spring-doc.cadn.net.cn

PathPatternRequestParser.Builder request = PathPatternRequestParser.withDefaults();
http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers(request.pattern("/js/**").matcher()).authenticated()
    )

请注意,这并不适用于所有类型的 servlet,因为并非所有 servlet 都有路径前缀。 例如,与 JSP Servlet 匹配的表达式可能使用 ant 模式/*/.jsp.spring-doc.cadn.net.cn

目前还没有通用的替代品,因此建议您使用RegexRequestMatcher这样:regexMatcher("\\.jsp$").spring-doc.cadn.net.cn

对于许多应用程序来说,这不会有什么区别,因为最常见的是,列出的所有 URI 都与默认 servlet 匹配。spring-doc.cadn.net.cn

使用 RedirectToHttps 而不是通道安全性

几年前,HTTPS 总体上是一个性能和配置问题,应用程序希望能够决定应用程序的哪些部分需要 HTTPS。spring-doc.cadn.net.cn

requires-channel在 XML 中,并且requiresChannel在 Java Config 中,允许在配置应用程序时考虑到这一点:spring-doc.cadn.net.cn

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。spring-doc.cadn.net.cn

在任何情况下,您都可以迁移到redirect-to-https-request-matcher-refredirectToHttps通过首先构造一个RequestMatcher其中包含需要重定向到 HTTPS 的所有情况。 然后,您可以像这样引用该请求匹配器:spring-doc.cadn.net.cn

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 的情况,请考虑使用OrRequestMatcher将它们合并为一个RequestMatcher实例。spring-doc.cadn.net.cn

setCookieCustomizer而不是单独的二传手

支持更简单的 API,CookieCsrfTokenRepository#setCookieCustomizer允许您更改 cookie 的任何方面,将setCookieHttpOnly,setCookieMaxAge,setSecuresetCookieDomain.spring-doc.cadn.net.cn

更改此内容:spring-doc.cadn.net.cn

CookeCsrfTokenRepository csrf = CookeCsrfTokenRepository.withHttpOnlyFalse();
csrf.setCookieMaxAge(86400)
val csrf = CookeCsrfTokenRepository.withHttpOnlyFalse()
csrf.setCookieMaxAge(86400)
CookeCsrfTokenRepository csrf = CookeCsrfTokenRepository.withHttpOnlyFalse();
csrf.setCookieCustomizer((c) -> c.maxAge(86400));
val csrf = CookeCsrfTokenRepository.withHttpOnlyFalse()
csrf.setCookieCustomizer { -> it.maxAge(86400) }