此版本仍在开发中,尚未被视为稳定版本。如需最新稳定版本,请使用 Spring Security 7.0.4spring-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-login 时,Spring Security 将使用一个类似于以下的 Location::spring-doc.cadn.net.cn

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

鉴于RFC所基于的内容现在已经过时,因此这现在已经不再必要。spring-doc.cadn.net.cn

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

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

大多数应用程序不会注意到任何差异。 然而,如果此更改导致问题,您可以将favorRelativeUrls值切换回Spring Security 6的行为: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的 API 来提供一个针对 Internet Explorer 中的一个错误的 workaround。 这个 workaround 已经不再必要,并且在某些场景下可能会给用户带来问题。因此,Spring Security 7 将移除 PortResolver 接口。spring-doc.cadn.net.cn

要为此变更做准备,用户应该将PortResolver.NO_OP暴露为一个名为portResolver的Bean。 这确保了使用的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将会默认使用PathPatternRequestMatcherspring-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。 在XML中,您可以使用request-matcher="path"代替request-matcher="ant"request-matcher="mvc",如下所示:spring-doc.cadn.net.cn

<http auto-config="true">
  <intercept-url pattern="/my/login/**" access="authenticated" request-matcher="path"/>
</http>

迁移exitUserUrlswitchUserUrl请求匹配器在SwitchUserFilter

SwitchUserFilter, 在其AntPathRequestMatchersetExitUserUrl方法中构造一个setSwitchUserUrl。 这将在Spring Security 7中改为使用PathPatternRequestMatcherspring-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"))

迁移filterProcessingUrlSpring 框架中的请求匹配器AbstractAuthenticationProcessingFilter实现

Spring Security 6 将通过 setFilterProcessingUrl 配置的任何处理端点转换为 AntPathRequestMatcher。 在 Spring Security 7 中,这将变为 PathPatternRequestMatcherspring-doc.cadn.net.cn

如果您直接在扩展AbstractAuthenticationProcessingFilter的过滤器(例如UsernamePasswordAuthenticationFilterOAuth2LoginAuthenticationFilterSaml2WebSsoAuthenticationFilterOneTimeTokenAuthenticationFilterWebAuthnAuthenticationFilter)上调用setFilterProcessingUrl,请改为调用setRequiredAuthenticationRequestMatcher以提前提供此PathPatternRequestMatcherspring-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 7 中,URL 应该是绝对路径,不包括任何上下文路径,例如:/proxy/receptorspring-doc.cadn.net.cn

为了应对这些更改,您可以使用setProxyReceptorRequestMatcher替代setProxyReceptorUrlspring-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标签库,或直接使用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

例如,如果我有一个使用@RequestMapping("/orders")的Spring MVC控制器,并且我的MVC应用程序部署到了/mvc(而不是默认的服务路径),那么此端点的URI为/mvc/orders。 历史上,Java DSL 没有简单的方法来指定Servlet路径前缀,Spring Security 曾尝试推断它。spring-doc.cadn.net.cn

随着时间的推移,我们了解到这些推断会让开发者感到惊讶。 现在,与其将这个责任从开发者那里拿走,不如这样指定servlet路径前缀要简单得多:spring-doc.cadn.net.cn

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

对于属于默认Servlet的路径,请使用PathPatternRequestMatcher.withDefaults()代替:spring-doc.cadn.net.cn

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

注意,这并不涵盖所有类型的servlet,因为并非所有的servlet都有路径前缀。 例如,匹配JSP Servlet的表达式可能会使用ant模式 /*/.jspspring-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 配置中用于根据需要配置应用程序: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

在任何情况下,您可以通过首先构建一个包含所有需要重定向到HTTPS的情况的redirect-to-https-request-matcher-ref来迁移至redirectToHttpsRequestMatcher。 然后您可以像这样引用该请求匹配器: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而不是单独的 setter 方法

在更简单易用的API方面,CookieCsrfTokenRepository#setCookieCustomizer 允许您更改任何与cookie相关的内容,替代了 setCookieHttpOnlysetCookieMaxAgesetSecuresetCookieDomainspring-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) }