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

浏览器调用API时request.getHeader("Authorization")为null,Postman正常

问题原因
  • Postman属于接口调试工具,不受浏览器同源策略约束,不会自动发起CORS预检请求,会直接携带配置的所有请求头发送实际业务请求,因此可以正常读取到Authorization头。
  • 浏览器在跨域场景下发送包含Authorization这类自定义请求头的请求前,会自动先发送OPTIONS方法的预检请求,预检请求本身不会携带任何业务自定义请求头(包括Authorization),原过滤器不分请求类型直接读取头,在预检请求阶段读到的必然是null。
  • 原CORS配置存在兼容性问题:Access-Control-Allow-Headers使用通配符*在部分浏览器版本、以及请求携带凭证(如Cookie、Authorization认证信息)的场景下不会生效,会导致预检不通过,浏览器根本不会发送后续携带Authorization的实际业务请求。另外如果请求开启了withCredentials,Access-Control-Allow-Origin设置为*也会被浏览器直接拦截。
解决方法
  • 区分预检请求和实际业务请求:仅在非OPTIONS的实际业务请求中读取Authorization等业务头,不要在预检请求阶段读取业务参数。
  • 不要滥用通配符配置CORS头,明确声明允许的请求头包含Authorization,如果业务需要携带凭证,要动态匹配允许的请求源,同时开启Access-Control-Allow-Credentials配置。
  • 预检请求处理完成后直接返回200状态码结束响应,确保预检通过后浏览器自动发起实际业务请求。
修正后代码
package com.web.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter{
    
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws 
        IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        
        // 动态获取请求源,替换*解决带凭证场景的跨域问题
        String origin = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", origin == null ? "*" : origin);
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        // 明确声明允许Authorization头,不要用通配符*
        response.setHeader("Access-Control-Allow-Headers", "Authorization,Content-Type,X-Requested-With");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {  
            // 预检请求直接返回200,不需要执行业务逻辑、读取业务头
            response.setStatus(HttpServletResponse.SC_OK);
            return;
        } 
        // 仅非预检的实际业务请求才走后续链路,在这里读取Authorization头即可拿到值
        String header = request.getHeader("Authorization");
        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }
}

补充说明:如果业务不需要跨域携带Cookie等凭证,也可以保留Access-Control-Allow-Origin为*,同时删除Access-Control-Allow-Credentials的配置,但依然需要明确在Access-Control-Allow-Headers中列出Authorization,不能仅用通配符。

内容的提问来源于stack exchange,提问作者Madan Mohan Mishra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:57:23