Django CORS Access-Control-Allow-Origin 丢失

Posted

技术标签:

【中文标题】Django CORS Access-Control-Allow-Origin 丢失【英文标题】:Django CORS Access-Control-Allow-Origin missing 【发布时间】:2018-03-05 09:03:22 【问题描述】:

我正在尝试在我的 django 应用中实现 google oauth2 身份验证。我已按照docs 执行了所有步骤。

在浏览器地址栏上,如果我浏览这个https://foo.bar.net/api/v1/auth/login/google-oauth2/ 这个url,它会通过google 正确验证,它会返回一个google-auth-token 到提到的redirect-url,它会获取auth-token 并将其转换为一个普通的令牌,然后以 json 格式发送给用户或前端。

但是如果我尝试从我的 js 代码中向上述 url 发出 GET 请求,它会显示

Reason: CORS header 'Access-Control-Allow-Origin' missing

前端的完整回溯看起来像,

GET https://foo.bar.net/api/v1/auth/login/google-oauth2/ 302 Found 718ms    
polyfil...ndle.js (line 7507)
GET https://accounts.google.com/o/oauth2/auth?client_...DW&response_type=code&scope=openid+email+profile 200 OK
Login Failed Response  _body=Event error,  status=0,  ok=false,  more...
main.bundle.js (line 367)
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://accounts.google.com/o/oauth2/auth?client_id=kguygvh868697-khgkhvkgvkgkgv.apps.googleusercontent.com&redirect_uri=https://foo.bar.net/api/v1/auth/complete/google-oauth2/&state=Cbms1QhSQVzjO3xkjhkyuu&response_type=code&scope=openid+email+profile. (Reason: CORS header 'Access-Control-Allow-Origin' missing).

我搜索了谷歌,提示我安装djang-CORS-headers。我已经安装并配置了上面的包。但是出现了同样的错误。

我的settings.py 的一部分看起来像,

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',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'oauth2_provider.middleware.OAuth2TokenMiddleware',
]

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'oauth2_provider',
    'corsheaders',
    'rest_framework_swagger',
]

CORS_ORIGIN_ALLOW_ALL = True

实际上,我们为前端(ang)和后端(django)有两个独立的项目。我同意ajax问题。这样我就可以在单独的窗口中打开 google oauth url。

在后端,我已经完成了获取服务器访问令牌并将其与我们应用程序的访问令牌交换。目前我正在以 json 格式返回令牌详细信息。所以这个 json 会显示在新打开的窗口中。但是不知道怎么弄

    从窗口中获取令牌并将其存储到浏览器上的临时存储中。

    出现详细信息后关闭新窗口。

    通过在请求标头中传递令牌信息重定向到用户/个人资料页面。

不知道这个 oauth 流程是否正确。而且我不希望完整的 oauth 流程出现在 js 部分(oauth 隐式流程)。请指导我正确的方向。

【问题讨论】:

你不能在 ajax 中重定向到谷歌。 @charlietfl 是的,实际上我正在通过 Angular 进行 GET 请求 “跨域请求被阻止:同源策略不允许读取accounts.google.com/o/oauth2/auth 的远程资源?...(原因:CORS 标头“Access-Control-Allow-Origin”缺失)” 表示问题不是因为您自己的服务器上缺乏 CORS 支持,而是因为 Google 端点故意不支持从浏览器中运行的前端 javascript 代码接收请求(通过 XHR 或 Fetch API) .缺少 Access-Control-Allow-Origin 响应标头的事实并非疏忽;缺少它意味着“不允许跨域请求” oauth 返回令牌时需要在新窗口中打开并在返回 url 中使用一些 javascript 与打开的窗口进行通信 hello.js库为例 【参考方案1】:

问题是在前端不应该使用授权码流,这里需要使用隐式流 (https://developers.google.com/actions/identity/oauth2-implicit-flow) 而不是授权码流(https://developers.google.com/actions/identity/oauth2-code-flow)

我想你也没有提到允许的标题

  CORS_ALLOW_HEADERS = (
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
)

【讨论】:

我可以知道我在哪里使用了前端的授权代码流吗? 你不应该在前端使用代码获取访问令牌。

以上是关于Django CORS Access-Control-Allow-Origin 丢失的主要内容,如果未能解决你的问题,请参考以下文章

Zscaler 的 Ajax 问题

django-cors-headers 和 nginx 配置:预检响应缺少 CORS 标头

Django-cors-headers解决跨域问题

django-cors-headers

django---django-cors-headers跨域源码分析

来自 AngularJS 的 Django CORS API