Django应用CORS头'Access-Control-Allow-Origin'缺失问题求助
解决跨域请求被拦截问题
问题描述
外部来源请求被阻止:同源策略禁止读取<EXTERNAL_LINK>上的远程资源。原因:CORS头'Access-Control-Allow-Origin'缺失。已禁止403
现有Django配置
INSTALLED_APPS = [ ... 'rest_framework', "corsheaders", ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'allauth.account.middleware.AccountMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.common.CommonMiddleware', ] CORS_ALLOWED_ORIGINS = [ 'http://myapp.site', # no SSL cert ] CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_METHODS = ( "DELETE", "GET", "OPTIONS", "PATCH", "POST", "PUT", "HEAD", )
浏览器请求信息
XHRHEAD <EXTERNAL_LINK> CORS Missing Allow Origin HEAD <EXTERNAL_LINK> Status 403 Version HTTP/2 Referrer policystrict-origin-when-cross-origin content-length 15 content-type application/octet-stream date Tue, 30 Apr 2024 16:46:05 GMT server nginx X-Firefox-Spdy h2 Accept */* Accept-Encoding gzip, deflate, br Connection keep-alive Host <DOMAIN_EXTERNAL_LINK> Origin http://myapp.site Referer http://myapp.site/ Sec-Fetch-Dest empty Sec-Fetch-Mode cors Sec-Fetch-Site cross-site User-Agent Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0
解决方案
核心问题说明
当前错误的根源并非Django配置,而是外部存储服务未配置允许http://myapp.site跨域访问。Django的corsheaders中间件仅负责处理前端到Django后端的跨域请求,而本次请求是前端直接向外部存储发起的,因此Django的CORS配置对该请求无效。
具体解决步骤
配置外部存储服务的CORS规则
- 进入外部存储服务的CORS设置面板(如AWS S3、阿里云OSS等均有专属CORS配置项)
- 添加允许源:
http://myapp.site - 允许方法:至少包含
HEAD和GET(匹配当前请求的HEAD方法) - 允许请求头:按需配置,可直接设置为
*允许所有头 - 示例CORS规则(JSON格式,不同服务格式可能略有差异):
[ { "AllowedOrigins": ["http://myapp.site"], "AllowedMethods": ["HEAD", "GET"], "AllowedHeaders": ["*"], "ExposeHeaders": [] } ]
临时代理方案(仅用于测试)
若暂时无法修改外部存储的CORS配置,可通过Django后端做代理中转:- 编写Django视图,接收前端请求后,由后端发起对外部存储的请求,再将结果返回给前端
- 示例视图代码:
import requests from django.http import HttpResponse def proxy_external_file(request, external_path): external_url = f"https://<EXTERNAL_LINK>/{external_path}" response = requests.head(external_url) # 若为GET请求,替换为requests.get并返回响应内容 return HttpResponse(status=response.status_code, headers=dict(response.headers)) - 注意:生产环境使用代理需考虑性能、缓存及安全问题,优先选择直接配置外部存储CORS。
清理Django中间件冗余配置
当前MIDDLEWARE中重复添加了django.middleware.common.CommonMiddleware,虽不影响跨域问题,但建议移除重复项,保证中间件顺序正确:MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'allauth.account.middleware.AccountMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', # 移除下方重复的CommonMiddleware # 'django.middleware.common.CommonMiddleware', ]
内容的提问来源于stack exchange,提问作者Max Isaev
相关产品推荐
相关产品推荐

