我有一个可运行的 Spring Boot 2.7 应用程序,具有 HTTP Basic auth,使用 Spring Security 和 Spring MVC。升级到 Spring Boot 3.3 后,我在所有页面上收到 403 响应,甚至是标记为
permitAll()
的页面。经过大量调试后,我的用户似乎成功通过了每个页面 Web 路径的身份验证检查,但随后未能通过 JSP URI 的后续身份验证检查,因为我没有定义任何指向我的 WEB-INF 的匹配器。
RequestMatcherDelegatingAuthorizationManager - Authorizing GET /my-page/
RequestMatcherDelegatingAuthorizationManager - Checking authorization on GET /my-page/ using org.springframework.security.authorization.AuthenticatedAuthorizationManager@2488b87f
FilterChainProxy - Secured GET /my-page/
...
RequestMatcherDelegatingAuthorizationManager - Authorizing GET /WEB-INF/jsp/my-page.jsp
RequestMatcherDelegatingAuthorizationManager - Denying request since did not find matching RequestMatcher
显然,客户端并不是直接请求 JSP;而是直接请求 JSP。这是来自我的控制器。在 Spring Boot 2.7 中调试
RequestMatcherDelegatingAuthorizationManager
显示仅检查了 Web 路径;没有对 JSP 进行后续检查。
这是我的 Spring Boot 3 安全配置:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class MyConfig
{
@Bean
public SecurityFilterChain mySecurityChainFilterChain(HttpSecurity httpSecurity) throws Exception
{
httpSecurity
.authorizeHttpRequests(requests -> requests
.requestMatchers("/").permitAll()
.requestMatchers("/my-page/**").authenticated()
.requestMatchers("/my-page/admin/**").hasRole("ADMIN")
)
.csrf().disable() // just to prove this isn't the problem
.cors().disable() // just to prove this isn't the problem
.authenticationManager(makeAuthenticationManager(httpSecurity))
.httpBasic(Customizer.withDefaults());
return httpSecurity.build();
}
private AuthenticationManager makeAuthenticationManager(HttpSecurity httpSecurity) throws Exception
{
AuthenticationManagerBuilder builder = httpSecurity.getSharedObject(AuthenticationManagerBuilder.class);
builder.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder);
return builder.build();
}
// ... bean definitions ...
}
有趣的是,为我的 WEB-INF 定义请求匹配器是有效的......但我知道这不是解决方案。如有任何帮助,我们将不胜感激。
再苦苦挣扎之后,我发现我必须在 FORWARD 上允许所有内容,这很快导致我意识到我需要对 INCLUDE 做同样的事情。
这是我的新 3.3 配置:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class MyConfig
{
@Bean
public SecurityFilterChain mySecurityChainFilterChain(HttpSecurity httpSecurity) throws Exception
{
httpSecurity
.authorizeHttpRequests(requests -> requests
.dispatcherTypeMatchers(
DispatcherType.ERROR,
DispatcherType.FORWARD,
DispatcherType.INCLUDE
).permitAll()
.requestMatchers("/my-page/admin/**").hasRole("ADMIN")
.requestMatchers("/my-page/**").authenticated()
.requestMatchers("/", "/public/assets/**").permitAll()
)
.authenticationManager(makeAuthenticationManager(httpSecurity))
.httpBasic(Customizer.withDefaults());
return httpSecurity.build();
}
// ... bean definitions ...
}