来自移动 WebView 的 CORS cookie 凭据使用 file://在本地加载 [英] CORS cookie credentials from mobile WebView loaded locally with file://

查看:17
本文介绍了来自移动 WebView 的 CORS cookie 凭据使用 file://在本地加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

忍受我,这个需要一些解释.

我正在帮助构建一个混合移动网络应用程序.主要代码库是 HTML5 和 JavaScript,它们将封装在本机移动 Web 视图(a la Phonegap)中.

部分功能要求应用将信息发布到由我们的一位客户控制的网络服务.由于其他人正在使用此 Web 服务,因此更改此 Web 服务的余地很小.我们使用 HTTP POST 发送 JSON 并从服务器接收响应.这个响应的一部分是一个 JSESSIONID cookie,它管理我们与服务器的会话.在初始 initSession() 调用之后,我们需要随每个 (AJAX) 请求发送 JSESSIONID cookie.

在移动设备上部署时,Web 应用程序封装在本机 Web 视图中,它通过浏览到 file:///path/to/app/index.html 来启动 Web 应用程序.

我们尝试的第一件事是要求我们的客户端在他们的响应头中设置 Access-Control-Allow-Origin: * 以允许 CORS.然后我们尝试发布到服务器:

$.ajax({url: 'http://thirdparty.com/ws',数据:数据,类型:POST",数据类型:JSON",成功:成功回调,错误:失败回调});

监控请求,很明显没有包含 cookie.仔细检查一下,在 CORS 规范中有一个 特殊部分用于处理用户凭据,其中包括会话 cookie.所以我修改了 AJAX 调用以包含这个:

$.ajax({url: 'http://thirdparty.com/ws',数据:数据,类型:POST",数据类型:JSON",成功:成功回调,错误:失败回调,xhrFields { withCredentials: true }});

另一个错误,这次来自浏览器.更多阅读结果如下:

<块引用>

如果第三方服务器没有使用 Access-Control-Allow-Credentials: true 标头响应,则响应将被忽略并且不可用于 Web 内容.

重要提示:当响应一个有凭据的请求时,服务器必须在Access-Control-Allow-Origin 标头中指定一个域,并且不能使用通配符.

因此我们需要更改服务器的标头以将 Access-Control-Allow-Credentials: trueAccess-Control-Allow-Origin 包含到我们的 Origin 中.>

这里我们终于解决了我的问题:当使用 file://协议加载网页时,从 Web View 发送的 Origin 请求头被设置为 null.因此它不能被服务器解析,所以服务器不能在 Access-Control-Allow-Origin 中设置它.但是,如果服务器无法将 Access-Control-Allow-Origin 设置为 * 以外的其他内容,我们将无法发送凭据,包括 cookie.

所以我被卡住了.该怎么办?我在这里看到了一个类似的问题,但我不太明白提议的回答.任何帮助将不胜感激!

解决方案

我意识到这个问题很老了,但我想无论如何我都会提出来.对于 CORS 请求,浏览器会对其进行预检.这意味着 - 无论您使用什么 $.ajax() 方法,都会向服务器发送 OPTIONS 请求.

这个预检的 OPTIONS 请求实际上是在说:

<块引用>

嘿,来自其他域的外国服务器,我想向您发送一个不简单的请求(简单的请求没有预检).我的不简单请求将具有这些类型的标头和内容类型等等.你能告诉我这是否合适吗?"

然后服务器会做它所做的一切(可能检查一些配置或数据库)并以允许的来源、允许的标头和/或允许的方法进行响应.

最后 - 如果该预检 OPTIONS 请求已收到允许实际 $.ajax() 方法运行的响应 - 就可以了.

CORS 与 JSONP 不同.

所有这一切 - 虽然 withCredentials 预检成功需要响应携带 Access-Control-Allow-Credentials 标头(如问题中所述),即 IN除了 Access-Control-Allow-OriginsAccess-Control-Allow-Methods 值,必须包括预期请求的方面.

例如 - 如果您要从源 http://foo-domain.com 发出 CORS POST 请求,请求头为 somevaluehttp://bar-domain.com,预检 OPTIONS 请求将发出,以便将实际发布请求发送到 http://bar-domain.comOPTIONS 请求需要接收包含 http 的 Access-Control-Allow-Origins 值的响应://foo-domain.com.这可以是源名称本身或 *.响应还需要包含 POSTAccess-Control-Allow-Methods 值.这也可能是 *.最后,如果我们希望允许我们的 somevalue 标头,响应必须包含一个 Access-Control-Allow-Headers 值,其中包括我们的 somevalue标题键或 *.

回过头来 - 如果您无法控制服务器,或者无法让服务器允许您的 CORS 请求,您可以始终使用 JSONP 或某些 urlEncoded 数据类型和/或发出没有自定义标头的简单请求.GETHEAD 和完整的 POST 请求通常是简单的请求.

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).

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.

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.

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:

$.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:

$.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.

So we need to change the server's headers to include Access-Control-Allow-Credentials: true and Access-Control-Allow-Origin to our 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.

So I'm stuck. What to do? I saw a similar question posted here but I don't really understand the proposed answer. Any help would be much appreciated!

解决方案

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.

What this preflighted OPTIONS request is actually doing is saying:

"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.

CORS is not the same as 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.

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 *.

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.

这篇关于来自移动 WebView 的 CORS cookie 凭据使用 file://在本地加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆