क्रॉस मूल अनुरोधों के लिए कुकीज़ सेट करें


102

कुकीज़ कैसे पार करें? अधिक विशेष रूप से, Set-Cookieहेडर के साथ संयोजन में हेडर का उपयोग कैसे करें Access-Control-Allow-Origin?

यहाँ मेरी स्थिति का स्पष्टीकरण दिया गया है:

मैं एक एपीआई के लिए एक कुकी सेट करने का प्रयास कर रहा हूं localhost:4000जो एक वेब ऐप पर चल रहा है जिसे होस्ट किया गया है localhost:3000

ऐसा लगता है कि मैं ब्राउज़र में सही प्रतिक्रिया हेडर प्राप्त कर रहा हूं, लेकिन दुर्भाग्य से उनका कोई प्रभाव नहीं है। ये प्रतिक्रिया हेडर हैं:

HTTP / 1.1 200 ठीक है
अभिगम-नियंत्रण-अनुमति-उत्पत्ति: http: // localhost: 3000
वैरी: उत्पत्ति, स्वीकार-एनकोडिंग
सेट-कुकी: टोकन = 0d522ba17e130d6d19eb9c25b7ac58387b798639f81ffe75bd449afbc3cc715d6b038d426adeac3316f0511dc7fae3f7; अधिकतम उम्र 86400 =; डोमेन = स्थानीय होस्ट: 4000; पथ = /; एक्सपायर = ट्यु, 19 सितंबर 2017 21:11:36 जीएमटी; केवल Http
सामग्री-प्रकार: आवेदन / json; charset = utf-8
कंटेंट-लंबाई: 180
ETag: W / "b4-VNrmF4xNeHGeLrGehNZTQNwAaUQ"
दिनांक: सोम, १: सितम्बर २०१ Sep २१:११:३६ GMT
कनेक्शन: जीवित रखें

इसके अलावा, मैं कुकी को Response Cookiesतब देख सकता हूं जब मैं Chrome के डेवलपर टूल के नेटवर्क टैब का उपयोग करके ट्रैफ़िक का निरीक्षण करता हूं। फिर भी, मैं एक कुकी को अनुप्रयोग टैब के अंतर्गत सेट नहीं किया जा सकता Storage/Cookies। मुझे कोई CORS त्रुटियां नहीं दिखाई देती हैं, इसलिए मुझे लगता है कि मैं कुछ और याद कर रहा हूं।

कोई सुझाव?

अपडेट I:

मैं सर्वर पर एक समापन बिंदु के लिए एक अनुरोध जारी करने के लिए एक रिएक्ट-रिडक्स एप्लिकेशन में अनुरोध मॉड्यूल का उपयोग कर रहा हूं /signin। सर्वर के लिए मैं एक्सप्रेस का उपयोग करता हूं।

एक्सप्रेस सर्वर:

res.cookie ('टोकन', 'xxx-xxx-xxx', {maxAge: 86400000, httpOnly: true, domain: 'localhost: 3000'})

ब्राउज़र में अनुरोध:

request.post ({uri: '/ signin', json: {userName: 'userOne', पासवर्ड: '123456'}}, (त्रुटी, प्रतिक्रिया, निकाय) => {
    // कार्य करना
})

अपडेट II:

मैं अब पागलों की तरह अनुरोध और प्रतिक्रिया हेडर सेट कर रहा हूं, यह सुनिश्चित करते हुए कि वे अनुरोध और प्रतिक्रिया दोनों में मौजूद हैं। नीचे एक स्क्रीनशॉट है। सूचना हेडर Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methodsऔर Access-Control-Allow-Origin। इस मुद्दे को देखकर मुझे एक्सियोस के जीथब में मिला , मैं इस धारणा के तहत हूं कि सभी आवश्यक हेडर अब सेट हो गए हैं। फिर भी, अभी भी कोई भाग्य नहीं है ...

यहां छवि विवरण दर्ज करें


4
@PimHeijden इस पर एक नज़र डालें: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/… शायद withCredentials का उपयोग आपको क्या चाहिए?
कलमारिको 13

2
ठीक है आप अनुरोध का उपयोग कर रहे हैं और मुझे लगता है कि यह सबसे अच्छा विकल्प नहीं है, इस पोस्ट और उत्तर पर एक नज़र डालें, मुझे लगता है कि axios मुझे आपके लिए उपयोगी हो सकता है। stackoverflow.com/questions/39794895/…
कलमारिको

धन्यवाद! मैं यह नोटिस करने में विफल रहा कि requestमॉड्यूल ब्राउज़र में उपयोग के लिए नहीं है। Axios अब तक एक बहुत अच्छा काम करता है। मुझे अब दोनों हेडर मिलते हैं: Access-Control-Allow-Credentials:trueऔर Access-Control-Allow-Origin:http://localhost:3000(कॉर्स को सक्षम करने के लिए उपयोग किया जाता है)। यह सही लगता है, लेकिन Set-Cookieहेडर कुछ भी नहीं करता है ...
पिम हाइजेन

एक ही मुद्दा है, लेकिन सीधे Axios का उपयोग कर: stackoverflow.com/q/43002444/488666 । जबकि { withCredentials: true }एक्सियोस की ओर से वास्तव में आवश्यक है, सर्वर हेडर को सावधानी से
फ्रॉस्टी जेड

क्या सर्वर हेडर?
पिम हाइजेन

जवाबों:


169

आपको क्या करने की आवश्यकता है

सफलतापूर्वक कोर्से अनुरोध द्वारा कुकीज़ प्राप्त करने और भेजने की अनुमति देने के लिए, निम्नलिखित करें।

बैक-एंड (सर्वर): HTTP हेडर Access-Control-Allow-Credentialsमान को सेट करें true। इसके अलावा, सुनिश्चित करें कि HTTP हेडर Access-Control-Allow-Originऔर Access-Control-Allow-Headersसेट हैं और वाइल्डकार्ड के साथ नहीं*

एक्सप्रेस js में कोर सेट करने के बारे में अधिक जानकारी के लिए डॉक्स यहां पढ़ें

फ्रंट-एंड (क्लाइंट):XMLHttpRequest.withCredentials ध्वज को सेट करें true, इसे अलग-अलग तरीकों से प्राप्त किया जा सकता है जो अनुरोध-प्रतिक्रिया लाइब्रेरी के आधार पर किया जाता है:

या

कुकीज़ के साथ संयोजन में कॉर्स का उपयोग करने से बचें। आप इसे एक प्रॉक्सी के साथ प्राप्त कर सकते हैं।

यदि आप जो भी कारण से बचने के लिए नहीं है। समाधान ऊपर है।

यह पता चला है कि यदि डोमेन में पोर्ट है तो क्रोम कुकी को सेट नहीं करेगा। localhost(पोर्ट के बिना) के लिए इसे सेट करना कोई समस्या नहीं है। इस टिप के लिए इरविन को बहुत धन्यवाद !


2
मुझे लगता है कि आपके पास यह समस्या सिर्फ इस वजह से है कि localhostयह जाँच करें: stackoverflow.com/a/1188145 और यह भी आपके मामले में मदद कर सकता है ( stackoverflow.com/questions/50966861/… )
एडविन

5
इस जवाब ने मुझे बहुत मदद की! इसे खोजने में काफी समय लगा। लेकिन मुझे लगता है कि उत्तर में उस Access-Control-Allow-Originस्पष्ट डोमेन का उल्लेख होना चाहिए , न कि केवल "*"आवश्यक है। फिर इसका सही जवाब होगा
e.dan

6
यह अच्छा उत्तर है, और कोर, हेडर, बैकएंड और फ्रंट एंड के लिए सभी सेटअप, और ओवरहाइड / आदि के साथ लोकलहोस्ट से बचने के लिए स्थानीय रूप से एक वास्तविक उपडोमेन के साथ होस्ट करता है, फिर भी मैं देखता हूं कि पोस्टमैन प्रतिक्रिया हेडर में एक सेट-कूकी दिखाता है लेकिन क्रोम डिबग नहीं करता है प्रतिक्रिया हेडर में यह दिखाएं और कुकी को वास्तव में क्रोम में सेट नहीं किया गया है। जाँच करने के लिए कोई अन्य विचार?
bjm88

1
@ bjm88 क्या आपने इसे समाप्त किया है? मैं ठीक उसी स्थिति में हूं। लोकलहोस्ट: 3010 से लोकलहोस्ट: 5001 से कनेक्ट करते समय कुकी को ठीक से सेट किया गया है, लेकिन लोकलहोस्ट से काम नहीं करता है: 3010 से फ़ेकरेमोटे: 5001 (जो मेरे होस्ट फ़ाइल में 127.0.0.1 की ओर इशारा करता है)। जब मैं अपने सर्वर को कस्टम डोमेन के साथ वास्तविक सर्वर पर होस्ट करता हूं (लोकलहोस्ट: 3010 से mydomain.com से कनेक्ट करता है) तो यह ठीक वैसा ही है। मैंने इस उत्तर में सभी की सिफारिश की है और मैंने बहुत सी अन्य चीजों की कोशिश की है।
फॉर्म

1
कोणीय में, आवश्यक ग्राहक पक्ष परिवर्तन को भी जोड़ने के लिए है क्रेडेंशियल्स: HttpClient.post, .get, विकल्प, आदि के लिए दिए गए विकल्पों के लिए सच है
मारविन

18

2020 में क्रोम ब्राउज़र के लिए नोट जारी किया गया।

Chrome की भावी रिलीज़ केवल कुकीज़ को क्रॉस-साइट अनुरोधों के साथ वितरित करेगी यदि वे साथ सेट हैं SameSite=Noneऔर Secure

इसलिए यदि आपका बैकएंड सर्वर सेमसाइट = कोई नहीं सेट करता है, तो क्रोम डिफ़ॉल्ट रूप से सेमसाइट = लैक्स का उपयोग करेगा और {कुकी के साथ इस कुकी का उपयोग नहीं करेगा: सच} अनुरोध।

अधिक जानकारी https://www.chromium.org/updates/same-site

फ़ायरफ़ॉक्स और एज डेवलपर्स भी भविष्य में इस सुविधा को जारी करना चाहते हैं।

यहाँ पाया गया है: https://tools.ietf.org/html/draft-west-cookie-incrementalism-01##8


4
samesite प्रदान करना = कोई नहीं और सुरक्षित ध्वज को HTTPS की आवश्यकता होती है। स्थानीय प्रणाली में इसे कैसे प्राप्त किया जाए जहां HTTPS एक विकल्प नहीं है? क्या हम किसी तरह से बायपास कर सकते हैं?
निर्मल पटेल

@ निर्मलपटेल बस "देव" मूल्य को चोम देव कंसोल में हटा दें।
लेनीलिप

4

क्लाइंट के लिए क्रॉस-ऑरिजनल रिक्वेस्ट से कुकीज़ को पढ़ने में सक्षम होने के लिए, आपके पास यह होना चाहिए:

  1. सर्वर से सभी प्रतिक्रियाओं को उनके हेडर में निम्नलिखित की आवश्यकता होती है:

    Access-Control-Allow-Credentials: true

  2. ग्राहक को सभी अनुरोधों को withCredentials: trueविकल्प के साथ भेजने की आवश्यकता है

कोणीय 7 और स्प्रिंग बूट के साथ मेरे कार्यान्वयन में, मैंने निम्नलिखित के साथ यह हासिल किया:


सर्वर साइड:

@CrossOrigin(origins = "http://my-cross-origin-url.com", allowCredentials = "true")
@Controller
@RequestMapping(path = "/something")
public class SomethingController {
  ...
}

origins = "http://my-cross-origin-url.com"भाग जोड़ना होगा Access-Control-Allow-Origin: http://my-cross-origin-url.comहर सर्वर की प्रतिक्रिया हेडर को

allowCredentials = "true"भाग जोड़ देगा Access-Control-Allow-Credentials: trueग्राहक कुकीज़ को पढ़ने के लिए क्रम में हर सर्वर की प्रतिक्रिया हेडर है, जो करने के लिए हम क्या जरूरत है


ग्राहक की ओर:

import { HttpInterceptor, HttpXsrfTokenExtractor, HttpRequest, HttpHandler, HttpEvent } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from 'rxjs';

@Injectable()
export class CustomHttpInterceptor implements HttpInterceptor {

    constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // send request with credential options in order to be able to read cross-origin cookies
        req = req.clone({ withCredentials: true });

        // return XSRF-TOKEN in each request's header (anti-CSRF security)
        const headerName = 'X-XSRF-TOKEN';
        let token = this.tokenExtractor.getToken() as string;
        if (token !== null && !req.headers.has(headerName)) {
            req = req.clone({ headers: req.headers.set(headerName, token) });
        }
        return next.handle(req);
    }
}

इस वर्ग के साथ आप वास्तव में अपने सभी अनुरोध पर अतिरिक्त सामान इंजेक्ट करते हैं।

पहला भाग req = req.clone({ withCredentials: true });, withCredentials: trueविकल्प के साथ प्रत्येक अनुरोध भेजने के लिए आपको क्या चाहिए । व्यावहारिक रूप से इसका मतलब है कि एक विकल्प अनुरोध पहले भेजा जाएगा, ताकि आपको वास्तविक POST / PUT / DELETE अनुरोध भेजने से पहले अपने कुकीज़ और प्राधिकरण टोकन मिल जाएं, जो उन्हें (शीर्ष लेख में) इस टोकन की आवश्यकता होती है, अनुरोध को सत्यापित करने और निष्पादित करने के लिए सर्वर के लिए आदेश।

दूसरा भाग वह है जो विशेष रूप से सभी अनुरोधों के लिए एक सीएसआरएफ टोकन को संभालता है। जरूरत पड़ने पर इसे कुकी से पढ़ता है और हर अनुरोध के शीर्षक में लिखता है।

वांछित परिणाम कुछ इस तरह है:

प्रतिक्रिया निवेदन


यह उत्तर मौजूदा में क्या जोड़ता है?
पेम हाइजेन

2
एक वास्तविक कार्यान्वयन। जिस कारण से मैंने इसे पोस्ट करने का फैसला किया है, वह यह है कि मैं एक ही मुद्दे को खोजने और इसे महसूस करने के लिए विभिन्न पदों से टुकड़ों को जोड़ने में बहुत समय बिताता हूं। किसी के लिए ऐसा करना बहुत आसान होना चाहिए, इस पोस्ट की तुलना के रूप में।
स्टीफनोस कारगास

एनोटेशन allowCredentials = "true"में सेटिंग @CrossOriginदिखाने से मुझे मदद मिली।
ponder275

@lennylip ने अपने उत्तर में ऊपर उल्लेख किया है, यह samesite और सुरक्षित ध्वज के लिए त्रुटि दिखा रहा है। एक सुरक्षित ध्वज के बिना लोकलहोस्ट सर्वर के साथ इसे कैसे प्राप्त किया जाए।
निर्मल पटेल

2

एक्सप्रेस के लिए, अपनी एक्सप्रेस लाइब्रेरी को अपग्रेड करें 4.17.1जिसमें नवीनतम स्थिर संस्करण है। फिर;

CorsOption में: originअपने लोकलहोस्ट url या अपने frontend उत्पादन url और उदा credentialsको सेट करेंtrue

  const corsOptions = {
    origin: config.get("origin"),
    credentials: true,
  };

मैंने अपने एनपीएम मॉड्यूल का उपयोग करके गतिशील रूप से अपना मूल सेट किया ।

फिर, res.cookie में:

स्थानीय होस्ट के लिए: आप आप सेट कर सकते हैं, सभी में sameSite और सुरक्षित विकल्प सेट की जरूरत नहीं है httpOnlyकरने के लिए trueरोकें XSS हमले और अन्य उपयोगी होने के साथ-कुकी के लिए विकल्प आपके उपयोग के मामले पर निर्भर करता है।

उत्पादन के माहौल के लिए, आपको क्रॉस-ऑरिजनल रिक्वेस्ट और टू के लिए सेट sameSiteकरना होगा । याद रखें कि केवल नवीनतम संस्करण के साथ ही अब और नवीनतम क्रोम संस्करण के साथ काम करता है केवल कुकी सेट करें , इस प्रकार सुरक्षित विकल्प की आवश्यकता है।nonesecuretruesameSitehttps

यहां बताया गया है कि कैसे मैंने अपने को गतिशील बनाया

 res
    .cookie("access_token", token, {
      httpOnly: true,
      sameSite: app.get("env") === "development" ? true : "none",
      secure: app.get("env") === "development" ? false : true,
    })

0

पिम का जवाब बहुत मददगार है। मेरे मामले में, मुझे उपयोग करना होगा

Expires / Max-Age: "Session"

यदि यह एक तारीख का समय है, तो भी यह समाप्त नहीं हुआ है, यह अभी भी कुकी को बैकएंड पर नहीं भेजेगा:

Expires / Max-Age: "Thu, 21 May 2020 09:00:34 GMT"

आशा है कि यह भविष्य के लोगों के लिए मददगार हो, जो एक ही मुद्दे को पूरा कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.