Spring Boot 3 与 Spring Security 拦截异常,我不希望它这样做

Bra*_*don 4 java spring spring-security spring-boot

我正在使用 Spring Boot 3.0.2 和 Spring Security 构建一个 API,我已经构建了安全过滤器链,并且它在阻止未经身份验证的请求方面工作正常。但我有一个RestController接受 的类application/json,如果我没有正确提供内容类型标头,我希望返回 415 状态代码。如果没有 Spring Security 的阻碍,它会得到很好的返回。但对于 Spring Security 来说,它似乎被拦截并返回 403。

WebSecurityConfig

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
               .cors().and()
               .csrf().disable()
               .authorizeHttpRequests(auth -> auth
                   .requestMatchers("/auth**").permitAll()
                   .anyRequest().authenticated())
               .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
               .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
               .userDetailsService(jpaUserDetailsService)
               .build();
}
Run Code Online (Sandbox Code Playgroud)

验证过滤器:

@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
    private final JwtUtils jwtUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String jwtToken = request.getHeader(AUTHENTICATION_HEADER);

        if (jwtToken != null && jwtToken.startsWith("Bearer ")) {
            jwtToken = jwtToken.split(" ")[1];
            if (jwtUtils.isValidToken(jwtToken)) {
                UserDetails userDetails = new UserSecurity(jwtUtils.extractUser(jwtToken));
                UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetails,
                        null, userDetails.getAuthorities());
                auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
        }

        filterChain.doFilter(request, response);
    }
}
Run Code Online (Sandbox Code Playgroud)

休息控制器:

@RestController
@RequestMapping(value = "auth", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public class AuthController {
    @GetMapping
    public Object test() {
        Map<String, String> test = new HashMap<>();
        test.put("key", "val");

        return test;
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法只在实际上是未经身份验证的错误时返回 403 异常?不是针对每一个例外吗?

dur*_*dur 7

您必须打开错误端点,请参阅Spring Boot 2.0 迁移指南

\n
\n

默认安全

\n

安全自动配置不再公开选项并尽可能使用 Spring Security 默认值。其一个明显的副作用是使用 Spring Security\xe2\x80\x99s 内容协商进行授权(表单登录)。

\n

Spring Boot 2.0\xe2\x80\x99t 与 Spring Security\xe2\x80\x99s 默认值相差太大,因此 Spring Boot 1.5 中绕过 Spring Security 的一些端点现在默认是安全的。其中包括错误端点和静态资源的路径,例如/css/**/js/**/images/**/webjars/**/**/favicon.ico。如果您想打开它们,则需要显式配置。

\n
\n

错误端点呈现响应,请参阅Spring Boot 参考

\n
\n

27.1.11 错误处理

\n

默认情况下,Spring Boot 提供了一个/error以合理方式处理所有错误的映射,它在 servlet 容器中注册为 \xe2\x80\x9cglobal\xe2\x80\x9d 错误页面。对于机器客户端,它会生成一个 JSON 响应,其中包含错误、HTTP 状态和异常消息的详细信息。对于浏览器客户端,有一个 \xe2\x80\x9cwhitelabel\xe2\x80\x9d 错误视图,它以 HTML 格式呈现相同的数据(要自定义它,请添加View解析为 的error)。

\n
\n

您修改后的安全链配置:

\n
@Bean\npublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {\n    return http\n               .cors().and()\n               .csrf().disable()\n               .authorizeHttpRequests(auth -> auth\n                    .requestMatchers("/error").permitAll()\n                    .requestMatchers("/auth**").permitAll()\n                    .anyRequest().authenticated())\n               .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))\n               .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)\n               .userDetailsService(jpaUserDetailsService)\n               .build();\n}\n
Run Code Online (Sandbox Code Playgroud)\n