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

Spring Security中hasAuthority()权限控制部分路径生效、部分路径失效的问题排查

解决Spring Security + React跨域403问题的步骤

兄弟,我看了你的问题和日志,发现核心问题出在跨域请求的凭证携带和路径匹配/过滤器顺序上——Postman能正常访问是因为它不会触发浏览器的跨域预检机制,而前端React会,所以才出现了差异。咱们一步步来解决:

1. 给前端请求补上凭证配置

你的CORS已经开启了AllowCredentials=true,但前端必须配合显式设置凭证携带,否则浏览器会自动丢弃Authorization这类敏感请求头,Spring Security拿不到JWT令牌自然返回403。

如果用Axios发送请求,要这么写:

axios.get('http://localhost:8080/item/', {
  withCredentials: true,
  headers: {
    'Authorization': 'Bearer ' + 你的JWT令牌
  }
})

如果用Fetch API:

fetch('http://localhost:8080/item/', {
  method: 'GET',
  credentials: 'include',
  headers: {
    'Authorization': 'Bearer ' + 你的JWT令牌
  }
})

2. 修正Spring Security的路径匹配与CORS配置

从安全日志里能看到,你实际请求的是/item/noSale/,但权限配置里只写了/item/——这是精确匹配,不会覆盖子路径。另外你同时配置了独立的CorsFilter Bean和http.cors(),容易导致过滤器顺序冲突,建议整合配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
        // 直接在Security内配置CORS,避免过滤器顺序问题
        .cors(cors -> cors.configurationSource(corsConfigurationSource()))
        .authorizeRequests()
        // 合并匹配规则,用/**覆盖/item下所有子路径,包括/item/noSale/
        .antMatchers("/worker/login/").permitAll()
        .antMatchers("/item/**", "/worker/getUserDetails/").hasAuthority("USER")
        .anyRequest().authenticated()
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}

// 将CORS配置与Security整合
private CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
    configuration.setAllowedMethods(Arrays.asList("*"));
    configuration.setAllowedHeaders(Arrays.asList("*"));
    configuration.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

3. 让JWT过滤器跳过OPTIONS预检请求

浏览器发送跨域请求前,会先发送OPTIONS预检请求,这个请求不会携带Authorization头。如果你的JWT过滤器硬要校验这个请求,会直接判定为未认证,所以得在过滤器里加判断跳过:

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
    // 跳过OPTIONS预检请求,直接放行
    if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
        response.setStatus(HttpServletResponse.SC_OK);
        chain.doFilter(request, response);
        return;
    }
    // 原有JWT校验逻辑继续执行...
}

4. 最后确认权限的大小写匹配

Spring Security的权限是区分大小写的,你得确保worker.getRole()返回的是大写的"USER"(和你配置的hasAuthority("USER")完全一致)。可以在getAuthorities()方法里加日志,或者在/item/的控制器里打印当前用户权限做验证:

@GetMapping("/") 
public ResponseEntity<List<Item>> getAllItems(Authentication auth){ 
    System.out.println("当前用户权限:" + auth.getAuthorities());
    return new ResponseEntity<>(itemService.noSale(), HttpStatus.OK); 
}

按照这几步逐一排查,应该就能解决前端请求返回403的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 20:19:05