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

Spring Security排除URL认证异常:GET生效POST失效求助

Spring Security POST接口配置permitAll仍要求认证的问题

我尝试在Spring Security配置中排除部分URL,使其无需JWT令牌认证即可访问,但发现GET方法接口/v1/all可正常免认证访问,而POST方法接口/v1/user-subscription尽管已配置permitAll,仍要求进行认证。

相关代码配置

安全配置代码

@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests()
            .requestMatchers(new AntPathRequestMatcher("/v1/all", "GET"), new AntPathRequestMatcher("/v1/user-subscription", "POST"))
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();
    return http.build();
}

控制器代码

@RestController
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class UserSubscription {

UserService userService;

    @PostMapping("/v1/user-subscription")
    public ResponseEntity<Void> createUser(User user) {
    userService.createUser(user);
    return new ResponseEntity(HttpStatus.NO_CONTENT);
}

服务层代码

public void createUser(User user) {

    RoleEntity roleEntity = roleRepository.findByRoleById(user.getId());

    String userId = user.getId();

    userRepository.findByRole(roleEntity).ifPresentOrElse(userEntity -> {
        UserEntity userUpdated = userEntity.toBuilder()
                .userId(userId)
                .build();
        userRepository.save(userUpdated);
    }, () -> {
        UserEntity newUser = UserEntity.builder()
                .userId(userId)
                .role(roleEntity)
                .build();
        userRepository.save(newUser);
    });
}

请求与响应截图

请求截图
响应截图

问题原因及解决方案

最可能的原因:CSRF防护拦截

Spring Security默认启用CSRF保护机制,针对POST、PUT、DELETE等非GET请求,会强制校验CSRF令牌。即使你为该路径配置了permitAll,CSRF校验依然会独立生效,导致请求被拦截并返回401未认证状态。

解决方案

方案1:针对特定路径关闭CSRF校验

在安全配置中,添加对/v1/user-subscription路径的CSRF忽略规则:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.csrf(csrf -> csrf.ignoringRequestMatchers("/v1/user-subscription"))
        .authorizeHttpRequests(auth -> auth
            .requestMatchers(new AntPathRequestMatcher("/v1/all", "GET"), 
                             new AntPathRequestMatcher("/v1/user-subscription", "POST"))
            .permitAll()
            .anyRequest().authenticated())
        .oauth2ResourceServer(oauth2 -> oauth2.jwt());
    return http.build();
}

方案2:全局关闭CSRF(仅适合无状态前后端分离场景)

如果你的应用是无状态的前后端分离架构,不存在CSRF攻击风险,可以全局关闭CSRF保护:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.csrf(csrf -> csrf.disable())
        .authorizeHttpRequests(auth -> auth
            .requestMatchers(new AntPathRequestMatcher("/v1/all", "GET"), 
                             new AntPathRequestMatcher("/v1/user-subscription", "POST"))
            .permitAll()
            .anyRequest().authenticated())
        .oauth2ResourceServer(oauth2 -> oauth2.jwt());
    return http.build();
}

其他排查方向

  • 检查请求路径是否完全匹配:确认实际请求的URL和配置中的/v1/user-subscription没有大小写、额外斜杠等差异。
  • 开启Spring Security调试日志:添加日志配置,查看请求是否被正确匹配到permitAll规则,排查是否有其他过滤器提前拦截请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:32:48