javascript 来自移动 WebView 的 CORS cookie 凭据使用 file:// 在本地加载
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9103876/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CORS cookie credentials from mobile WebView loaded locally with file://
提问by Tom Spencer
Bear with me, this one needs a bit of explanation.
忍受我,这个需要一点解释。
I am helping to build a hybrid mobile web app. The main codebase is HTML5 and JavaScript, which will be wrapped in a native mobile Web View (a la Phonegap).
我正在帮助构建一个混合移动网络应用程序。主要的代码库是 HTML5 和 JavaScript,它们将被包装在一个原生的移动 Web 视图(a la Phonegap)中。
Part of the functionality requires the app to post information to a web service controlled by one of our clients. There is very little scope to change this web service as it is being used by others. We send JSON using an HTTP POST and receive responses from the server. Part of this response is a JSESSIONID cookie which manages our session with the server. After the initial initSession()
call, we need to send the JSESSIONID cookie with every (AJAX) request.
部分功能要求应用程序将信息发布到由我们的一位客户控制的 Web 服务。由于其他人正在使用此 Web 服务,因此更改此 Web 服务的余地很小。我们使用 HTTP POST 发送 JSON 并从服务器接收响应。这个响应的一部分是一个 JSESSIONID cookie,它管理我们与服务器的会话。在初始initSession()
调用之后,我们需要随每个 (AJAX) 请求发送 JSESSIONID cookie。
When deployed on a mobile device, the web app is wrapped in the native Web View, which starts the web app by browsing to file:///path/to/app/index.html
.
当部署在移动设备上时,Web 应用程序被包装在本机 Web 视图中,它通过浏览到file:///path/to/app/index.html
.
The first thing we tried was asking our client to set Access-Control-Allow-Origin: *
in their response header to allow CORS. We then tried posting to the server:
我们尝试的第一件事是要求我们的客户Access-Control-Allow-Origin: *
在他们的响应头中设置允许 CORS。然后我们尝试发布到服务器:
$.ajax({
url: 'http://thirdparty.com/ws',
data: data,
type: "POST",
dataType: "JSON",
success: successCallback,
error: failedCallback
});
Monitoring the requests, it was apparent that the cookies were not being included. On closer inspection there is a special section in the CORS spec for dealing with user credentials, which includes session cookies. So I modified the AJAX call to include this:
监控请求,很明显没有包含 cookie。仔细检查一下,CORS 规范中有一个特殊部分用于处理用户凭据,其中包括会话 cookie。所以我修改了 AJAX 调用以包含以下内容:
$.ajax({
url: 'http://thirdparty.com/ws',
data: data,
type: "POST",
dataType: "JSON",
success: successCallback,
error: failedCallback,
xhrFields { withCredentials: true }
});
Another error, this time from the Browser. More reading yielded the following:
另一个错误,这次来自浏览器。更多阅读产生以下结果:
If the third party server did not respond with an
Access-Control-Allow-Credentials: true
header the response would be ignored and not made available to web content.Important note: when responding to a credentialed request, the server must specify a domain in the
Access-Control-Allow-Origin
header, and cannot use wild carding.
如果第三方服务器没有使用
Access-Control-Allow-Credentials: true
标头响应,则响应将被忽略并且不可用于 Web 内容。重要提示:响应凭据请求时,服务器必须在
Access-Control-Allow-Origin
标头中指定域,并且不能使用通配符。
So we need to change the server's headers to include Access-Control-Allow-Credentials: true
and Access-Control-Allow-Origin
to our Origin.
因此,我们需要更改服务器的标头以包含Access-Control-Allow-Credentials: true
和Access-Control-Allow-Origin
到我们的 Origin。
Here we finally come to my problem: when loading a web page using the file:// protocol, the Origin
request header sent from the Web View is set to null
. It therefore can't be parsed by the server and so the server can't set it in Access-Control-Allow-Origin
. But if the server can't set Access-Control-Allow-Origin
to something other than *
we can't send credentials, including cookies.
到这里我们终于来了我的问题:当使用 file:// 协议加载网页时,Origin
从 Web View 发送的请求头被设置为null
. 因此它不能被服务器解析,所以服务器不能将它设置在Access-Control-Allow-Origin
. 但是,如果服务器不能设置Access-Control-Allow-Origin
为其他东西,*
我们就不能发送凭据,包括 cookie。
So I'm stuck. What to do? I saw a similar question posted herebut I don't really understand the proposed answer. Any help would be much appreciated!
所以我被困住了。该怎么办?我在这里看到了一个类似的问题,但我不太明白建议的答案。任何帮助将非常感激!
回答by J.Wells
I realize this question is old, but I figured I'd throw in on it anyhow. In the case of CORS requests, the browser preflights them. What this means is - in spite of whatever $.ajax()
method you are using, an OPTIONS
request is sent to the server.
我意识到这个问题很旧,但我想无论如何我都会提出来。对于 CORS 请求,浏览器会对其进行预检。这意味着 - 无论$.ajax()
您使用什么方法,OPTIONS
都会向服务器发送请求。
What this preflighted OPTIONS
request is actually doing is saying:
这个预检OPTIONS
请求实际上是在说:
"Hey there, foreign-server-from-some-other-domain, I want to send you a not-simple request (simple req's are not preflighted). My not-simple request going to have these kinds of headers and content type and so on. Can you let me know if this is okay?"
“嘿,来自其他域的外国服务器,我想向您发送一个不简单的请求(简单的请求没有预检)。我的不简单请求将具有这些类型的标头和内容类型以及等等。你能告诉我这是否可以吗?
Then the server will do whatever it does (probably check some configuration or database) and respond with the allowable origin(s), the allowable header(s), and/or the allowable method(s).
然后服务器将做它所做的任何事情(可能检查一些配置或数据库)并以允许的来源、允许的标头和/或允许的方法进行响应。
Finally - if that preflight OPTIONS
request has received response that allows the actual $.ajax()
method to go - it goes.
最后 - 如果该预检OPTIONS
请求已收到允许实际$.ajax()
方法运行的响应- 它会继续。
CORS is not the same as JSONP.
CORS 与 JSONP 不同。
All that said - while withCredentials
preflight success requires the response to carry a Access-Control-Allow-Credentials
header (as stated in the question), that is IN ADDITION to Access-Control-Allow-Origins
AND Access-Control-Allow-Methods
values, which must include the facets of the intended request.
所有这一切 - 虽然withCredentials
预检成功需要响应携带Access-Control-Allow-Credentials
标头(如问题中所述),这是对Access-Control-Allow-Origins
ANDAccess-Control-Allow-Methods
值的补充,其中必须包括预期请求的方面。
For example - if you are making a CORS POST
request from origin http://foo-domain.com
with headers somevalue
to http://bar-domain.com
, a preflight OPTIONS
request would go out and in order for the actual post request to be made to http://bar-domain.com
, the OPTIONS
request would need to receive a response with an Access-Control-Allow-Origins
value that included http://foo-domain.com
. This could be the origin name itself or *
. The response would also need to have an Access-Control-Allow-Methods
value that included POST
. This may also be *
. And Finally if we want our somevalue
header to be allowed, the response must contain a Access-Control-Allow-Headers
value that includes our somevalue
header key or *
.
例如,如果您POST
从源头发出一个http://foo-domain.com
带有somevalue
to的 CORS请求http://bar-domain.com
,一个预检OPTIONS
请求将会发出,并且为了发出实际的 post 请求http://bar-domain.com
,该OPTIONS
请求需要接收一个Access-Control-Allow-Origins
包含http://foo-domain.com
. 这可能是原始名称本身或*
. 响应还需要包含一个Access-Control-Allow-Methods
值POST
。这也可能是*
。最后,如果我们希望我们的somevalue
标头被允许,响应必须包含一个Access-Control-Allow-Headers
包含我们somevalue
标头键或 的值*
。
To circle back - if you can't control the server, or have no way to allow the server to allow your CORS requests, you could always use JSONP or some urlEncoded datatype and/or make simple requests without custom headers. GET
, HEAD
, and full POST
requests are usually simple requests.
回过头来 - 如果您无法控制服务器,或者无法让服务器允许您的 CORS 请求,您可以始终使用 JSONP 或某些 urlEncoded 数据类型和/或发出没有自定义标头的简单请求。GET
、HEAD
和 完整POST
请求通常是简单请求。
回答by Jorge Enrique Reyes Salas
I imagine that if you are creating a hybrid application you are using cordova. If that is the case you don't need CORS you just need to white list the domains you are going to access.
我想如果您正在创建一个混合应用程序,您将使用cordova。如果是这种情况,您不需要 CORS,您只需要将要访问的域列入白名单。
http://docs.phonegap.com/en/3.0.0/guide_appdev_whitelist_index.md.html
http://docs.phonegap.com/en/3.0.0/guide_appdev_whitelist_index.md.html
回答by Ace
My suggestion is set ACCESS-CONTROL-ALLOW-ORIGIN
to null
on server side
我的建议设置 ACCESS-CONTROL-ALLOW-ORIGIN
为null
在服务器端
Yes, This question bothers me for a little bit.
是的,这个问题让我有点困扰。
Regarding to CORS spec, null
can cater the situation where a CORS request from a file://
scheme
关于CORS 规范,null
可以满足来自file://
方案的 CORS 请求的情况
And a pratical recommendation on that spec is to set it as origin-list-or-null, which is either a list of space-separated origins or simply "null" (by the way, the string %x6E %x75 %x6C %x6C
from the definition for origin-list-or-null
is literally null
hex- encoded)
关于该规范的一个实用建议是将其设置为origin-list-or-null,它要么是空格分隔的起源列表,要么只是“null”(顺便说一下,%x6E %x75 %x6C %x6C
定义中的字符串origin-list-or-null
实际上是null
十六进制的-编码)
Finally you will ask, wont that equal to *
if we set ACCESS-CONTROL-ALLOW-ORIGIN
to null
since every request from scheme file://
is valid (which means every hybrid app can access your endpoint if it knows about your uri)?
最后你会问,这不等于*
如果我们设置ACCESS-CONTROL-ALLOW-ORIGIN
为null
因为来自方案的每个请求file://
都是有效的(这意味着每个混合应用程序都可以访问你的端点,如果它知道你的 uri)?
Well, given Access-Control-Allow-Credentials: true
, I believe you've got a whole auth mechanism working on the server. It should have filtered those requests without the correct auth
好吧,鉴于Access-Control-Allow-Credentials: true
,我相信您已经在服务器上使用了完整的身份验证机制。它应该在没有正确身份验证的情况下过滤掉那些请求
Hope it will help
希望它会有所帮助
回答by Onimo
On php side for example you need set this:
例如,在 php 端,您需要设置:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, X-Request-With, Set-Cookie, Cookie, Bearer');
header('Access-Control-Allow-Credentials: true');
// header('Cookie: PHPSESSID='.$_COOKIE['PHPSESSID']);
回答by ksivamuthu
回答by Tim King
Try looking at www.5app.co.uk. Avoids use of XHR calls altogether and works reliably on mobile when data connections comes and goes. Gateway then interfaces with your client.
尝试查看 www.5app.co.uk。完全避免使用 XHR 呼叫,并在数据连接来来去去时在移动设备上可靠地工作。然后网关与您的客户端连接。