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

为何Spring Security配置permitAll()后/upload端点仍需认证并返回403?

问题:Spring Boot 3.2.2 + Spring Security中/upload端点permitAll()不生效

我使用Spring Boot 3.2.2搭配Spring Security,已为3个端点配置permitAll(),但仅/upload端点不生效:它仍要求认证,且认证后返回403。即使将其移至ADMIN或USER的requestMatchers()中,依然返回403,其他端点则正常工作。

这些端点的唯一区别是:/upload是接收MultipartFile的POST请求,其余为简单GET请求。


控制器代码示例

@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
    // 业务逻辑代码
}

安全配置代码示例

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.formLogin(Customizer.withDefaults())
            .authorizeHttpRequests((authorize) -> authorize
                    .requestMatchers("/test/user").hasRole(UserRole.USER.name())
                    .requestMatchers("/test/admin").hasRole(UserRole.ADMIN.name())
                    .requestMatchers("/test/no-role", "/upload", "/api/ai/generate").permitAll()
                    .anyRequest().authenticated()
            );
    return http.build();
}

更新:DEBUG级别日志

2024-02-13T12:50:34.003+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing POST /upload
2024-02-13T12:50:34.005+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.security.web.csrf.CsrfFilter         : Invalid CSRF token found for http://localhost:8080/upload
2024-02-13T12:50:34.007+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.s.w.access.AccessDeniedHandlerImpl   : Responding with 403 status code
2024-02-13T12:50:34.009+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing POST /error
2024-02-13T12:50:34.009+02:00 DEBUG 16611 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : Retrieved SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=admin, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, CredentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=7579E5587784A8B4847F2571BCD188A2], Granted Authorities=[ROLE_ADMIN]]]
2024-02-13T12:50:34.009+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Secured POST /error
2024-02-13T12:50:34.009+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for POST "/error", parameters={}
2024-02-13T12:50:34.010+02:00 DEBUG 16611 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2024-02-13T12:50:34.010+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2024-02-13T12:50:34.012+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json]
2024-02-13T12:50:34.013+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [{timestamp=Tue Feb 13 12:50:34 EET 2024, status=403, error=Forbidden, path=/upload}]
2024-02-13T12:50:34.022+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2024-02-13T12:50:34.022+02:00 DEBUG 16611 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 403

问题原因与解决方案

从DEBUG日志可以直接定位问题:Invalid CSRF token found for http://localhost:8080/upload,这说明CSRF保护拦截了你的POST请求。

Spring Security默认会对所有非GET请求启用CSRF校验,哪怕端点配置了permitAll(),CSRF校验依然会生效——这就是为什么其他GET端点正常,而POST的/upload出问题的核心原因。

解决方案一:给/upload端点禁用CSRF校验

修改SecurityFilterChain配置,添加csrf忽略规则:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.formLogin(Customizer.withDefaults())
            .csrf(csrf -> csrf.ignoringRequestMatchers("/upload")) // 忽略该路径的CSRF校验
            .authorizeHttpRequests((authorize) -> authorize
                    .requestMatchers("/test/user").hasRole(UserRole.USER.name())
                    .requestMatchers("/test/admin").hasRole(UserRole.ADMIN.name())
                    .requestMatchers("/test/no-role", "/upload", "/api/ai/generate").permitAll()
                    .anyRequest().authenticated()
            );
    return http.build();
}

解决方案二:在请求中携带有效CSRF Token

如果不想禁用CSRF保护,可在POST请求中携带CSRF Token:

  • 前端:从Cookie中获取XSRF-TOKEN,在请求头中添加X-XSRF-TOKEN字段,值为获取到的Token
  • 后端测试:用Postman等工具先登录获取Cookie中的CSRF Token,再在请求头中添加对应字段

注意事项

  • 若/upload是公开接口(无需用户认证),推荐方案一,这类接口通常不需要CSRF保护
  • 若接口需要用户认证,建议保留CSRF保护,采用方案二

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:07:33