[英]Keeping the cookie after a cross-domain ajax request
運行在10.0.0.1
上的 javascript 應用程序嘗試通過跨域 ajax 調用對其用戶進行身份驗證。
請求看起來像:
function test(again){
$.ajax({
type: 'GET',
url: 'http://example.com/userinfo',
dataType: 'json',
success: function(userinfo){
if(again)
test(false);}});}
test(true);
來自服務器的第一個響應嘗試設置 cookie:
Access-control-allow-origin:http://10.0.0.1
Set-Cookie:PHPSESSID=uuj599r4k1ohp48f1poobil665; expires=Sat, 28-Jan-2012 17:10:40 GMT; path=/
但是第二個請求不包含此 cookie,也不包含對該域的任何其他 ajax 請求。
我不是要讀取另一個域的 cookie,我只是希望另一個域上的應用程序能夠設置和讀取它自己的 cookie。
這可能嗎?
我已經在 Chrome 和 Firefox 9 中進行了測試。
服務器應該設置標題:
response.Headers.Add("Access-Control-Allow-Credentials", "true");
客戶端設置為:
xhrFields: {
withCredentials: true
}
只要您使用支持 CORS 的瀏覽器,AJAX 請求上的 cookie 就應該可以工作。 但是您必須將XMLHttpRequest
上的withCredentials
設置為 true。
請參閱: withCredentials 屬性
我不使用 JQuery,但這里有一個專門withCredentials
通過 JQuery 設置withCredentials
的問題。
不,cookie 不能跨域共享。 假設瀏覽器支持它們,可以使用Access-Control-*
標頭為 AJAX 調用規避同源策略,但對於 cookie 則沒有辦法。
我需要使用 AJAX 和 PHP 將 cookie 從多個子域傳遞到單個 API 域。
這是挑戰和解決方案:
1 - api.example.com 上的后端 PHP。
2 - 多個 JS 前端,例如 one.example.com、two.example.com 等。
3 - Cookie 需要雙向傳遞。
4 - api.example.com 上從多個前端到 PHP 后端的 AJAX 調用
5 - 在 PHP 中,我不喜歡使用 $_SERVER["HTTP_ORIGIN"],在我看來並不總是可靠/安全(我有一些瀏覽器的 HTTP-ORIGIN 總是空的)。
在具有單個前端域的 PHP 中執行此操作的正常方法是從 PHP 代碼開始:
header('Access-Control-Allow-Origin: https://one.example.com');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
header('Access-Control-Allow-Credentials: true');
在 one.example.com 域上的 JS 中:
jQuery.ajax({
url: myURL,
type: "POST",
xhrFields: {withCredentials: true},
dataType: "text",
contentType: "text/xml; charset=\"utf-8\"",
cache: false,
headers: "",
data: myCallJSONStr,
success: function(myResponse) {.....}
但是,這是行不通的,因為我使用多個子域來調用我的 API 域。
這個解決方案將不起作用,因為我想傳遞 cookie:
header('Access-Control-Allow-Origin: *');
它與 JS 站點上的 pass on cookie 設置沖突:
xhrFields: {withCredentials: true}
這是我所做的:
1 - 使用 GET 參數傳遞子域。
2 - 在 PHP 中硬編碼主域,因此只允許(所有)子域。
這是我的解決方案的 JS/JQuery AJAX 部分:
函數 getSubDomain(){
let mySubDomain = "";
let myDomain = window.location.host;
let myArrayParts = myDomain.split(".");
if (myArrayParts.length == 3){
mySubDomain = myArrayParts[0];
}
return mySubDomain;
}
在 AJAX 調用中:
let mySubDomain = getSubDomain();
if (mySubDomain != ""){
myURL += "?source=" + mySubDomain + "&end"; //use & instead of ? if URL already has GET parameters
}
jQuery.ajax({
url: myURL,
type: "POST",
xhrFields: {withCredentials: true},
dataType: "text",
contentType: "text/xml; charset=\"utf-8\"",
cache: false,
headers: "",
data: myCallJSONStr,
success: function(myResponse) {.....}
最后,PHP部分:
<?php
$myDomain = "example.com";
$mySubdomain = "";
if (isset($_GET["source"])) {
$mySubdomain = $_GET["source"].".";
}
$myDomainAllowOrigin = "https://".$mySubdomain.$myDomain;
$myAllowOrigin = "Access-Control-Allow-Origin: ".$myDomainAllowOrigin;
//echo $myAllowOrigin;
header($myAllowOrigin);
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
header('Access-Control-Allow-Credentials: true');
重要信息,不要忘記為所有子域設置 cookie,在這種情況下,cookie 的域將是:.example.com(因此在主域前面有一個點):
<?php
//////////////// GLOBALS /////////////////////////////////
$gCookieDomain = ".example.com";
$gCookieValidForDays = 90;
//////////////// COOKIE FUNTIONS /////////////////////////////////
function setAPCookie($myCookieName, $myCookieValue, $myHttponly){
global $gCookieDomain;
global $gCookieValidForDays;
$myExpires = time()+60*60*24*$gCookieValidForDays;
setcookie($myCookieName, $myCookieValue, $myExpires, "/", $gCookieDomain, true, $myHttponly);
return $myExpires;
}
此解決方案允許我從 example.com 上的任何子域調用 api.example.com 上的 API。
注意。 對於只有一個調用子域的情況,我更喜歡使用 .htaccess 來設置 CORS 而不是 PHP。 下面是一個 .htaccess (linux/apache) 的例子,只有 one.example.com 調用 api.example.com:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "https://one.example.com"
Header set Access-Control-Allow-Headers "Origin, Content-Type, X-Auth-Token"
Header set Access-Control-Allow-Credentials "true"
</IfModule>
並將這個 .htaccess 放在 api.example.com 的根目錄中。
+Darin Dimitrov 懷疑“cookie 沒有被瀏覽器保存,因為它來自另一個域,而不是托管這個調用源的頁面的域”。
但是,在使用 JSONP 時會根據需要設置 cookie,但 JSONP 僅適用於 GET 請求。
我的解決方案是通過在<script>
加載以下 php 文件來檢索 cookie(PHP 會話 ID):
<? echo $_GET['callback'] . '("' . session_id() . '")'; ?>
並在所有跨域 POST 請求中將會話 ID 作為請求變量傳遞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.