别人的代码:
antd 的reactjs的web页面,去登录,出错:
<code>Failed to load http://localhost:65000/api/v1/jwt-token-auth/: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:8000' is therefore not allowed access. index.js:2177 uncaught at _callee3 at _callee3 at _callee6 at takeEvery(login/login, _callee) at _callee at _callee Error: TypeError: Cannot set property 'status' of undefined at login$ (http://localhost:8000/index.js:16499:31) at tryCatch (http://localhost:8000/index.js:33388:40) at Generator.invoke [as _invoke] (http://localhost:8000/index.js:33622:22) at Generator.prototype.(anonymous function) [as next] (http://localhost:8000/index.js:33440:21) at next (http://localhost:8000/index.js:70781:27) at currCb (http://localhost:8000/index.js:70858:7) at http://localhost:8000/index.js:70108:17 at http://localhost:8000/index.js:71719:26 at onError (http://localhost:8000/index.js:70109:11) at sagaWithCatch$ (http://localhost:8000/index.js:72119:13) at tryCatch (http://localhost:8000/index.js:33388:40) at Generator.invoke [as _invoke] (http://localhost:8000/index.js:33622:22) at Generator.prototype.(anonymous function) [as throw] (http://localhost:8000/index.js:33440:21) at next (http://localhost:8000/index.js:70759:32) at Object.currCb [as cont] (http://localhost:8000/index.js:70858:7) at end (http://localhost:8000/index.js:70826:23) at abort (http://localhost:8000/index.js:70549:5) at Object.task.cont (http://localhost:8000/index.js:70562:9) at next (http://localhost:8000/index.js:70798:16) at currCb (http://localhost:8000/index.js:70858:7) __stack_frame_overlay_proxy_console__ @ index.js:2177 log @ utils.js:240 logError @ proc.js:221 。。。 batchedUpdates @ react-dom.development.js:2131 dispatchEvent @ react-dom.development.js:4555 interactiveUpdates$1 @ react-dom.development.js:16714 interactiveUpdates @ react-dom.development.js:2150 dispatchInteractiveEvent @ react-dom.development.js:4532 request.js:72 Fetch finished loading: OPTIONS "http://localhost:65000/api/v1/jwt-token-auth/". </code>
对于此问题:
之前实际上是访问的在线的:
47.x.x.x的接口
也是同样问题:
别人告诉我说,自己肯定是已经实现了CORS
-》其都是连接的本地的Server去调试的,就没有这个问题
-〉而上面看到的,是已经花了九牛二虎之力,终于跑起来其写的本地的Django的代码了,但是错误依旧。
去搜了下的代码
Object.task.cont
currCb
代码里都搜不到
-》好像这个错误不是自己的代码
像是Reactjs或Antd中的。
不过,还是先要去解决第一个错误:
<code>Failed to load http://localhost:65000/api/v1/jwt-token-auth/: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:8000' is therefore not allowed access. </code>
看起来是:
Django的jwt-token-auth导致的
换了safari,错误信息是类似的
然后别人那里是没有问题的,其log是:
Fetch finished loading: OPTIONS “http://localhost:65000/api/v1/jwt-token-auth/“.
而此处是在这条log之前,出现的错误。
Failed to load jwt-token-auth
Failed to load jwt-token-auth Access-Control-Allow-Origin
django Failed to load jwt-token-auth Access-Control-Allow-Origin
django Failed to load jwt-token-auth
去试试这个
<code>➜ xxx git:(master) ✗ pip3 install django-cors-headers Requirement already satisfied: django-cors-headers in /usr/local/lib/python3.6/site-packages (2.2.0) </code>
发现已经安装和设置参数了。
然后再去加上:
<code>CORS_ORIGIN_ALLOW_ALL = True </code>
看看结果
问题依旧。
加了:
<code> CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_WHITELIST = ('*', 'localhost:8001', 'localhost:8000', 'localhost:65000') CORS_ALLOW_METHODS = ( 'DELETE', 'GET', 'OPTIONS', 'PATCH', 'POST', 'PUT', ) CORS_ALLOW_HEADERS = ( 'accept', 'accept-encoding', 'authorization', 'content-type', 'dnt', 'origin', 'user-agent', 'x-csrftoken', 'x-requested-with', ) CORS_ALLOW_CREDENTIALS = True </code>
问题依旧。
python – Django Rest Framework JWT – Stack Overflow
django restframework token Authentication fail with “invalid token” – Stack Overflow
Ionic2 JWT authentication failed with Django rest framework backend – Stack Overflow
python – Django Rest Framework – Authentication credentials were not provided – Stack Overflow
python – How to test authentication using REST Framework JWT? – Stack Overflow
感觉是:
此处的django-cors-headers就没起效果,导致CORS失败
django-cors-headers not working
python – django-cors-headers not work – Stack Overflow
<code>CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_CREDENTIALS = False </code>
结果:
再去看看:
<code>Failed to load http://localhost:65000/api/v1/jwt-token-auth/: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:8000' is therefore not allowed access. </code>
试试:
去掉CORS_ORIGIN_WHITELIST中的*
<code>CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_WHITELIST = ('localhost:8001', 'localhost:8000', 'localhost:65000') CORS_ALLOW_CREDENTIALS = False </code>
结果:问题依旧。
试试:
<code>CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_WHITELIST = ('localhost:8001', 'localhost:8000', 'localhost:65000') CORS_ALLOW_CREDENTIALS = True </code>
结果:问题依旧。
有:
access-control-allow-origin:*
返回。
python – django-cors-headers not working at all – Stack Overflow
Django 1.9 + django-cors-headers + AJAX not working – Stack Overflow
说:Django-cors-headers 已经失效
建议换:Django-cors-middleware
jquery – Django-cors-headers not working – Stack Overflow
Enable Django CORS (Cross Origin Resource Sharing) Headers configuration · crs4/ome_seadragon Wiki
确保CommonMiddleware在最后:
<code>MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'corsheaders.middleware.CorsMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.common.CommonMiddleware', ] </code>
也不行。
再换个位置:
<code>'django.middleware.csrf.CsrfViewMiddleware', 'corsheaders.middleware.CorsMiddleware', </code>
结果:问题依旧。
CorsMiddleware is not working in Django 1.10 · Issue #102 · ottoyiu/django-cors-headers
搞不定。
再去找找另外的问题
index.js uncaught at _callee3 at _callee3
Error: TypeError: Cannot set property ‘status’ of undefined
参数不对出现uncaught at _callee3问题再次进行操作无法进行 · Issue #1446 · dvajs/dva
request.js中fetch执行后浏览器console抛出异常 · Issue #1068 · dvajs/dva
通过调试代码:
xx/src/index.js
<code>import './index.less'; // 1. Initialize const app = dva({ history: createHistory(), onError: (err, dispatch) => { console.log("err=", err) console.log("err.response=", err.response) console.log("dispatch=", dispatch) // if (err.response) { // console.log("err.response=", err.response) // console.log("dispatch=", dispatch) // } }, }); </code>
xx/src/models/login.js
<code> effects: { *login({ payload }, { call, put }) { console.log("payload=", payload) console.log("call=", call) console.log("put=", put) const response = yield call(getUserToken, payload); console.log("response=", response) response.status = 'ok' response.type = 'account' </code>
发现:
后面的错误:
Error: TypeError: Cannot set property ‘status’ of undefined
是代码:
response.status = ‘ok’
导致的,原因是:
此时的response是空
-》而response是空的原因是:
CORS错误,导致无法正常返回response
-〉所以:
后面的代码没有问题
还是要先去解决CORS的问题。
试试:
https://github.com/zestedesavoir/django-cors-middleware
<code>➜ xx git:(master) ✗ pip3 install django-cors-middleware Collecting django-cors-middleware Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.urllib3.connection.VerifiedHTTPSConnection object at 0x109998390>, 'Connection to files.pythonhosted.org timed out. (connect timeout=15)')': /packages/33/d8/23f4b1249021f0192a3d6f263c29b46637c1f03ab41608ed8477d992550d/django-cors-middleware-1.3.1.tar.gz Downloading https://files.pythonhosted.org/packages/33/d8/23f4b1249021f0192a3d6f263c29b46637c1f03ab41608ed8477d992550d/django-cors-middleware-1.3.1.tar.gz Building wheels for collected packages: django-cors-middleware Running setup.py bdist_wheel for django-cors-middleware ... done Stored in directory: /Users/crifan/Library/Caches/pip/wheels/1c/bd/91/bb2ee8ca87deb8c32db5d0356112f0e9b4abde22221e5d502c Successfully built django-cors-middleware Installing collected packages: django-cors-middleware Successfully installed django-cors-middleware-1.3.1 </code>
然后把去掉
django-cors-headers
换成:
django-cors-middleware
问题依旧。
还是换回去:
django-cors-headers
https://github.com/ottoyiu/django-cors-headers
“If True, the whitelist will not be used and all origins will be accepted.”
所以,已经:
CORS_ORIGIN_ALLOW_ALL = True
就去掉:
<code># CORS_ORIGIN_WHITELIST = ('*', 'localhost:8001', 'localhost:8000', 'localhost:65000') # CORS_ORIGIN_WHITELIST = ('localhost:8001', 'localhost:8000', 'localhost:65000') </code>
结果:问题依旧。
The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’
javascript – CORS: credentials mode is ‘include’ – Stack Overflow
Django must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’
fetch 带cookie跨域访问 – SegmentFault 思否
axios的cookie跨域以及相关配置 – 个人文章 – SegmentFault 思否
记一次header跨域与cookie共享 – andy_chan – 博客园
Django the request’s credentials mode is ‘include’
看本地的Django的log是:
<code>➜ xx git:(master) ✗ python3 ./manage.py runserver_plus 65000 * Running on http://127.0.0.1:65000/ (Press CTRL+C to quit) * Restarting with stat Performing system checks... System check identified no issues (0 silenced). Django version 2.0.6, using settings 'conf.development.settings' Development server is running at http://[127.0.0.1]:65000/ Using the Werkzeug debugger (http://werkzeug.pocoo.org/) Quit the server with CONTROL-C. * Debugger is active! * Debugger PIN: 119-413-930 127.0.0.1 - - [06/Jul/2018 15:49:27] "OPTIONS /api/v1/jwt-token-auth/ HTTP/1.1" 200 - </code>
-》看来是:
需要把host加上127.0.0.1?
并且也注意到:
127.0.0.1 – – [06/Jul/2018 15:49:27] “OPTIONS /api/v1/jwt-token-auth/ HTTP/1.1” 200 –
表示此处的CORS的OPTIONS,是支持了的
但是对于后续的login的POST出错了。
试试:
<code>CORS_ORIGIN_WHITELIST = ( 'localhost:8001', 'localhost:8000', 'localhost:65000', '127.0.0.1:8001', '127.0.0.1:8000', '127.0.0.1:65000', ) </code>
结果:
http://localhost:8000/#/user/login
错误依旧。
难道是本地的Python版本的问题?
此处用的是:
/usr/local/lib/python3.6/
别人(没有CORS问题)用的是:
/usr/local/var/pyenv/versions/3.6.3/lib/python3.6
django Access-Control-Allow-Origin header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’
django fetch Access-Control-Allow-Origin header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’
Cross-Origin Resource Sharing (CORS) – HTTP | MDN
最后此处经过调试是:
实际上此处的django-cors-headers是工作了的
然后对于:
如果Chrome中没有启动CORS插件:
那么几种配置:
<code>CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_CREDENTIALS = True </code>
或:
<code>CORS_ORIGIN_WHITELIST = ('*', 'localhost:8001', 'localhost:8000', 'localhost:65000') CORS_ALLOW_CREDENTIALS = True </code>
其中包含了自己此处的地址:
http://localhost:8000/#/user/login/
对应的:
localhost:8000
或:
<code>CORS_ORIGIN_WHITELIST = ( 'localhost:8001', 'localhost:8000', 'localhost:65000', # '127.0.0.1:8001', # '127.0.0.1:8000', # '127.0.0.1:65000', ) </code>
都是可以工作的,都可以正常登录:
但是如果开启了Chrome的CORS插件:
那么上面的配置,无论如何,都无法生效,都无法登录,出现前面的错误:
<code>Failed to load http://localhost:65000/api/v1/jwt-token-auth/: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:8000' is therefore not allowed access. </code>
而另外,对于前端代码
其中给fetch的(去登录时的)POST加上:
<code>credentials: 'include', </code>
-》
方式1:
xx/src/utils/request.js
中加上:
<code>export default function request(url, options) { const defaultOptions = { credentials: 'include', }; const newOptions = { ...defaultOptions, ...options }; if (newOptions.method === 'POST' || newOptions.method === 'PUT' || newOptions.method === 'PATCH') { newOptions.credentials = 'include' if (!(newOptions.body instanceof FormData)) { </code>
或:
方式2:
xx/src/services/api.js
中加上:
<code>export async function getUserToken(params) { return request(`${apiHost}${apiVersion}/jwt-token-auth/`, { method: 'POST', credentials : 'include', body: params, }); } </code>
然后发现其实:
xx/src/utils/request.js
已经有了:
<code> const defaultOptions = { credentials: 'include', }; </code>
所以去掉了,也不影响前面测试的效果。
【总结】
对于此处错误:
<code>Failed to load http://localhost:65000/api/v1/jwt-token-auth/: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:8000' is therefore not allowed access. </code>
的解释是:
如果你的请求(此处是web前端中js中的fetch)的credentials是include模式的话
更多的可能的值,详见:
<code>postData('http://example.com/answer', {answer: 42}) .then(data => console.log(data)) // JSON from `response.json()` call .catch(error => console.error(error)) function postData(url, data) { // Default options are marked with * return fetch(url, { body: JSON.stringify(data), // must match 'Content-Type' header cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached credentials: 'same-origin', // include, same-origin, *omit headers: { 'user-agent': 'Mozilla/4.0 MDN Example', 'content-type': 'application/json' }, method: 'POST', // *GET, POST, PUT, DELETE, etc. mode: 'cors', // no-cors, cors, *same-origin redirect: 'follow', // manual, *follow, error referrer: 'no-referrer', // *client, no-referrer }) .then(response => response.json()) // parses response to JSON } </code>
的:
same-origin
omit
就不应该:
<code>Access-Control-Allow-Origin: * </code>
然后最后找到的原因是:
此处Chrome(之前安装了的)CORS插件是开启了的:
从而导致出错的。
而正确的做法是:
确保此处的Chrome的CORS插件(如果有的话),不要开启,是关闭的:
然后去使用如下配置:
最终,Django(版本:2.0.6)中对于django-cors-headers(版本:2.2.0)来说,相关配置:
<code>INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.sites', 'rest_framework', 'corsheaders', 'rest_framework_swagger', 'django_extensions', 'apps.core', 'apps.user', 'apps.script', ] </code>
其中
‘corsheaders’,
放在中间即可。
<code>MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] </code>
其中:
corsheaders.middleware.CorsMiddleware
放在最上面
尤其是要在:
django.middleware.common.CommonMiddleware
的前面。
<code>CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOW_CREDENTIALS = True </code>
即可。
而其中的
CORS_ORIGIN_ALLOW_ALL = True
可以换成:
<code>CORS_ORIGIN_ALLOW_ALL = False CORS_ORIGIN_WHITELIST = ( 'localhost:8001', 'localhost:8000', 'localhost:65000', # '127.0.0.1:8001', # '127.0.0.1:8000', # '127.0.0.1:65000', ) </code>
或:
<code>CORS_ORIGIN_ALLOW_ALL = False CORS_ORIGIN_WHITELIST = ('*', 'localhost:8001', 'localhost:8000', 'localhost:65000') </code>
意思是:
不是允许allow所有all的origin,只允许whitelist(白名单)中的这些值
其中的:
localhost:8000
对应着此处的web前端的地址:
http://localhost:8000/#/user/login/
然后,Django后台log才正常,OPTIONS后,才能正常POST:
<code>➜ xx git:(master) ✗ python3 ./manage.py runserver_plus 65000 * Running on http://127.0.0.1:65000/ (Press CTRL+C to quit) * Restarting with stat Performing system checks... System check identified no issues (0 silenced). Django version 2.0.6, using settings 'conf.development.settings' Development server is running at http://[127.0.0.1]:65000/ Using the Werkzeug debugger (http://werkzeug.pocoo.org/) Quit the server with CONTROL-C. * Debugger is active! * Debugger PIN: 119-413-930 * Detected change in '/Users/crifan/dev/dev_root/company/xx/conf/development/settings.py', reloading * Restarting with stat Performing system checks... ... 127.0.0.1 - - [06/Jul/2018 16:41:28] "OPTIONS /api/v1/jwt-token-auth/ HTTP/1.1" 200 - 127.0.0.1 - - [06/Jul/2018 16:41:28] "POST /api/v1/jwt-token-auth/ HTTP/1.1" 200 - 127.0.0.1 - - [06/Jul/2018 16:41:28] "OPTIONS /api/v1/users/current_user/ HTTP/1.1" 200 - 127.0.0.1 - - [06/Jul/2018 16:41:29] "GET /api/v1/users/current_user/ HTTP/1.1" 200 - 127.0.0.1 - - [06/Jul/2018 16:41:29] "OPTIONS /api/v1/scripts/? HTTP/1.1" 200 - 127.0.0.1 - - [06/Jul/2018 16:41:29] "GET /api/v1/scripts/? HTTP/1.1" 200 - </code>
更多解释详见:
https://github.com/ottoyiu/django-cors-headers
【后记】
后来才发现,原来前面这个帖子:
中已经提到了:
Chrome的CORS插件
只是做了一件事情:给response中的header中插入一个:
<code>Access-Control-Allow-Origin: * </code>
-》而如果插件更加智能的话,应该插入:
<code>Access-Control-Allow-Origin: http://localhost:8000 </code>
其中
http://localhost:8000
是此处request的origin
所以结论是:
避免使用Chrome的CORS插件。
而此处经过上面的测试,确定Chrome的CORS插件,至少会导致此处的CORS的问题,所以还是以后尽量不用Chrome的CORS插件了。
【后记】
如果不用CORS插件,暂时又不想要删除,可以去禁用:
转载请注明:在路上 » 【已解决】Chrom中js去POST本地Django的API出错:The value of the Access-Control-Allow-Origin header in the response must not be the wildcard * when the request’s credentials mode is include