此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Security 6.4.5spring-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 中的错误提供解决方法。 该解决方法不再需要,并且在某些情况下可能会给用户带来问题。 因此,Spring Security 7 将删除PortResolver接口。spring-doc.cadn.net.cn

要为此更改做好准备,用户应公开PortResolver.NO_OP作为名为portResolver. 这可确保PortResolver使用的 implementation 是一个 no-op (例如,什么都不做),它模拟了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请求 MatcherAbstractAuthenticationProcessingFilter实现

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.servletPath("/mvc");
http
    .authorizeHttpRequests((authorize) -> authorize
        .requestMatchers(servlet.pattern("/orders/**").matcher()).authenticated()
    )

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

PathPatternRequestParser.Builder request = PathPatternRequestParser.path();
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