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

带Authorization头的GET请求仅浏览器报错(CF API与Angular18)

CORS问题排查:ColdFusion自研API + Angular 18应用

问题概述

我们基于ColdFusion自研RestAPI,配置了以下CORS响应头:

cfheader (name="Access-Control-Allow-Origin", value="*");
cfheader (name="Access-Control-Allow-Headers", value="*");
cfheader (name="Access-Control-Allow-Methods", value="GET, POST, PUT, HEAD, OPTIONS");
cfheader (name="Access-Control-Allow-Credentials", value="true");

服务器已开放所有请求头和方法,Angular 18应用的登录接口(POST,无授权头)在Postman和浏览器中均正常,但登录成功后的GET请求出现差异:

  • 不带Authorization头时:Postman和浏览器均返回200,正常响应
  • 带有效Authorization令牌时:仅Postman能获取有效响应,浏览器的OPTIONS预飞行请求和后续GET请求均报500 CORS错误

我们对比两种请求的头信息几乎一致,疑惑为何浏览器与Postman表现不同,且添加任意自定义头都会触发问题。

相关代码

Angular 18拦截器代码

if (req.headers.has('no-auth')) {
    req = req.clone({
      headers: req.headers.delete('no-auth', 'true'),
      setHeaders: { Accept: 'application/json' },
    });
    return next(req);
  } else {
    /* Token: */
    let Token = localStorage.getItem('Token')
      ? localStorage.getItem('Token')
      : '';
    const auth_headers = req.headers.set('Authorization', `${Token}`);

    // Clone the request and add the authorization header
    const authReq = req.clone({/*auth_headers*/});
    return next(authReq);
  }

注:拦截器尚未完成

补充API配置(OPTIONS预飞行处理)

// Handle CORS preflight request
if (cgi.request_method == "OPTIONS") {
    cfheader(name="Access-Control-Allow-Origin", value="http://localhost:4004");
    cfheader(name="Access-Control-Allow-Headers", value="Content-Type, Authorization");
    cfheader(name="Access-Control-Allow-Methods", value="GET, POST, PUT, DELETE, OPTIONS");
    cfheader(name="Access-Control-Allow-Credentials", value="true");
    cfheader(statuscode="200", statustext="OK");
    cfexit();
}

// Your actual API logic here
cfheader(name="Access-Control-Allow-Origin", value="*");
cfheader(name="Access-Control-Allow-Headers", value="*");
cfheader(name="Access-Control-Allow-Methods", value="GET, POST, PUT, DELETE, OPTIONS");
cfheader(name="Access-Control-Allow-Credentials", value="true");

核心原因分析

  1. CORS规则冲突:通配符与Credentials不兼容
    浏览器严格遵循CORS规范:当Access-Control-Allow-Credentials设为true时,Access-Control-Allow-Origin不能使用通配符*,必须指定具体的前端源(如http://localhost:4004)。Postman作为非浏览器工具,不会强制校验这一规则,因此能正常响应。

  2. OPTIONS预飞行与实际请求的Origin不一致
    当前配置中,OPTIONS预飞行请求返回的Access-Control-Allow-Origin是具体源http://localhost:4004,但实际API请求返回的是*,浏览器会判定这两个Origin不匹配,直接拦截请求并抛出CORS错误。

  3. 拦截器代码的潜在问题
    拦截器中克隆请求时注释掉了auth_headers参数(const authReq = req.clone({/*auth_headers*/});),导致修改后的Authorization头没有正确附加到请求中,可能引发后续的认证逻辑错误,间接导致500状态码。

修复方案

  • 统一Origin配置:将所有请求(包括OPTIONS预飞行和实际API请求)的Access-Control-Allow-Origin都设置为前端应用的具体源(如http://localhost:4004),彻底移除通配符*。
  • 保持CORS头一致性:确保OPTIONS预飞行返回的Access-Control-Allow-Headers、Access-Control-Allow-Methods与实际API请求的配置完全一致,避免浏览器判定规则冲突。
  • 修复拦截器代码:正确传递修改后的请求头,将克隆请求的代码改为:
    const authReq = req.clone({ headers: auth_headers });
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:50:16