我正在使用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
crossDomain: true; withCredentials:true
...-Allow-Credentials: true; ...-Allow-Origin: bbb.com
当aaa.com尝试发出PUT POST DELETEajax请求时,就会出现主要问题。根据CORS文档: [https://www.w3.org/TR/cors/#cross-origin-request-with- preflight-0],客户端ajax请求是正确的,并且 ...-Allow-Headers, ...-Allow-Methods 与 ...-Request-Headers, ...-Request-Methods
PUT POST DELETE
...-Allow-Headers, ...-Allow-Methods
...-Request-Headers, ...-Request-Methods
因此,此请求并非“简单”,因此所有浏览器首先将aa.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
经过一周的尝试来解决此问题,我意识到服务器希望更改:预检请求上的Cookie,这是不可能的,因为跨域预检请求的标头中不能包含Cookie。
我开始找到解决此问题的方法,并发现:https : //code.djangoproject.com/ticket/13217
“启用django.middleware.locale.LocaleMiddleware会导致django在每个响应中添加一个’Vary:Cookie’标头。” 因此,即使在飞行前OPTIONS响应中,localMiddleware也会添加标头Vary:Cookie
有很多建议可用来djang-cors-header解决某些问题。但是使用此软件包功能与我在服务器端的设置相同。
djang-cors-header
我还找到了漂亮的软件包:django-dont-vary- on如果安装了该软件包,则可以设置装饰器以关闭Vary:cookie,但就我而言,我仅需要在OPTIONS响应中关闭Vary:cookie。
django-dont-vary- on
我对django有点陌生,实际上甚至无法想象在这种情况下该怎么办。我的每一步都像在雷场上行走。有什么解决方案或其他选择吗?
您必须将客户列入CORS白名单才能访问服务器。
如果它们是跨域请求,则如果您使用GET,HEAD或POST以外的方法,则该请求将被预检。
另外,如果使用POST发送内容类型为application / x-www-form-urlencoded,multipart / form- data或text / plain以外的Content-Type的请求数据,它将变为预检状态。
它是允许处理或拒绝跨域客户端请求的服务器(默认)。
因此,如果您有权访问服务器端应用程序,则可以执行以下操作以获取响应。
在服务器端
在您的服务器端安装django-cors-header并白名单您的客户端域或IP(也是端口特定的)
pip install django-cors-headers
在settings.py中,将其添加到您的INSTALLED_APPS中
INSTALLED_APPS = ( ... 'corsheaders', ... )
在MIDDLEWARE_CLASSES中添加corsheaders.middleware.CorsMiddleware
MIDDLEWARE_CLASSES = ( 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', '**corsheaders.middleware.CorsMiddleware**', 'django.middleware.common.CommonMiddleware', .... )
并定义一个CORS白名单
CORS_ORIGIN_WHITELIST = ( 'aaa.com', )
现在,当您将客户添加到CORS白名单中时,您现在可以发出成功的Ajax请求。