首页 > 基础知识 > 跨域 cors教程 python代码示例

跨域 cors教程 python代码示例

2025-04-03 14:16:33

一、Python CORS 解决方案总览

框架 推荐方案 特点
Flask flask-cors 扩展 简单易用,支持细粒度控制
Django django-cors-headers 中间件 配置化,适合 Django 生态
原生 WSGI 手动设置响应头 灵活但需要自行处理逻辑

二、Flask 框架实现 CORS

1. 安装依赖

pip install flask-cors

2. 基础全局配置(允许所有源)

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": "CORS enabled for all origins"})

if __name__ == '__main__':
    app.run(port=5000)
from flask import Flask, jsonify, make_response
from flask_cors import CORS

app = Flask(__name__)
CORS(
    app,
    origins=["https://your-frontend.com", "http://localhost:3000"],  # 允许的域名
    supports_credentials=True,  # 允许携带 Cookie
    methods=["GET", "POST", "PUT", "DELETE"],  # 允许的方法
    allow_headers=["Content-Type", "Authorization"]  # 允许的请求头
)

@app.route('/api/login')
def login():
    response = make_response(jsonify({"status": "Logged in"}))
    response.set_cookie(
        'user_token', 
        'token_value',
        secure=True,    # 仅 HTTPS
        httponly=True,
        samesite='None' # 允许跨站 Cookie
    )
    return response

if __name__ == '__main__':
    app.run(ssl_context='adhoc')  # 测试用自签名 HTTPS

4. 动态允许域名(高级场景)

from flask import Flask, request, jsonify
from flask_cors import CORS

app = Flask(__name__)
cors = CORS()  # 创建 CORS 实例

def dynamic_origin_check(origin):
    # 自定义逻辑:检查域名是否在白名单
    allowed_origins = ["https://trusted.com", "http://localhost:3000"]
    return origin in allowed_origins

@app.route('/api/data')
def get_data():
    # 手动设置响应头(示例)
    origin = request.headers.get('Origin')
    if dynamic_origin_check(origin):
        response = jsonify({"data": "Dynamic CORS allowed"})
        response.headers['Access-Control-Allow-Origin'] = origin
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        return response
    else:
        return jsonify({"error": "Origin not allowed"}), 403

if __name__ == '__main__':
    cors.init_app(app)  # 初始化 CORS
    app.run(port=5000)

三、Django 框架实现 CORS

1. 安装依赖

pip install django-cors-headers

2. 配置 settings.py

# settings.py

INSTALLED_APPS = [
    ...
    'corsheaders',  # 添加应用
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',  # 尽量靠前
    ...
]

# CORS 配置
CORS_ALLOWED_ORIGINS = [
    "https://your-frontend.com",
    "http://localhost:3000",
]

CORS_ALLOW_CREDENTIALS = True  # 允许 Cookie
CORS_ALLOW_METHODS = [
    'GET',
    'POST',
    'PUT',
    'DELETE',
    'OPTIONS',
]
CORS_ALLOW_HEADERS = [
    'content-type',
    'authorization',
]
# views.py
from django.http import JsonResponse

def api_data(request):
    response = JsonResponse({"data": "Django CORS enabled"})
    response.set_cookie(
        'session_id', 
        'abc123',
        secure=True,
        httponly=True,
        samesite='None',
        max_age=3600
    )
    return response

四、原生 WSGI 应用实现(如 Bottle)

from bottle import Bottle, response, request

app = Bottle()

# 手动设置 CORS 头
def enable_cors():
    origin = request.headers.get('Origin', '*')
    response.headers['Access-Control-Allow-Origin'] = origin
    response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS'
    response.headers['Access-Control-Allow-Headers'] = 'Origin, Content-Type, Authorization'
    response.headers['Access-Control-Allow-Credentials'] = 'true'

@app.hook('after_request')
def apply_cors():
    enable_cors()

@app.route('/api/data')
def get_data():
    return {"message": "Manual CORS handling"}

if __name__ == '__main__':
    app.run(port=8080)

五、关键注意事项

  • 必须设置samesite='None' + secure=True(仅 HTTPS 生效)
  • 前端请求需添加 credentials: 'include'(浏览器端)
    fetch(url, { credentials: 'include' })
    

2. 预检请求(OPTIONS)处理

  • Flask/Django 的扩展会自动处理,原生 WSGI 需手动响应:
    @app.route('/api/data', method=['OPTIONS'])
    def handle_options():
        enable_cors()
        return ''
    

3. 生产环境安全建议

  • 避免使用 origins="*"
  • 限制允许的 HTTP 方法
  • 定期审查域名白名单

六、常见问题排查

 

问题1:CORS 配置不生效

  • 检查项
    • 中间件顺序(Django 中 CorsMiddleware 需在靠前位置)
    • 是否有多重 CORS 配置冲突
    • 浏览器缓存(尝试无痕模式)

问题2:Cookie 无法跨域传递

  • 检查项
    • 服务端是否设置 supports_credentials=True(Flask)或 CORS_ALLOW_CREDENTIALS=True(Django)
    • Cookie 的 SameSite 和 Secure 属性是否正确
    • 前端请求是否携带 credentials: 'include'

问题3:自定义头被拦截

  • 解决方案
    • 在 CORS_ALLOW_HEADERS(Django)或 allow_headers(Flask)中添加头名称
    • 确保前端请求头在 Access-Control-Allow-Headers 中声明

七、测试工具

使用 curl 或 Postman 验证响应头:

curl -I -X OPTIONS http://localhost:5000/api/data
# 检查返回的 Access-Control-* 头

 

使用 Ctrl+D 可将网站添加到书签
收藏网站
扫描二维码
关注早实习微信公众号
官方公众号
Top