问题
I'm developing some site aaa.com with django, which sends cross-domain ajax "GET" requests to receive json data from bbb.com which is also running on django and is using REST framework. At this point everything works pretty fine with adding crossDomain: true; withCredentials:true
. And of course its configurated on server-side of aaa.com....-Allow-Credentials: true;
...-Allow-Origin: bbb.com
The main issue comes when aaa.com is trying to make PUT POST DELETE
ajax requests.
According to CORS documentation:
[https://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0], client side ajax request is correct, and...-Allow-Headers, ...-Allow-Methods
is matched with...-Request-Headers, ...-Request-Methods
so this request is not 'simple' and first of all browser sends preflight request from aaa.com to bbb.com to ask if some custom headers and methods are allowed.
Everything is OK But I'm still getting 403 Error. Here is the request/response:
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
After week of tries to fix this issue I realised that server wants to Vary: Cookie on pre-flighted request which is impossible because cross-domain pre-flight request cannot contain cookie in its header.
I started finding some solution to this issue and found: https://code.djangoproject.com/ticket/13217
"Enabling django.middleware.locale.LocaleMiddleware causes that django adds a 'Vary: Cookie' header to every reponse." So localMiddleware adds header Vary: Cookie even in pre-flight OPTIONS response
There are lots of reccomendations to use djang-cors-header
to fix some of this problems. But using this package function are equal to my settings on server-side.
I have also found pretty package: django-dont-vary-on
which if installed can set decorators to turn off Vary:cookie, but in my case i need to turn off Vary:cookie only in OPTIONS response.
Im bit new to django and actually cannot even imagine what to do in this situation. Every my step is just like walking on a mine field. Is there any solution or some alternatives?
回答1:
You have to CORS whitelist your client to access the server.
In case their is a Cross-domain request, the request becomes preflighted if you use methods other than GET, HEAD or POST.
Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, it becomes preflighted.
Its the server that allows the cross-domain client request to be processed or deny it (default).
So if you have access to the server-side application, you could do the following to get the response.
On server-side
Install django-cors-headers on your server side and white list your client domain or IP (it is also port specific)
pip install django-cors-headers
In settings.py, add it in your INSTALLED_APPS
INSTALLED_APPS = (
...
'corsheaders',
...
)
Add the corsheaders.middleware.CorsMiddleware in MIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES = (
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'**corsheaders.middleware.CorsMiddleware**',
'django.middleware.common.CommonMiddleware',
....
)
and define a CORS whitelist
CORS_ORIGIN_WHITELIST = (
'aaa.com',
)
Now as you have added your client in the CORS whitelist, you will now be able to make a successful ajax request.
来源:https://stackoverflow.com/questions/38187340/cross-domain-ajax-options-error-403-django