Python案例怎么解决跨域报错?

wen python案例 18

本文目录导读:

Python案例怎么解决跨域报错?

  1. Flask 解决方案
  2. Django 解决方案
  3. FastAPI 解决方案
  4. 通用手动方案(不依赖第三方库)
  5. 常见问题与排查

解决Python(尤其是Flask/Django/FastAPI等Web框架)的跨域报错(CORS,Cross-Origin Resource Sharing,跨域资源共享问题),核心是在服务端进行配置,明确告诉浏览器“允许来自其他域名的请求”。

常见的跨域报错信息类似:

Access to XMLHttpRequest at 'http://localhost:5000/api/data' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

下面针对不同框架给出具体的解决方法和代码案例。


Flask 解决方案

推荐使用第三方库 flask-cors,它最简洁、最安全。

安装

pip install flask-cors

全局启用(推荐开发环境或用) 让整个应用的所有路由都支持跨域。

from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app)  # 默认允许所有来源
@app.route('/api/data')
def get_data():
    return jsonify({"message": "Hello from Flask!"})
if __name__ == '__main__':
    app.run(debug=True)

指定允许的来源(生产环境推荐) 只允许特定的域名访问,提高安全性。

from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
# 只允许 http://localhost:3000 访问
CORS(app, origins='http://localhost:3000')
@app.route('/api/data')
def get_data():
    return jsonify({"message": "Hello from specific origin!"})
if __name__ == '__main__':
    app.run(debug=True)

仅对单个路由启用(精细控制)

from flask import Flask, jsonify
from flask_cors import cross_origin
app = Flask(__name__)
@app.route('/api/data')
@cross_origin(origins='http://localhost:3000')  # 只允许这个路由跨域
def get_data():
    return jsonify({"message": "Hello from specific route!"})
if __name__ == '__main__':
    app.run(debug=True)

Django 解决方案

推荐使用 django-cors-headers

安装

pip install django-cors-headers

配置步骤

  1. settings.pyINSTALLED_APPS 中添加 'corsheaders'
  2. MIDDLEWARE 中(尽量靠前,通常在 CommonMiddleware 之前)添加 'corsheaders.middleware.CorsMiddleware'
  3. 设置允许的来源。
# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    '...',
    'corsheaders',  # 添加这一行
    'your_app',
]
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',  # 建议放在最前面
    'django.middleware.common.CommonMiddleware',
    # ... 其他中间件
]
# 方案A: 允许所有来源(开发用,生产环境危险)
CORS_ALLOW_ALL_ORIGINS = True
# 方案B: 指定白名单(生产环境推荐)
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
    "https://your-frontend.com",
]
# 允许携带 Cookie(如果需要)
CORS_ALLOW_CREDENTIALS = True
# 允许的 HTTP 方法
CORS_ALLOW_METHODS = [
    'GET',
    'POST',
    'PUT',
    'PATCH',
    'DELETE',
    'OPTIONS',
]
# 允许的请求头
CORS_ALLOW_HEADERS = [
    'accept',
    'authorization',
    'content-type',
    'x-csrftoken',
]

FastAPI 解决方案

FastAPI 基于 Starlette,可以使用 starlette.middleware.cors 中间件。

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# 配置允许的来源
origins = [
    "http://localhost:3000",  # 你的前端地址
    "http://localhost:5173",  # Vite 默认端口
    "https://your-frontend.com",
]
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],  # 允许所有方法
    allow_headers=["*"],  # 允许所有请求头
)
@app.get("/api/data")
async def get_data():
    return {"message": "Hello from FastAPI!"}
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

通用手动方案(不依赖第三方库)

如果你不想安装第三方库,可以自己手动在响应头中添加 CORS 头。这种方式只适合非常简单的场景,因为还需要处理预检请求(OPTIONS 方法)。

from flask import Flask, jsonify, make_response
app = Flask(__name__)
@app.after_request
def add_cors_headers(response):
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
    response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
    return response
@app.route('/api/data')
def get_data():
    return jsonify({"message": "Manual CORS"})
if __name__ == '__main__':
    app.run(debug=True)

常见问题与排查

  1. 为什么会报错?

    • 浏览器的同源策略,浏览器会阻止从一个域名(如 http://localhost:3000)向另一个域名(如 http://localhost:5000)发起的 AJAX 请求,除非服务器明确告诉浏览器“允许这个请求”。
    • 同源:协议、域名、端口三者完全相同,只要有一个不同,就构成跨域。
  2. 预检请求(Preflight)

    • 当请求不是简单请求(例如使用了 PUT/DELETE 方法、自定义请求头、Content-Type: application/json)时,浏览器会先发送一个 OPTIONS 请求(预检请求),询问服务器是否允许后续的正式请求。
    • 解决方案:服务器必须正确处理 OPTIONS 请求,并返回 Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers 等响应头,前面的所有代码示例都自动处理了这一点。
  3. 使用 Nginx 或反向代理

    • 如果你的后端(Python 应用)位于 Nginx 之后,你也可以在 Nginx 层面配置 CORS,而不是在 Python 应用层面。
    • Nginx 配置示例
      location /api/ {
          add_header 'Access-Control-Allow-Origin' '*';
          add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
          # ... 其他配置
      }
  4. 生产环境注意事项

    • *不要使用 `Access-Control-Allow-Origin: *` 允许所有来源,生产环境中应替换为具体的域名。
    • Credentials:如果你的请求需要携带 Cookie 或 Authorization 头,Access-Control-Allow-Origin *不能是 `**,必须是指定的具体域名,且需要设置Access-Control-Allow-Credentials: true`。
  5. 兜底方案(不推荐)

    • 如果你的后端和前端都部署在同一台服务器上,可以不解决 CORS 问题,而是通过反向代理(如 Nginx 或 Vite 的 proxy 配置)将前端对后端的请求代理到同一个端口下,从而避免跨域。

框架 推荐方案 关键配置
Flask flask-cors CORS(app)CORS(app, origins=[...])
Django django-cors-headers settings.py 中添加中间件和 CORS_ALLOWED_ORIGINS
FastAPI CORSMiddleware app.add_middleware(CORSMiddleware, ...)

最简单的起步命令:根据你的后端框架,复制上面的“全局启用”代码,将 origins 改为你的前端地址,然后重启后端服务即可。

抱歉,评论功能暂时关闭!