programing

CORS를 통한 Ajax 요청을 사용하는 브라우저의 Set-Cookie

newnotes 2023. 3. 6. 21:26
반응형

CORS를 통한 Ajax 요청을 사용하는 브라우저의 Set-Cookie

Ajax 로그인/사인업 프로세스를 구현하려고 합니다(인증 사이트 새로 고침 없음).상태를 유지하기 위해 쿠키를 사용합니다.지금쯤은 가지고 있을 줄 알았는데 서버에서 쿠키를 가져온 후 브라우저가 쿠키를 설정하지 않습니다.누구 도와줄 사람?요청 및 응답 헤더는 다음과 같습니다.

Request URL:http://api.site.dev/v1/login
Request Method:POST
Status Code:200 OK

요청 헤더

Accept:application/json, text/plain, */*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:57
Content-Type:application/json;charset=UTF-8
Host:api.site.dev
Origin:http://site.dev
Referer:http://site.dev/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.101 Safari/537.11
withCredentials:true
X-Requested-With:XMLHttpRequest
Request Payload
{"email":"calvinfroedge@gmail.com","password":"foobar"}

응답 헤더

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:X-Requested-With, Content-Type, withCredentials
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:http://site.dev
Connection:Keep-Alive
Content-Length:19
Content-Type:application/json
Date:Tue, 08 Jan 2013 18:23:14 GMT
Keep-Alive:timeout=5, max=99
Server:Apache/2.2.22 (Unix) DAV/2 PHP/5.4.7 mod_ssl/2.2.22 OpenSSL/0.9.8r
Set-Cookie:site=%2B1THQQ%2BbZkEwTYFvXFVV5fxi00l2K%2B6fvt9SuHACTNsEwUGzDSUckt38ZeDsNbZSsqzHmPMWRLc84eDLZzh8%2Fw%3D%3D; expires=Thu, 10-Jan-2013 18:23:14 GMT; path=/; domain=.site.dev; httponly
X-Powered-By:PHP/5.4.7

서버로부터 반환된 크롬 네트워크 툴의 쿠키도 표시됩니다.

응답 쿠키

Name: site
Value: %2B1THQQ%2BbZkEwTYFvXFVV5fxi00l2K%2B6fvt9SuHACTNsEwUGzDSUckt38ZeDsNbZSsqzHmPMWRLc84eDLZzh8%2Fw%3D%3D
Domain: .site.dev
Path: /
Expires: Session
Size: 196
Http: ✓

AJAX 요청은 "withCredentials" 설정이 true로 설정되어 있어야 합니다(XmlHttpRequest2 및 fetch에서만 사용 가능).

    var req = new XMLHttpRequest();
    req.open('GET', 'https://api.bobank.com/accounts', true); // force XMLHttpRequest2
    req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
    req.setRequestHeader('Accept', 'application/json');
    req.withCredentials = true; // pass along cookies
    req.onload = function()  {
        // store token and redirect
        let json;
        try {
            json = JSON.parse(req.responseText);
        } catch (error) {
            return reject(error);
        }
        resolve(json);
    };
    req.onerror = reject;

CORS, API 보안 및 쿠키에 대한 자세한 설명이 필요한 경우 StackOverflow 코멘트에 해당되지 않습니다.이 주제에 대해 쓴 이 기사를 보세요: http://www.redotheweb.com/2015/11/09/api-security.html

비슷한 문제가 있었는데 브라우저 설정이 서드파티 쿠키를 차단하고 있었습니다(Crome > Settings > Advanced Settings > Privacy > Content Settings > Block thirdparty cookie and site data).차단을 해제하면 문제가 해결되었습니다!

AJAX와 PHP를 사용하여 여러 서브도메인에서 하나의 API 도메인으로 쿠키를 전달하고 CORS를 올바르게 처리해야 했습니다.

이것이 과제이자 해결책이었습니다.

1 - api.example.com의 백엔드 PHP.

2 - one.example.com, two.example.com 등 여러 JS 프론트 엔드

3 - 쿠키는 양방향으로 전달되어야 합니다.

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 도메인을 호출하기 위해 여러 서브도메인을 사용하고 있기 때문에 이 기능은 사용할 수 없습니다.

이 솔루션은 쿠키를 전달하고 싶기 때문에 작동하지 않습니다.

header('Access-Control-Allow-Origin: *');  

JS 사이트의 쿠키 전달 설정과 충돌합니다.

xhrFields: {withCredentials: true}

제가 한 일은 다음과 같습니다.

1 - GET 파라미터를 사용하여 서브도메인을 전달합니다.

2 - (모든) 서브 도메인만 허용되도록 PHP의 메인 도메인을 하드코드합니다.

다음은 제 솔루션의 JS/JQuery AJAX 부분입니다.

function 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');

중요: 모든 서브도메인에 대해 쿠키를 설정하는 것을 잊지 마십시오.이 경우 쿠키의 도메인은 .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를 호출할 수 있습니다.

NB. 호출 서브도메인이 하나밖에 없는 경우에는 PHP 대신 .htaccess를 사용하여 CORS를 설정하는 것이 좋습니다.다음으로 api.example.com만을 호출하는.htaccess(linux/vlinux)의 예를 나타냅니다.

<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의 루트에 배치합니다.

언급URL : https://stackoverflow.com/questions/14221722/set-cookie-on-browser-with-ajax-request-via-cors

반응형