You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security配置中permitAll端点仍返回403的求助

Spring Security 6.2.1中permitAll()端点返回403错误排查与解决

我使用Spring Boot 3.2.2 + Spring Security 6.2.1搭建供React调用的Web API项目,大部分配置已完成,但设置了permitAll()的登录端点始终返回403错误。

当前SecurityFilterChain配置

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
    System.out.println(httpSecurity);
      return httpSecurity
                .authorizeHttpRequests((auth) -> auth
                        .requestMatchers("/api/myproject/admin/**") // 尝试过移除该条件
                        .hasRole("ADMIN")
                        .requestMatchers(HttpMethod.POST, "/public/login") // 尝试过不带上下文路径
                        .permitAll()
                        .requestMatchers(HttpMethod.POST, "/api/myproject/public/login") // 尝试过带上下文路径
                        .permitAll()
                        .anyRequest().authenticated()
                    )
                .csrf(AbstractHttpConfigurer::disable) // 尝试过禁用CSRF
                .authenticationProvider(authenticationProvider())
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                .build();

}

已尝试的无效方案

  • 为登录端点同时配置GET和POST请求(理想情况是用POST)
  • 禁用CSRF防护
  • 尝试带/不带上下文路径(/api/myproject为项目上下文路径)的端点匹配规则
  • 明确指定HTTP POST请求方法
  • 移除所有规则,仅保留登录路由的permitAll()配置

仅当设置anyRequest().permitAll()时,所有端点(包括登录)才能正常访问。

补充代码信息

登录控制器代码

@Slf4j
@RestController
@RequestMapping("/public")
public class LoginController {

    @Autowired
    private LoginService loginService;

    @PostMapping("/login")
    public ResponseEntity<LoginResponse> generateUserToken(@RequestBody LoginRequest loginRequest) {
        log.info("generateUserToken Started");
        String token = loginService.login(loginRequest.getEmailId(), loginRequest.getPwd());
        return ResponseEntity.ok(new LoginResponse(token));
    }

}

调用API的curl命令

curl --location 'http://localhost:8080/api/myproject/public/login' \
--header 'Content-Type: application/json' \
--header 'Cookie: JSESSIONID=9E2DD3E4A04619324786B0F595BD96FD' \
--data-raw '{
    "emailId": "dkjkaj@gmail.com",
    "pwd": "jhdsjhdj"
}'

问题原因及解决方法

1. 上下文路径匹配冗余

Spring Security的requestMatchers匹配的是上下文路径之后的请求路径,不需要额外拼接项目上下文路径/api/myproject。你的控制器映射是/public/login,所以只需配置HttpMethod.POST, "/public/login"即可,多余的带上下文路径的匹配规则会干扰正常匹配逻辑。

2. JWT过滤器拦截了未授权请求

你添加的jwtAuthFilter在UsernamePasswordAuthenticationFilter之前执行,如果该过滤器对所有请求(包括登录端点)都进行JWT校验,那么即使设置了permitAll(),未携带token的登录请求也会被过滤器拦截返回403。

解决方式:
在JWT过滤器中排除登录端点,直接放行:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    String path = request.getRequestURI();
    // 排除登录端点,跳过JWT校验
    if (path.equals("/public/login")) {
        filterChain.doFilter(request, response);
        return;
    }
    // 其他JWT校验逻辑...
}

或者在Security配置中,为登录端点禁用JWT过滤器:

.authorizeHttpRequests((auth) -> auth
        .requestMatchers(HttpMethod.POST, "/public/login").permitAll()
        .requestMatchers("/admin/**").hasRole("ADMIN")
        .anyRequest().authenticated()
)
// 给登录端点禁用JWT过滤器
.requestMatchers(HttpMethod.POST, "/public/login").filters(f -> f.disable())

3. 添加无状态会话配置

你的请求携带了JSESSIONID,这是Spring Security默认创建会话的产物,但JWT认证应该是无状态的。在Security配置中添加无状态会话配置,避免会话干扰:

.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))

4. 简化后的完整Security配置

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
            .csrf(csrf -> csrf.disable())
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                    .requestMatchers(HttpMethod.POST, "/public/login").permitAll()
                    .requestMatchers("/admin/**").hasRole("ADMIN")
                    .anyRequest().authenticated()
            )
            .authenticationProvider(authenticationProvider())
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
            .build();
}

内容的提问来源于stack exchange,提问作者Saurabh Tiwari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:55:00