前端开发中的跨域访问问题

2025-04-02

最近在工作中做到了一些前端开发工作,由于工作环境受限,只能使用原生的js,在开发过程中遇到了跨域请求问题,特此记录。

一、为什么会出现跨域问题

本质上是浏览器有同源策略限制。同源策略(Same Origin Policy) 是一种约定,是浏览器最核心的安全功能,如果缺少了同源策略,浏览器的正常功能可能会受到影响。可以说,web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。

同源策略会阻止一个域的js脚本和另一个域的内容进行交互,所谓同源就是同一个域,即两个页面具有相同的协议、主机和端口号。

二、什么是跨域

当一个请求url的协议、域名和端口号三者之间任意一个与当前页面url不同,即为跨域。

当前页面url 请求url 是否跨域 原因
http://www.current.com http://www.request.com/index.html 协议、域名、端口号相同
http://www.current.com https://www.request.com/index.html 协议不同(http/https)
http://www.current.com http://www.baidu.com 域名不同
http://www.current.com http://current.com 主域名不同
http://www.current.com:8080 http://www.current.com:8081 端口号不同

我遇到的问题是无法使用js向后端发起http请求:

 const response = await fetch(API_URL, {
     method: 'POST',
     headers: {
         'Content-Type': 'application/json'
     },
     body: JSON.stringify({
         "model": "modelscope.cn/Qwen/Qwen2.5-3B-Instruct-GGUF:latest",
         "messages": [
             {"role": "user", "content": message}
         ],
         "stream": false
     })
 });

如代码所示,我需要调用云上部署的阿里通义千问大模型的api,在开发前端界面过程中出现了阻止跨域访问的问题,跨域原因是域名不同(本机与云服务器不域名不同)。

三、解决办法

跨域问题通常要在后端解决,前端虽然有一些可以跳过跨域检查的方法,但是存在安全问题,不推荐使用。

http.server

以原生的Python中requests库为例,在服务器收到请求之后,会执行预检操作,直接在预检请求中设置跨域请求头:

from http.server import BaseHTTPRequestHandler, HTTPServer

class CORSRequestHandler(BaseHTTPRequestHandler):
    def do_OPTIONS(self):
        """处理 OPTIONS 方法的预检请求"""
        self.send_response(200, "ok")
        
        # 添加 CORS 头
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type, Authorization')
        self.send_header('Access-Control-Max-Age', '86400')  # 24小时缓存
        
        self.end_headers()
    
    def do_GET(self):
        """处理 GET 请求时也需要包含 CORS 头"""
        self.send_response(200)
        self.send_header('Content-type', 'application/json')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.end_headers()
        
        response = {"message": "Hello, CORS!"}
        self.wfile.write(bytes(str(response), "utf-8"))

def run(server_class=HTTPServer, handler_class=CORSRequestHandler, port=8000):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print(f'Starting httpd server on port {port}...')
    httpd.serve_forever()

if __name__ == "__main__":
    run()

这样就可以实现跨域访问,但是注意,在开发环境中可以这样去写,方便调试和测试,但是在生产环境中,尽量不要使用这种写法:

 self.send_header('Access-Control-Allow-Origin', '*')

Flask

直接安装flask_cors库,然后通过以下方式可以直接接收跨域请求:

from flask import Flask, request, jsonify, make_response
from flask_cors import CORS  # 导入CORS
app = Flask(__name__)
CORS(app)  # 启用CORS,允许所有路由接受跨域请求

这种方式比较简单。