Azure部署Angular+Nest.js应用突发生产/UAT环境CORS错误咨询
问题判定
双环境同时突发CORS报错、无代码变更无部署、本地运行正常,大概率是Azure平台侧的配置变更/默认规则更新导致的,和业务代码逻辑无关。
这类无改动突发CORS问题在Azure App Service上非常常见,核心原因是平台滚动更新时,内置的CORS、身份验证、边缘缓存模块会覆盖应用层返回的响应头,你看到的No 'Access-Control-Allow-Origin' header本质是预检请求(OPTIONS)被Azure层拦截或者响应头被过滤了,根本没走到你的Nest.js应用逻辑。
高频触发原因排查
按出现概率从高到低排序:
- Azure App Service内置CORS规则和Nest.js框架层CORS规则冲突:如果你之前同时在两层配置了CORS,平台更新后会优先返回Azure层的CORS头,一旦Azure层配置为空或者规则不匹配,就会直接不返回
Access-Control-Allow-Origin头,哪怕你Nest里配置是对的也没用 - 平台自动开启/更新了Easy Auth(App Service身份验证授权)功能:这个功能会在请求到达应用前拦截所有未携带认证信息的请求,OPTIONS预检请求默认不会带认证Cookie/Token,会被直接拦截返回401/403,响应里自然不带CORS头
- 如果你用了Azure CDN、Front Door、Application Gateway这类边缘代理,边缘规则更新、节点缓存异常也会直接过滤掉应用返回的CORS头,双环境同时出问题可以优先查下是否订阅级别的边缘规则做了统一调整
- 有个容易忽略的细节:如果Azure内置CORS配置了
*(允许所有源),同时你的GraphQL接口开启了credentials: include,浏览器会直接判定CORS校验不通过,表现和缺少响应头完全一致
Access-Control-Allow-Origin头配置位置选择 绝对不要多层重复配置CORS,只选一层配置即可,多层配置必出冲突,优先选框架层配置,稳定性最高,不受平台更新影响:
- 框架层配置(推荐)
第一步先彻底关掉Azure侧的CORS功能:- 进入对应App Service资源,在左侧菜单找到「API」分类下的「CORS」选项
- 清空所有已配置的允许源列表,不要留任何域名也不要选允许所有源,保存配置
第二步确认Nest.js侧的CORS配置(你本地运行正常说明配置本身没问题,重点确认GraphQL相关的预检请求放行):
// src/main.ts 配置示例 async function bootstrap() { const app = await NestFactory.create(AppModule); app.enableCors({ // 明确写死所有允许的前端域名,不要用* origin: [ 'https://example-production.azurewebsites.net', 'https://example-uat.azurewebsites.net' ], credentials: true, // 必须放行OPTIONS预检请求 methods: ['GET', 'POST', 'OPTIONS'], // 把GraphQL需要的自定义头加进去,比如Apollo客户端的预检头 allowedHeaders: ['Content-Type', 'Authorization', 'Apollo-Require-Preflight'] }); // 如果关了Azure CORS还是报预检错误,取消下面注释,加全局中间件强制响应OPTIONS请求 // app.use((req, res, next) => { // if (req.method === 'OPTIONS') return res.sendStatus(204); // next(); // }); await app.listen(process.env.PORT || 3000); } bootstrap(); - Azure平台层配置(不推荐,容易被平台更新覆盖)
如果你不想在代码里维护CORS规则,就把Nest.js里所有enableCors相关的代码全部删掉,然后在App Service的CORS配置页逐条添加你需要放行的前端域名,不要选「允许所有源」,保存即可。如果用了边缘代理,就在边缘规则引擎里添加响应头规则,匹配对应来源时注入Access-Control-Allow-Origin头,同时放行OPTIONS请求。
快速验证步骤
- 先用Postman/curl直接发OPTIONS请求到报错的GraphQL接口,不要带任何自定义头,如果返回的响应里没有
Access-Control-Allow-Origin,说明请求根本没走到Nest应用,是Azure层拦截了 - 如果Postman里能看到正常的CORS头,浏览器里看不到,先清掉前端站点和后端接口的浏览器缓存,再检查是否有凭证配置和通配源的冲突
- 如果开了Easy Auth,去身份验证配置页把「未经身份验证的请求时采取的操作」改成「允许未经身份验证的请求」,让请求能正常走到应用逻辑即可。
内容的提问来源于stack exchange,提问作者Tom Bom
相关产品推荐
相关产品推荐

