来自移动WebView的CORS cookie凭证在本地加载了file://

时间:2012-02-01 21:51:21

标签: javascript ajax web-services cookies cors

请耐心等待,这需要一些解释。

我正在帮助构建一个混合移动网络应用程序。主要代码库是HTML5和JavaScript,它们将包含在本机移动Web视图(一个电话间隙)中。

部分功能要求应用程序将信息发布到由我们的客户控制的Web服务。由于其他人正在使用此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',
  data: data,
  type: "POST",
  dataType: "JSON",
  success: successCallback,
  error: failedCallback
});

监控请求,很明显没有包含cookie。仔细检查后会有一个special section in the CORS spec for dealing with user credentials,其中包含会话cookie。所以我修改了AJAX调用以包含这个:

$.ajax({
  url: 'http://thirdparty.com/ws',
  data: data,
  type: "POST",
  dataType: "JSON",
  success: successCallback,
  error: failedCallback,
  xhrFields { withCredentials: true }
});

另一个错误,这次来自浏览器。更多阅读产生了以下内容:

  

如果第三方服务器未使用Access-Control-Allow-Credentials: true标头回复,则响应将被忽略,并且不会对Web内容可用。

     

重要说明:在响应凭证请求时,服务器必须在Access-Control-Allow-Origin标头中指定域,并且不能使用通配符。

因此,我们需要更改服务器的标头,以便将Access-Control-Allow-Credentials: trueAccess-Control-Allow-Origin包含在我们的Origin中。

我们终于遇到了问题:when loading a web page using the file:// protocol,从Web View发送的Origin请求标头设置为null。因此,服务器无法对其进行解析,因此服务器无法在Access-Control-Allow-Origin中对其进行设置。但是,如果服务器无法将Access-Control-Allow-Origin设置为*以外的其他内容,我们就无法发送凭据,包括Cookie。

所以我被困住了。该怎么办? I saw a similar question posted here但我并不理解建议的答案。任何帮助将非常感激!

6 个答案:

答案 0 :(得分:7)

我意识到这个问题已经过时了,但我想我无论如何都要投入其中。在CORS请求的情况下,浏览器预检它们。这意味着 - 尽管您使用的是$.ajax()方法,但OPTIONS请求仍会发送到服务器。

此预检OPTIONS请求实际上在做的是:

  

“嘿那里,外来服务器来自其他域名,我想发给你一个不简单的请求(简单的请求不是预检的)。我不简单的请求会有这些类型的标题和内容类型等等。如果可以的话,你能告诉我吗?“

然后服务器将执行它所做的任何事情(可能检查一些配置或数据库)并使用允许的原点,允许的标题和/或允许的方法进行响应。

最后 - 如果该预检OPTIONS请求收到了允许实际$.ajax()方法发布的响应,那么它就会发生。

CORS与JSONP不同。

所有这一切 - 虽然withCredentials预检成功,但要求回复带有Access-Control-Allow-Credentials标题(如问题中所述),这是Access-Control-Allow-Origins和{{1}的补充}值,必须包含预期请求的方面。

例如 - 如果您要使用标题Access-Control-Allow-MethodsPOST从来源http://foo-domain.com发出CORS somevalue请求,则预检http://bar-domain.com请求将会消失并且为了将实际的帖子请求发送到OPTIONShttp://bar-domain.com请求需要收到包含OPTIONS的{​​{1}}值的回复。这可以是原始名称本身或Access-Control-Allow-Origins。响应还需要包含http://foo-domain.com的{​​{1}}值。这也可能是*。最后,如果我们希望允许Access-Control-Allow-Methods标头,则响应必须包含POST值,其中包含*标头密钥或somevalue

要回退 - 如果您无法控制服务器,或者无法允许服务器允许您的CORS请求,您可以始终使用JSONP或某些urlEncoded数据类型和/或在没有自定义标头的情况下发出简单请求。 <{1}},Access-Control-Allow-Headers和完整somevalue请求通常是简单的请求。

答案 1 :(得分:2)

我想如果您正在创建混合应用程序,那么您正在使用cordova。如果是这种情况,您不需要CORS,只需要列出您要访问的域名。

http://docs.phonegap.com/en/3.0.0/guide_appdev_whitelist_index.md.html

答案 2 :(得分:1)

我的建议是在服务器端将ACCESS-CONTROL-ALLOW-ORIGIN设置为null

是的,这个问题困扰了我一点点。

关于CORS specnull可以满足来自file://计划的CORS请求的情况

关于该规范的实用建议是将其设置为origin-list-or-null,这是一个以空格分隔的起源列表或简单地&#34; null&#34; (顺便说一下,%x6E %x75 %x6C %x6C定义中的字符串origin-list-or-null实际上是null十六进制编码的

最后,您会问,如果我们将*设置为ACCESS-CONTROL-ALLOW-ORIGIN,那么等于null,因为来自方案file://的每个请求都有效(这意味着每个混合应用都可以如果它知道你的uri,请访问你的端点?

好吧,鉴于Access-Control-Allow-Credentials: true,我相信您已经在服务器上运行了整个身份验证机制。它应该在没有正确的auth

的情况下过滤这些请求

希望它会有所帮助

答案 3 :(得分:0)

试着查看www.5app.co.uk.完全避免使用XHR调用,并在数据连接来来往往时在移动设备上可靠地工作。然后,Gateway与您的客户端连接。

答案 4 :(得分:0)

使用JsonP请求。 JsonP请求使您可以执行跨域请求。 Here就是一个例子。

答案 5 :(得分:0)

例如,在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']);