我试图对传递源服务器设置的cookie的跨源端点进行AJAX调用。在我的例子中,源服务器是http://localhost,端点是通过AWS API Gateway调用的AWS Lambda函数。原点有一个小的PHP脚本,它设置一个cookie并返回一个简单的HTML文档,其中包含对API网关端点的AJAX调用。
这是PHP脚本:
<?php
header('Origin: http://localhost');
setcookie('test', 'TEST', 0, '/', 'localhost', false, true);
?>
<html>
<head>
<title>Lambda Cookie Test</title>
<script src="https://code.jquery.com/jquery-3.2.1.min.js">//
</script>
<script type="text/javascript">
var doMagic = function() {
$.ajax({
url: "https://abcdefg.execute-api.eu-west-1.amazonaws.com/dev/MyFunction",
method: "GET",
dataType: 'json',
xhrFields: {
withCredentials: true
}
})
.done(function (data) {
$("#test").text(data);
})
.fail(function (xhr, status) {
$("#test").text("FAIL: " + status);
});
};
</script>
</head>
<body>
<div id="test">Nothing doing yet.</div>
<button type="button" onclick="doMagic()">Do Magic</button>
</body>
</html>
当我通过cURL调用端点时,设置Cookie
标头,我可以验证我的Lambda函数是否正常工作并返回所需的CORS标头。首先,这是OPTIONS
请求对API网关端点的响应:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 0
Connection: keep-alive
Date: Wed, 03 Jan 2018 17:55:24 GMT
x-amzn-RequestId: xxxx-xxx-xxx
Access-Control-Allow-Origin: http://localhost
Access-Control-Allow-Headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent,Access-Control-Allow-Origin,Access-Control-Allow-Credentials
Access-Control-Allow-Methods: OPTIONS,GET
Access-Control-Allow-Credentials: true
X-Cache: Miss from cloudfront
Via: 1.1 abc123.cloudfront.net (CloudFront)
X-Amz-Cf-Id: xxxxxxxxxx
以下是我从cURL发出的GET
请求:
GET /dev/MyFcuntion HTTP/1.1
Host: abc123.execute-api.eu-west-1.amazonaws.com
User-Agent: curl/7.55.1
Accept: */*
Cookie: test=TEST
回复:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 17
Connection: keep-alive
Date: Wed, 03 Jan 2018 17:57:48 GMT
x-amzn-RequestId: zzzz-zzz-zzz
Access-Control-Allow-Origin: http://localhost
X-Amzn-Trace-Id: sampled=0;root=x-xxxx-xxx
Access-Control-Allow-Credentials: true
X-Cache: Miss from cloudfront
Via: 1.1 abc123.cloudfront.net (CloudFront)
X-Amz-Cf-Id: xxxxxxxxxx
{"test":"TEST"}
这对我来说看起来很合理。
但是当我的浏览器尝试使用上面代码中的withCredentials: true
选项通过AJAX调用此API网关端点时,它会发出此请求:
Accept: application/json, text/javascript, */*; q=0.01
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.5
Connection: keep-alive
Host: abc123.execute-api.eu-west-1.amazonaws.com
Origin: http://localhost
Referer: http://localhost/
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:56.0) Gecko/20100101 Firefox/56.0
请注意没有传递从PHP脚本获取的test=TEST
Cookie。然后这是它得到的回应:
X-Firefox-Spdy: h2
access-control-allow-credentials: true
access-control-allow-origin: http://localhost
content-length: 42
content-type: application/json
date: Wed, 03 Jan 2018 17:41:56 GMT
via: 1.1 abc123.cloudfront.net (CloudFront)
x-amz-cf-id: xxxx
x-amzn-requestid: xxxx
x-amzn-trace-id: sampled=0;root=z-zzzzz
x-cache: Error from cloudfront
{"errorMessage":"No cookie"}
当没有提供请求cookie时,响应正文是我的Lambda函数的预期响应。我还将响应错误代码设置为400。
我已尝试过几种变体:
127.0.0.1
(而不是localhost
)这些都没有任何区别。
为什么AJAX不传递从原点获取的cookie?是否与localhost服务有关?这不可能吗?