请耐心等待,这需要一些解释。
我正在帮助构建一个混合移动网络应用程序。主要代码库是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: true
和Access-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但我并不理解建议的答案。任何帮助将非常感激!
答案 0 :(得分:7)
我意识到这个问题已经过时了,但我想我无论如何都要投入其中。在CORS请求的情况下,浏览器预检它们。这意味着 - 尽管您使用的是$.ajax()
方法,但OPTIONS
请求仍会发送到服务器。
此预检OPTIONS
请求实际上在做的是:
“嘿那里,外来服务器来自其他域名,我想发给你一个不简单的请求(简单的请求不是预检的)。我不简单的请求会有这些类型的标题和内容类型等等。如果可以的话,你能告诉我吗?“
然后服务器将执行它所做的任何事情(可能检查一些配置或数据库)并使用允许的原点,允许的标题和/或允许的方法进行响应。
最后 - 如果该预检OPTIONS
请求收到了允许实际$.ajax()
方法发布的响应,那么它就会发生。
CORS与JSONP不同。
所有这一切 - 虽然withCredentials
预检成功,但要求回复带有Access-Control-Allow-Credentials
标题(如问题中所述),这是Access-Control-Allow-Origins
和{{1}的补充}值,必须包含预期请求的方面。
例如 - 如果您要使用标题Access-Control-Allow-Methods
到POST
从来源http://foo-domain.com
发出CORS somevalue
请求,则预检http://bar-domain.com
请求将会消失并且为了将实际的帖子请求发送到OPTIONS
,http://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 spec,null
可以满足来自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']);