Django应用中的Access-Control-Allow-Origin
我正在为我的Django应用开发一个Phonegap应用,但在尝试进行Ajax调用时遇到了这个错误:
XMLHttpRequest cannot load http://domain.herokuapp.com/getcsrf/?tags=jquery%2Cjavascript&tagmode=any&format=json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
我该如何设置我的Django应用,让某些网址可以跨域访问呢?
这是我的Ajax代码:
get: function() {
$.getJSON("http://domain.herokuapp.com/getcsrf/",
{
tags: "jquery,javascript",
tagmode: "any",
format: "json"
},
function(data) {
$.each(data.items, function(item){
console.log(item);
});
});
}
6 个回答
在我的情况下,我上传了一个超过1MB的文件,结果出现了错误,这是因为nginx
的设置问题(默认最大大小是1MB)。所以……
对我来说,nginx.conf
的路径是/etc/nginx/nginx.conf
。
我只是在http block
里添加了client_max_body_size
,这样就解决了问题。
http {
...
client_max_body_size 200M;
}
记得在修改完这个设置后重启nginx。
你可以使用django-cors-headers,就像其他人建议的那样。现在你需要按照下面的步骤操作。
要在你的项目中使用django-cors-headers,请参考这个项目的说明文档中的安装和配置部分,或者你也可以看下面的内容(我从说明文档中复制过来,方便你阅读)。
安装
通过pip安装:
python -m pip install django-cors-headers
然后把它添加到你的已安装应用中:
INSTALLED_APPS = [
...
'corsheaders',
...
]
确保你在最后加上逗号,否则可能会出现ModuleNotFoundError(可以参考这篇博客)。
你还需要添加一个中间件类来监听响应:
MIDDLEWARE = [
...,
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...,
]
CorsMiddleware
应该尽量放在最上面,特别是在任何可能生成响应的中间件之前,比如Django的CommonMiddleware
或Whitenoise的WhiteNoiseMiddleware
。如果不放在前面,它就无法为这些响应添加CORS头。
如果你使用CORS_REPLACE_HTTPS_REFERER
,它也应该放在Django的CsrfViewMiddleware
之前。
配置
在你的Django设置中配置中间件的行为。你必须设置以下三个选项中的至少一个:
`CORS_ALLOWED_ORIGINS`
`CORS_ALLOWED_ORIGIN_REGEXES`
`CORS_ALLOW_ALL_ORIGINS`
CORS_ALLOWED_ORIGINS
一个被授权进行跨站HTTP请求的来源列表。默认值是[]
。
来源是由CORS规范第3.2节定义的,包括URI方案 + 主机名 + 端口,或者特殊值'null'或'file://'。默认端口(HTTPS = 443,HTTP = 80)在这里是可选的。
特殊值null是在“隐私敏感的上下文”中由浏览器发送的,比如当客户端从file://域运行时。特殊值file://是某些版本的Chrome在Android上意外发送的,具体可以参考这个bug。
示例:
CORS_ALLOWED_ORIGINS = [
"https://example.com",
"https://sub.example.com",
"http://localhost:8080",
"http://127.0.0.1:9000"
]
之前这个设置叫做CORS_ORIGIN_WHITELIST
,现在仍然可以用作别名,但新名称优先。
CORS_ALLOWED_ORIGIN_REGEXES
一个字符串列表,表示被授权进行跨站HTTP请求的来源的正则表达式。默认值是[]
。当CORS_ALLOWED_ORIGINS
不方便使用时,比如你有很多子域名时,这个选项很有用。
示例:
CORS_ALLOWED_ORIGIN_REGEXES = [
r"^https://\w+\.example\.com$",
]
之前这个设置叫做CORS_ORIGIN_REGEX_WHITELIST
,现在仍然可以用作别名,但新名称优先。
CORS_ALLOW_ALL_ORIGINS
如果设置为True
,所有来源都将被允许。其他限制允许来源的设置将被忽略。默认值是False
。
把这个设置为True
可能会很危险,因为它允许任何网站向你的站点发起跨域请求。一般来说,你会想通过CORS_ALLOWED_ORIGINS
或CORS_ALLOWED_ORIGIN_REGEXES
来限制允许的来源列表。
之前这个设置叫做CORS_ORIGIN_ALLOW_ALL
,现在仍然可以用作别名,但新名称优先。
你可以使用“django-cors-headers”这个工具。只需要通过pip安装它:
pip install django-cors-headers
然后把'corsheaders'加到你的已安装应用里:
INSTALLED_APPS = [
...
'corsheaders',
...
]
接着添加中间件:
MIDDLEWARE = [
...,
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...,
]
然后在你的“settings.py”文件里加上这些内容:
CORS_ALLOWED_ORIGINS = [
'http://siteyouwantto.allow.com',
'http://anothersite.allow.com',
]
如果你还想允许某些域名发送“POST”请求,记得在“settings.py”里加上这些内容,并且不要忘了在“CORS_ALLOWED_ORIGINS”里添加它们。
CSRF_TRUSTED_ORIGINS = [
'http://siteyouwantto.allow.com',
]
希望这能解决你的问题 :)
对于单个视图,你可以手动添加标题:
@require_GET
def api_getto(request):
response = JsonResponse(
# your stuff here
)
response["Access-Control-Allow-Origin"] = "*"
response["Access-Control-Allow-Methods"] = "GET, OPTIONS"
response["Access-Control-Max-Age"] = "1000"
response["Access-Control-Allow-Headers"] = "X-Requested-With, Content-Type"
return response
Django 默认情况下不提供跨域请求所需的头信息。最简单的方法就是使用这个 Django 应用,它可以为你处理这些问题:https://github.com/adamchainz/django-cors-headers
- 把它添加到已安装的应用中
- 把它添加到中间件中
- 然后就可以做一些其他的设置...
CORS_ALLOWED_ORIGINS = [
"http://read.only.com",
"http://change.allowed.com",
]
如果你想允许所有的请求,只需要使用这个设置...
CORS_ALLOW_ALL_ORIGINS = True
然后在中间件或者视图中对请求进行过滤。