我在两个库中有两个安全配置
第一个用于身份验证:
@Bean
@Order(10)
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorizeRequests ->
authorizeRequests
.requestMatchers(createAntRequestMatchers(whitelist))
.permitAll().anyRequest()
.authenticated()
)
.oauth2ResourceServer( ...)
return http.build();
}
第二个添加了一些资源过滤器:
@Bean
@Order(100)
public SecurityFilterChain filterChain(HttpSecurity http, ResourceFilter resourceFilter) throws Exception {
return http
.authorizeHttpRequests(authorizeRequests ->
authorizeRequests
.requestMatchers(createAntRequestMatchers(whitelist))
.permitAll().anyRequest()
.authenticated()
).addFilterAfter(resourceFilter, SessionManagementFilter.class).build();
}
在 spring-boot 3.3 之前它工作得很好。? 更新到 spring-boot 3.4.1 spring context 后不再启动并显示错误消息
匹配任何请求的过滤器链[DefaultSecurityFilterChain在...中定义为'filterChain'已经被配置,这意味着这个过滤器链...永远不会被调用。请使用
HttpSecurity#securityMatcher
确保只有一个过滤器链配置为“任何请求”,并且“任何请求”过滤器链最后发布。
在每个配置中添加 requestMatcher (所有请求)后
http.securityMatcher("/**").authorizeHttpRequests(...
它按预期工作。但是如果我阅读 spring-security 问题评论https://github.com/spring-projects/spring-security/issues/15220 我对我的解决方案有疑问。
你什么意思?
OP 将安全配置分成两条链,我相信,只有在安全链完全执行后,主体才可用。但是,主体已填充且在
BearerTokenAuthenticationFilter
完成后可用。因此,问题中的两条链可以合并为一条。
可以通过将以下日志过滤器添加到链中来验证此行为:
.addFilterAfter(new LoggingFilter(), BearerTokenAuthenticationFilter.class)
这是日志过滤器的实现:
private static class LoggingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
var authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null) {
LOG.info("Logged in as: {}", authentication.getName());
LOG.info("Authorities: {}",
authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(", "))
);
} else {
LOG.info("No user");
}
filterChain.doFilter(request, response);
}
}