React端Authorization token无法通过Java Spring Boot过滤器问题排查
问题根源
- 首先是浏览器CORS预检请求机制:跨域请求携带自定义头(如Authorization)时,浏览器会先发送
OPTIONS方法的预检请求,该请求不会携带任何自定义请求头,仅用于校验服务端是否允许当前跨域请求。你当前的过滤器未对OPTIONS请求做特殊处理,直接尝试读取Authorization头并调用substring方法,触发空指针异常,导致预检请求未返回200状态码,浏览器直接拦截后续正式请求,所以你看不到正式请求里的Authorization头。Postman不会触发CORS预检机制,因此请求可以正常执行。 - 其次CORS配置不完整:你当前的CORS配置未显式声明允许
Authorization请求头,也未将OPTIONS加入允许的方法列表,即使过滤器不报错,预检请求也无法通过校验。 - 额外隐患:你注入的
UserDetails默认是单例Bean,多并发请求下会出现用户信息覆盖的线程安全问题。
修复方案
- 修改过滤器逻辑,放行OPTIONS请求并增加空校验
修改doFilter方法开头的逻辑如下:
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; // 放行OPTIONS预检请求 if ("OPTIONS".equalsIgnoreCase(httpRequest.getMethod())) { chain.doFilter(request, response); return; } // 增加Authorization头空校验,避免空指针 String authHeader = httpRequest.getHeader("Authorization"); if (authHeader == null || !authHeader.startsWith("Bearer ")) { throw new AuthenticationException("Missing or invalid Authorization header."); } String token = authHeader.substring(7); // 后续原有逻辑不变 ... }
- 补全CORS配置
修改WebConfig的addCorsMappings方法,增加允许的请求头和OPTIONS方法:
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedMethods("PUT", "DELETE","POST","GET", "OPTIONS") .allowedOrigins("*") .allowedHeaders("Authorization", "Content-Type") .exposedHeaders("*") .maxAge(3600); // 缓存1小时预检结果,减少重复预检请求 }
- 修复UserDetails线程安全问题
给UserDetails的Bean定义增加请求作用域注解,确保每个请求对应一个独立实例:
@Component @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) public class UserDetails { // 原有逻辑不变 }
其他获取Token的可选方式
如果有特殊场景无法使用请求头传递Token,也可以将Token放在URL请求参数中传递(如/image?token=xxx),后端通过httpRequest.getParameter("token")获取,但该方式会让Token暴露在日志等位置,安全性低于请求头传递,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者Olga
相关产品推荐
相关产品推荐

