Django应用中的Access-Control-Allow-Origin

78 投票
6 回答
147517 浏览
提问于 2025-04-17 21:57

我正在为我的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 个回答

1

在我的情况下,我上传了一个超过1MB的文件,结果出现了错误,这是因为nginx的设置问题(默认最大大小是1MB)。所以……

对我来说,nginx.conf的路径是/etc/nginx/nginx.conf

我只是在http block里添加了client_max_body_size,这样就解决了问题。

http {
    ...
    client_max_body_size 200M;
}    

记得在修改完这个设置后重启nginx。

8

你可以使用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_ORIGINSCORS_ALLOWED_ORIGIN_REGEXES来限制允许的来源列表。

之前这个设置叫做CORS_ORIGIN_ALLOW_ALL,现在仍然可以用作别名,但新名称优先。

14

你可以使用“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',
    ]

希望这能解决你的问题 :)

33

对于单个视图,你可以手动添加标题:

@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
114

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 然后在中间件或者视图中对请求进行过滤。

撰写回答