You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

开启Cloudflare Under Attack Mode时出现CORS问题的原因及解决方案咨询

Cloudflare Under Attack Mode引发CORS问题的原因与解决方案

首先明确回答:是的,Cloudflare的Under Attack Mode确实可能引发CORS问题,主要和它的JS挑战机制有关,下面我会一步步拆解原因、对应的解决方案,以及你提到的请求头限制相关问题。

一、为什么Under Attack Mode会触发CORS?

Under Attack Mode开启后,Cloudflare会对所有入站请求先返回一个JavaScript挑战页面,验证访问者是人类而非自动化脚本。但你的前端Apollo Client在发起GraphQL请求时,是直接发送的AJAX请求,不会自动处理这个JS挑战——这就导致Cloudflare返回的挑战响应没有符合CORS要求的头信息(比如Access-Control-Allow-Origin),浏览器因此抛出CORS错误。而关闭模式后,挑战被跳过,后端正常返回带正确CORS头的响应,所以问题消失。

二、核心解决方案:绕过GraphQL接口的挑战

因为你的GraphQL接口是固定路径(比如/graphql),完全可以让Cloudflare跳过对这个路径的挑战,具体操作步骤:

  1. 登录Cloudflare控制台,进入你的域名管理页
  2. 导航到「防火墙」→「防火墙规则」
  3. 点击「创建规则」,设置匹配条件:
    • 选择「URI路径」→「等于」,填入你的GraphQL接口路径(例如/graphql
  4. 动作选择「跳过」→「托管挑战(由Under Attack Mode使用)」
  5. 保存规则后,针对这个接口的请求就不会再触发JS挑战,CORS问题应该会立即缓解。

三、确保后端CORS配置兼容Cloudflare

即使绕过了挑战,也需要确保后端的CORS配置是正确的,避免Cloudflare代理后出现头信息丢失或不匹配的情况。以你的Apollo Server为例,调整CORS配置如下:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  cors: {
    origin: 'https://fronend.com', // 严格指定你的前端域名,避免通配符带来的问题
    credentials: true, // 如果前端需要携带Cookie或认证信息,务必开启
    allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'], // 包含Apollo Client常用的请求头
    exposedHeaders: ['Content-Length', 'X-Custom-Header'] // 如果有自定义响应头需要前端读取,这里添加
  },
});

另外,检查Cloudflare的「转换规则」→「修改响应头」,确保没有规则意外修改或移除了Access-Control-*系列头。

四、Cloudflare对请求头的限制及应对

Under Attack Mode下,Cloudflare确实会对请求头有一定限制:

  • 它可能会拦截带有特殊字符、不规范格式的自定义头
  • 部分罕见的请求头可能被当作自动化请求的特征而拦截

应对方法:

  1. 检查前端Apollo Client的请求配置,避免使用过于特殊的自定义头,如果必须使用,确保头名符合HTTP规范
  2. 前往Cloudflare「防火墙」→「分析」,查看被拦截的请求记录,筛选和你的GraphQL请求相关的条目,查看拦截原因是否和请求头有关
  3. 如果确认是特定头被拦截,可以在防火墙规则中添加例外:针对包含该头的请求,跳过挑战或放行

五、其他可能的原因及排查方向

  • 缓存问题:Cloudflare可能缓存了错误的CORS响应,尝试在「缓存」→「清除缓存」中清除全部缓存,再测试
  • SSL/TLS配置:确保Cloudflare的SSL模式设置为「完全」或「严格」,避免前端和Cloudflare、Cloudflare和后端之间出现SSL不兼容的情况,这可能间接导致CORS错误
  • 请求超时:前端请求在等待Cloudflare挑战完成时超时,表现为CORS错误。可以调整Apollo Client的超时设置:
    const client = new ApolloClient({
      uri: 'https://backend.com/graphql',
      cache: new InMemoryCache(),
      defaultOptions: {
        query: {
          fetchPolicy: 'network-only',
          timeout: 10000, // 延长超时时间到10秒
        },
      },
    });
    

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

火山引擎 最新活动