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

调用OpenAI ChatGPT API时遭遇CORS策略错误的排查与解决

调用ChatGPT API时的CORS错误排查与解决

问题描述

"Access to fetch at 'https://api.chatgpt.com/answer?question=How%20are%20you?&api_key=sk-U3BPK...' from origin 'https://wordpress-......cloudwaysapps.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."

我已在托管环境的服务器端启用了CORS头部,但错误仍然存在。请问该问题的原因是什么?如何解决?

我的代码

<html>
<head>
  <script>
    function askQuestion() {
      var question = document.getElementById("questionInput").value;
      var apiKey = document.getElementById("apiKey").value;
      // 调用ChatGPT API并传入问题和API密钥
      fetch("https://api.chatgpt.com/answer?question=" + question + "&api_key=" + apiKey)
        .then(response => {
          if (!response.ok) {
            throw new Error("Failed to fetch answer from API");
          }
          return response.json();
        })
        .then(data => {
          // 将API返回的答案显示在文本框中
          document.getElementById("answerBox").value = data.answer;
        })
        .catch(error => {
          console.error("Error fetching answer from API: ", error);
        });
    }

    function askFollowUpQuestion() {
      var followUpQuestion = document.getElementById("followUpQuestionInput").value;
      var apiKey = document.getElementById("apiKey").value;
      // 调用ChatGPT API并传入追问和API密钥
      fetch("https://api.chatgpt.com/answer?question=" + followUpQuestion + "&api_key=" + apiKey)
        .then(response => {
          if (!response.ok) {
            throw new Error("Failed to fetch answer from API");
          }
          return response.json();
        })
        .then(data => {
          // 将API返回的答案显示在文本框中
          document.getElementById("followUpAnswerBox").value = data.answer;
        })
        .catch(error => {
          console.error("Error fetching answer from API: ", error);
        });
    }
  </script>
</head>
<body>
  <input type="text" id="questionInput" placeholder="Enter your question here"></input>
  <br>
  <input type="text" id="apiKey" placeholder="Enter your API key"></input>
  <br>
  <button onclick="askQuestion()">Ask</button>
  <br>
  <textarea id="answerBox" readonly></textarea>
  <br>
  <input type="text" id="followUpQuestionInput" placeholder="Enter your follow-up question here"></input>
  <br>
  <button onclick="askFollowUpQuestion()">Ask Follow-up</button>
  <br>
  <textarea id="followUpAnswerBox" readonly></textarea>
</body>
</html>

原因分析

  1. API端点错误:你调用的https://api.chatgpt.com/answer并非OpenAI官方的ChatGPT API端点,官方正确地址为https://api.openai.com/v1/chat/completions。非官方端点几乎不会配置允许你域名的CORS规则,而CORS权限由目标API服务器控制,你自己的前端托管服务器开启CORS完全无效。
  2. 密钥暴露风险:直接在前端通过URL参数传递API密钥,不仅会被浏览器拦截(敏感信息存URL不符合安全规范),还会导致密钥泄露——任何人查看页面源码都能获取你的密钥。
  3. 请求方式错误:官方ChatGPT API要求使用POST请求,且参数需放在请求体中,你使用的GET请求+URL拼接参数的方式不符合官方规范。

解决方法

步骤1:改用官方API与正确请求方式

使用OpenAI官方API端点,采用POST请求,通过请求体传递对话参数,通过Authorization请求头传递API密钥。

步骤2:搭建后端代理(核心解决CORS)

OpenAI官方API默认禁止前端直接跨域请求,必须搭建后端代理:由你的后端服务器转发请求到OpenAI API,前端仅请求自身后端,彻底规避CORS问题。

示例后端代理(Node.js/Express)

const express = require('express');
const axios = require('axios');
const cors = require('cors');
const app = express();

app.use(cors());
app.use(express.json());

// 代理ChatGPT请求
app.post('/api/chat', async (req, res) => {
  try {
    const { question, apiKey } = req.body;
    const response = await axios.post(
      'https://api.openai.com/v1/chat/completions',
      {
        model: "gpt-3.5-turbo",
        messages: [{ role: "user", content: question }]
      },
      {
        headers: {
          'Authorization': `Bearer ${apiKey}`,
          'Content-Type': 'application/json'
        }
      }
    );
    res.json({ answer: response.data.choices[0].message.content });
  } catch (error) {
    res.status(error.response?.status || 500).json({ error: error.message });
  }
});

app.listen(3000, () => console.log('代理服务器运行在端口3000'));

修改后的前端代码

<html>
<head>
  <script>
    async function askQuestion() {
      const question = document.getElementById("questionInput").value;
      const apiKey = document.getElementById("apiKey").value;
      try {
        const response = await fetch('/api/chat', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({ question, apiKey })
        });
        if (!response.ok) throw new Error('请求失败');
        const data = await response.json();
        document.getElementById("answerBox").value = data.answer;
      } catch (error) {
        console.error('请求出错:', error);
      }
    }

    async function askFollowUpQuestion() {
      const followUpQuestion = document.getElementById("followUpQuestionInput").value;
      const apiKey = document.getElementById("apiKey").value;
      try {
        const response = await fetch('/api/chat', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({ question: followUpQuestion, apiKey })
        });
        if (!response.ok) throw new Error('请求失败');
        const data = await response.json();
        document.getElementById("followUpAnswerBox").value = data.answer;
      } catch (error) {
        console.error('请求出错:', error);
      }
    }
  </script>
</head>
<body>
  <input type="text" id="questionInput" placeholder="输入你的问题"></input>
  <br>
  <input type="text" id="apiKey" placeholder="输入你的API密钥"></input>
  <br>
  <button onclick="askQuestion()">提问</button>
  <br>
  <textarea id="answerBox" readonly></textarea>
  <br>
  <input type="text" id="followUpQuestionInput" placeholder="输入你的追问"></input>
  <br>
  <button onclick="askFollowUpQuestion()">追问</button>
  <br>
  <textarea id="followUpAnswerBox" readonly></textarea>
</body>
</html>

步骤3:安全优化建议

  • 更安全的做法是将API密钥存储在后端环境变量中,前端无需输入密钥,避免泄露风险。
  • 确保后端服务器与前端托管在同一域名下,或后端配置精准的CORS规则,仅允许你的前端域名访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:16:08