【发布时间】:2016-11-06 08:10:42
【问题描述】:
我正在使用 django 开发一些站点 aaa.com,它发送跨域 ajax“GET”请求以从 bbb.com 接收 json 数据,该 bbb.com 也在 django 上运行并使用 REST 框架。此时,添加crossDomain: true; withCredentials:true 一切正常。当然,它是在 aaa.com 的服务器端配置的。...-Allow-Credentials: true;
...-Allow-Origin: bbb.com
主要问题出现在 aaa.com 尝试发出 PUT POST DELETE ajax 请求时。
根据 CORS 文档:
[https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0],客户端ajax请求正确,...-Allow-Headers, ...-Allow-Methods
与...-Request-Headers, ...-Request-Methods
所以这个请求并不“简单”,首先浏览器从 aaa.com 向 bbb.com 发送预检请求,询问是否允许某些自定义标头和方法。
一切正常,但我仍然收到 403 错误。这是请求/响应:
General:
Request URL:http://bbb.com/api/someapipage/
Request Method:OPTIONS
Status Code:403 Forbidden
Remote Address:some ip:80
Response Headers:
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:accept, content-type, x-csrftoken, x-requested-with
Access-Control-Allow-Methods:GET, POST, OPTIONS, HEAD, PUT, DELETE
Access-Control-Allow-Origin:http://aaa.com
Allow:GET, POST, HEAD, OPTIONS
Connection:Keep-Alive
Content-Language:en
Content-Type:application/json
Date:Mon, 04 Jul 2016 14:20:38 GMT
Keep-Alive:timeout=5, max=100
Server:gunicorn/19.6.0
Transfer-Encoding:chunked
Vary:Accept,Accept-Language,Cookie
X-Frame-Options:SAMEORIGIN
Request Headers:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,ru;q=0.6
Access-Control-Request-Headers:accept, content-type, x-csrftoken
Access-Control-Request-Method:POST
Connection:keep-alive
Host:aaa.com
Origin:http://aaa.com
Referer:http://aaa.com/
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36
经过一周的尝试解决此问题后,我意识到服务器想要 Vary: Cookie on pre-flighted request 这是不可能的,因为跨域 pre-flight 请求的标头中不能包含 cookie。
我开始为这个问题寻找一些解决方案,并发现: https://code.djangoproject.com/ticket/13217
“启用 django.middleware.locale.LocaleMiddleware 会导致 django 在每个响应中添加一个 'Vary: Cookie' 标头。” 所以 localMiddleware 甚至在飞行前的 OPTIONS 响应中添加了 header Vary: Cookie
有很多建议可以使用djang-cors-header 来解决其中的一些问题。但是使用这个包功能等于我在服务器端的设置。
我还发现了漂亮的包:django-dont-vary-on,如果安装它可以设置装饰器关闭 Vary:cookie,但在我的情况下,我只需要在 OPTIONS 响应中关闭 Vary:cookie。
我对 django 有点陌生,实际上甚至无法想象在这种情况下该怎么做。我的每一步都像走在雷区。 有什么解决方案或替代方案吗?
【问题讨论】:
标签: ajax django cookies cors cross-domain