Django本地主机CORS无法工作

22

我有一个本地的Django设置,如下所示

Django Rest Framework:localhost:8000

AngularJS前端:在http://localservername上运行的本地Apache

我已经安装了django-cors-headers,在我的settings.py中,我已经进行了设置。

CORS_ORIGIN_WHITELIST = (
    'http://localhost',
    'localservername',
    'http://localservername',
    '127.0.0.1'
)


MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

然而,每当我访问任何由Rest Framework提供的API时,我会遇到一个No 'Access-Control-Allow-Origin' header is present on the requested resource.错误。如果我设置CORS_ORIGIN_ALLOW_ALL = True,则API将正常工作,但这对我的服务器端数据来说是极其不安全的。

我需要做出哪些更改来修复这个问题?


2
你是否在INSTALLED_APPS中的corsheaders之前正确添加了corsheaders.middleware.CorsMiddlewaredjango.middleware.common.CommonMiddleware - Daniil Ryzhkov
1
@DaniilRyzhkov,是的,我有,我会把它添加到我的问题中。 - Newtt
@HamletHakobyan,这并不重要,因为我的请求是从localservernamelocalhost:8000 - Newtt
尝试删除 'http://localservername','http://localhost', 行。 - Daniil Ryzhkov
14个回答

24

在这个错误中,提示明确说明需要使用https://

HINT: Add a scheme (e.g. https://) or netloc (e.g. example.com).

此外,在 Django 设置中,括号的使用也很重要。

CORS_ORIGIN_WHITELIST = [
    'https://localhost:3000'
]

上述设置可以正常工作。

而使用不同括号的相同设置将无法正常工作。

CORS_ORIGIN_WHITELIST = (
    'https://localhost:3000'
)

Django 4.x文档使用CORS_ALLOWED_ORIGINS而不是CORS_ORIGIN_WHITELIST,这是一种不同的表达方式吗? - Marc Maxmeister
这不是因为"不同的括号",而是因为('abcdef') == 'abcdef'。如果你想要一个只有一个值的元组,需要加上逗号:('abcdef',) - MrKsn

9
对于我来说,我使用[]而不是()。另外,在URL末尾不要添加'/'。
类似这样:
CORS_ORIGIN_WHITELIST = [
    'http://localhost:3000'
]

4

我有同样的问题。通过浏览 django-cors-headers 代码发现我的错误是以下内容:

一个完整的CORS标头看起来像这样(注意模式和主机名):

Access-Control-Allow-Origin: https://example.com
CORS_ORIGIN_WHITELIST设置需要按照与urlparse.netloc (文档)相同的格式进行比较,而这个格式只包含Origin标头的主机名(可能包括端口)。
def origin_found_in_white_lists(self, origin, url):
    return (
        url.netloc in conf.CORS_ORIGIN_WHITELIST or
        (origin == 'null' and origin in conf.CORS_ORIGIN_WHITELIST) or
        self.regex_domain_match(origin)
    )

在IT技术中,需要使用正则表达式白名单对数据进行筛选,将其与完整的Origin头部信息进行比较。

因此,正确的设置应该是(正如设置手册中的示例所正确说明的那样,但没有适当描述):

CORS_ORIGIN_WHITELIST = (
    'example.com',
)

如果您不希望API与非安全的网站http版本通信,这可能是一个问题。在这种情况下,请使用正则表达式。

另外请注意:在故障排除期间,我发现如果没有找到匹配项,则CORS标头完全不存在。这意味着标头的缺失并不一定表示中间件完全故障,而可能只是配置错误。


3
根据http://www.w3.org/Security/wiki/Same_Origin_Policy,请求应该来自相同的端口、协议和主机才能被视为同一来源。在这里,你的一个服务器在80端口,另一个服务器在8080端口。

一个源是由URL的协议、主机和端口定义的。通常情况下,从不同源检索的文档彼此隔离。例如,如果从http://example.com/doc.html检索的文档试图访问从https://example.com/target.html检索的文档的DOM,用户代理将禁止访问,因为第一个文档的源(http,example.com,80)与第二个文档的源(https,example.com,443)不匹配。


2
这对我有用,请尝试使用此方法,它可能有助于解决您的问题。
CORS_ORIGIN_WHITELIST = (
    'http://localhost',
)

1

1

对我来说大括号很重要,使用[]代替(),我已经在Django中验证过了,其他的我还没有检查。

像这样写:

CORS_ORIGIN_WHITELIST=[ 'https://localhost:3000' ]


1

1
django-cors-headers documentation 中复制白名单代码,然后进行修改即可:
CORS_ORIGIN_WHITELIST = [
    "https://example.com",
    "https://sub.example.com",
    "http://localhost:8080",
    "http://127.0.0.1:9000"
]

这将确保您没有犯任何拼写错误。

1
请勿添加路径/,如下所示:


CORS_ORIGIN_WHITELIST = (
    'https://localhost:3000/'
)

只需添加以下代码即可。
CORS_ORIGIN_WHITELIST = [
    'https://localhost:3000'
]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接