Django+Angular CORS 不适用于 POST
Django+Angular CORS not working with POST
我的 Angular4 应用程序(运行 在 http://127.0.0.1:4200
开发服务器上)应该访问网络上的 django REST 后端。后端在我的控制之下,只能通过 HTTPS(运行 Apache 将请求传送到内部端口上的 gunicorn 服务器 运行)。假设这是 https://example.com/
。由于历史原因,用户登录是使用会话完成的,因为我希望用户登录后也能使用Django的管理界面。工作流程如下:
- 用户打开
http://127.0.0.1:4200
,我向 https://example.com/REST/is_logged_in
执行 GET 请求,当用户尚未通过会话登录时 returns 返回 403,否则返回 200。在前一种情况下,用户被重定向到 https://example.com/login/
,由 Django 的模板引擎渲染,允许用户登录。登录后,用户被重定向到 http://127.0.0.1:4200
- 单击我的 Angular UI 中的某个按钮时,会执行 POST 请求。此 post 请求失败并显示 403,即使预检 OPTIONS 请求明确列出 POST 作为允许的操作。
这是我在 Django 中的 CORS 配置:
NG_APP_ABSOLUTE_URL = 'http://127.0.0.1:4200'
# adapt Django's to Angular's presumed XSRF cookie/header names
CSRF_COOKIE_NAME = "XSRF-TOKEN"
CSRF_HEADER_NAME = "HTTP_X_XSRF_TOKEN"
CORS_ORIGIN_WHITELIST = (
urlparse(NG_APP_ABSOLUTE_URL).netloc
)
CSRF_TRUSTED_ORIGINS = (
urlparse(NG_APP_ABSOLUTE_URL).netloc
)
CORS_ALLOW_HEADERS = default_headers + (
'x-xsrf-token',
)
CORS_ALLOW_CREDENTIALS = True
这是 Chrome 报告的第一个 REST GET 请求(成功,200)以检查用户是否登录(在他成功登录后)在响应中:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://127.0.0.1:4200
Allow:GET, HEAD, OPTIONS
Connection:close
Content-Type:application/json
Date:Wed, 26 Apr 2017 15:09:26 GMT
Server:gunicorn/19.6.0
Set-Cookie:XSRF-TOKEN=...; expires=Wed, 25-Apr-2018 15:09:26 GMT; Max-Age=31449600; Path=/
Transfer-Encoding:chunked
Vary:Accept,Cookie,Origin
X-Frame-Options:SAMEORIGIN
对应的请求是这样的:
Cookie:sessionid=...; XSRF-TOKEN=...
Host:example.com
Origin:http://127.0.0.1:4200
Referer:http://127.0.0.1:4200/
现在,针对实际问题:
预检请求:
Request URL:https://example.com/REST/change_user_data/
Request Method:OPTIONS
Status Code:200 OK
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:example.com
Origin:http://127.0.0.1:4200
Referer:http://127.0.0.1:4200/dashboard/account
预检响应:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with, x-xsrf-token
Access-Control-Allow-Methods:DELETE, GET, OPTIONS, PATCH, POST, PUT
Access-Control-Allow-Origin:http://127.0.0.1:4200
Access-Control-Max-Age:86400
Connection:close
Content-Length:0
Content-Type:text/html; charset=utf-8
Date:Wed, 26 Apr 2017 15:36:56 GMT
Server:gunicorn/19.6.0
Vary:Origin
X-Frame-Options:SAMEORIGIN
现在我失败了 (403) POST 请求:
Accept:application/json
Accept-Encoding:gzip, deflate, br
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:60
Content-Type:application/json
Cookie:sessionid=...; XSRF-TOKEN=...
Host:example.com
Origin:http://127.0.0.1:4200
Referer:http://127.0.0.1:4200/dashboard/account
响应headers:
HTTP/1.1 403 Forbidden
Date: Wed, 26 Apr 2017 15:36:56 GMT
Server: gunicorn/19.6.0
Vary: Accept,Cookie,Origin
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
Access-Control-Allow-Credentials: true
Allow: POST, OPTIONS
Access-Control-Allow-Origin: http://127.0.0.1:4200
Set-Cookie: XSRF-TOKEN=...; expires=Wed, 25-Apr-2018 15:36:56 GMT; Max-Age=31449600; Path=/
Connection: close
Transfer-Encoding: chunked
为什么这个请求不起作用?这对我来说意义不大!
此致!
我遇到了同样的问题,试图从我的 Angular CLI(端口 4200)向 Django(端口 8000)发送 POST 请求。我认为这是 Django 的问题所以我安装了 cors 包但是 "problem" 与浏览器有关(实际上不是问题,这是一个安全问题,请参阅 here)。无论如何,我解决了为我的 Angular CLI 添加代理规则的问题,如下所示:
- 首先,不是将我的请求发送到 http://localhost:8000/api/...而是将它们发送到 /api/(即到我的 ng 服务器 运行ning 在端口 4200)。
- 然后我在我的 Angular 项目中添加了一个名为 "proxy.conf.json" 的文件,内容如下:
{
"/api": {
"target": "http://localhost:8000",
"secure": false
}
}
- 最后,运行 你的带有标志“--proxy-config”的 ng 服务器:
ng serve --watch --proxy-config proxy.conf.json
所有 API 请求将被发送到端口 4200,并且 Angular 将在内部将它们重定向到 Django,从而避免 CORS 问题。
请注意,这仅对开发有效,不会在您构建应用程序代码并将其添加为 Django 服务器的静态代码时使用。
最后,有了这个解决方案,我不再需要 cors 的 python 模块,所以您可以删除它。
我的 Angular4 应用程序(运行 在 http://127.0.0.1:4200
开发服务器上)应该访问网络上的 django REST 后端。后端在我的控制之下,只能通过 HTTPS(运行 Apache 将请求传送到内部端口上的 gunicorn 服务器 运行)。假设这是 https://example.com/
。由于历史原因,用户登录是使用会话完成的,因为我希望用户登录后也能使用Django的管理界面。工作流程如下:
- 用户打开
http://127.0.0.1:4200
,我向https://example.com/REST/is_logged_in
执行 GET 请求,当用户尚未通过会话登录时 returns 返回 403,否则返回 200。在前一种情况下,用户被重定向到https://example.com/login/
,由 Django 的模板引擎渲染,允许用户登录。登录后,用户被重定向到http://127.0.0.1:4200
- 单击我的 Angular UI 中的某个按钮时,会执行 POST 请求。此 post 请求失败并显示 403,即使预检 OPTIONS 请求明确列出 POST 作为允许的操作。
这是我在 Django 中的 CORS 配置:
NG_APP_ABSOLUTE_URL = 'http://127.0.0.1:4200'
# adapt Django's to Angular's presumed XSRF cookie/header names
CSRF_COOKIE_NAME = "XSRF-TOKEN"
CSRF_HEADER_NAME = "HTTP_X_XSRF_TOKEN"
CORS_ORIGIN_WHITELIST = (
urlparse(NG_APP_ABSOLUTE_URL).netloc
)
CSRF_TRUSTED_ORIGINS = (
urlparse(NG_APP_ABSOLUTE_URL).netloc
)
CORS_ALLOW_HEADERS = default_headers + (
'x-xsrf-token',
)
CORS_ALLOW_CREDENTIALS = True
这是 Chrome 报告的第一个 REST GET 请求(成功,200)以检查用户是否登录(在他成功登录后)在响应中:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://127.0.0.1:4200
Allow:GET, HEAD, OPTIONS
Connection:close
Content-Type:application/json
Date:Wed, 26 Apr 2017 15:09:26 GMT
Server:gunicorn/19.6.0
Set-Cookie:XSRF-TOKEN=...; expires=Wed, 25-Apr-2018 15:09:26 GMT; Max-Age=31449600; Path=/
Transfer-Encoding:chunked
Vary:Accept,Cookie,Origin
X-Frame-Options:SAMEORIGIN
对应的请求是这样的:
Cookie:sessionid=...; XSRF-TOKEN=...
Host:example.com
Origin:http://127.0.0.1:4200
Referer:http://127.0.0.1:4200/
现在,针对实际问题:
预检请求:
Request URL:https://example.com/REST/change_user_data/
Request Method:OPTIONS
Status Code:200 OK
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:example.com
Origin:http://127.0.0.1:4200
Referer:http://127.0.0.1:4200/dashboard/account
预检响应:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:accept, accept-encoding, authorization, content-type, dnt, origin, user-agent, x-csrftoken, x-requested-with, x-xsrf-token
Access-Control-Allow-Methods:DELETE, GET, OPTIONS, PATCH, POST, PUT
Access-Control-Allow-Origin:http://127.0.0.1:4200
Access-Control-Max-Age:86400
Connection:close
Content-Length:0
Content-Type:text/html; charset=utf-8
Date:Wed, 26 Apr 2017 15:36:56 GMT
Server:gunicorn/19.6.0
Vary:Origin
X-Frame-Options:SAMEORIGIN
现在我失败了 (403) POST 请求:
Accept:application/json
Accept-Encoding:gzip, deflate, br
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:60
Content-Type:application/json
Cookie:sessionid=...; XSRF-TOKEN=...
Host:example.com
Origin:http://127.0.0.1:4200
Referer:http://127.0.0.1:4200/dashboard/account
响应headers:
HTTP/1.1 403 Forbidden
Date: Wed, 26 Apr 2017 15:36:56 GMT
Server: gunicorn/19.6.0
Vary: Accept,Cookie,Origin
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
Access-Control-Allow-Credentials: true
Allow: POST, OPTIONS
Access-Control-Allow-Origin: http://127.0.0.1:4200
Set-Cookie: XSRF-TOKEN=...; expires=Wed, 25-Apr-2018 15:36:56 GMT; Max-Age=31449600; Path=/
Connection: close
Transfer-Encoding: chunked
为什么这个请求不起作用?这对我来说意义不大!
此致!
我遇到了同样的问题,试图从我的 Angular CLI(端口 4200)向 Django(端口 8000)发送 POST 请求。我认为这是 Django 的问题所以我安装了 cors 包但是 "problem" 与浏览器有关(实际上不是问题,这是一个安全问题,请参阅 here)。无论如何,我解决了为我的 Angular CLI 添加代理规则的问题,如下所示:
- 首先,不是将我的请求发送到 http://localhost:8000/api/...而是将它们发送到 /api/(即到我的 ng 服务器 运行ning 在端口 4200)。
- 然后我在我的 Angular 项目中添加了一个名为 "proxy.conf.json" 的文件,内容如下:
{
"/api": {
"target": "http://localhost:8000",
"secure": false
}
}
- 最后,运行 你的带有标志“--proxy-config”的 ng 服务器:
ng serve --watch --proxy-config proxy.conf.json
所有 API 请求将被发送到端口 4200,并且 Angular 将在内部将它们重定向到 Django,从而避免 CORS 问题。 请注意,这仅对开发有效,不会在您构建应用程序代码并将其添加为 Django 服务器的静态代码时使用。
最后,有了这个解决方案,我不再需要 cors 的 python 模块,所以您可以删除它。