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

含凭证请求CORS通配符*报错,客户端如何解决?

CORS错误与WebSocket拦截器未触发问题解决

问题详情

遇到如下CORS错误:

Access to XMLHttpRequest at 'https://my.domain/api/chat/info?t=1701325904808' from origin 'http://localhost:8100' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
chatItemMessage.page.ts:40 GET https://my.domain/api/chat/info?t=1701325904808 net::ERR_FAILED 200 (OK)

对接使用SockJS的Spring Boot后端,安装了以下依赖:

npm install sockjs-client
npm install stompjs

编写了AppHttpInterceptor用于添加请求头,但上述GET请求从未触发该拦截器,拦截器代码如下:

@Injectable()
export class AppHttpInterceptor implements HttpInterceptor {

constructor(protected authService: AuthService, private router: Router) { }

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return from(this.authService.getToken()).pipe(
        switchMap((token) => {
            const tokenString: string = token as string;
            if(token) {
                let authReq = req.clone({
                    setHeaders: {  
                        'x-auth-token': tokenString,
                        'Content-Type': 'application/json'
                        }
                });
                return next.handle(authReq);
            } else {
                return next.handle(req);
            } 
        })
    );
  }
}  

当前WebSocket连接代码:

const socket = new SockJS('https://my.domain/api/chat');
const stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
    alert('connected StompClient in chatItemMessage.page.ts');    
});

需求:寻找客户端侧的解决办法,同时解决拦截器未触发的问题。


客户端侧解决方案

1. 拦截器未触发的原因与修复

Angular的HttpInterceptor仅拦截Angular HttpClient发起的请求,而SockJS内部使用原生XMLHttpRequest/fetch发起请求,不会走Angular的拦截器链。需要手动给SockJS配置请求头:

// 先获取token(注意如果是异步方法要加await)
const token = await authService.getToken();

const socket = new SockJS('https://my.domain/api/chat', {}, {
  transports: ['xhr-streaming', 'xhr-polling'], // 指定用XMLHttpRequest传输
  headers: {
    'x-auth-token': token,
    'Content-Type': 'application/json'
  },
  withCredentials: true // 根据需求决定是否开启,开启后后端不能用*作为允许源
});

const stompClient = Stomp.over(socket);
// 也可以在stomp连接时额外携带header
stompClient.connect({'x-auth-token': token}, function(frame) {
    alert('connected StompClient in chatItemMessage.page.ts');    
});

2. CORS错误的针对性调整

根据错误提示,有两种客户端调整方向:

  • 无需携带凭证时:关闭withCredentials,此时后端用*作为Access-Control-Allow-Origin是合法的:
    const socket = new SockJS('https://my.domain/api/chat', {}, {
      withCredentials: false
    });
    
  • 必须携带凭证时:客户端无法绕过限制,只能要求后端将Access-Control-Allow-Origin设置为具体源(如http://localhost:8100),同时添加Access-Control-Allow-Credentials: true响应头。

3. 开发环境本地代理方案

开发阶段可以通过Angular代理绕过CORS:

  1. 项目根目录创建proxy.conf.json:
{
  "/api": {
    "target": "https://my.domain",
    "secure": true,
    "changeOrigin": true,
    "pathRewrite": {
      "^/api": "/api"
    }
  }
}
  1. 修改angular.json的serve配置,添加代理引用:
"serve": {
  "builder": "@angular-devkit/build-angular:dev-server",
  "options": {
    "browserTarget": "你的项目名:build",
    "proxyConfig": "proxy.conf.json"
  }
}
  1. 修改WebSocket连接地址为本地代理路径:
const socket = new SockJS('/api/chat');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 06:08:11