簡體   English   中英

跨域ajax請求后保留cookie

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM