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
相关产品推荐
相关产品推荐

