ดึง API ด้วยคุกกี้


201

ฉันกำลังลอง API การดึงข้อมูลใหม่ แต่มีปัญหากับคุกกี้ หลังจากเข้าสู่ระบบสำเร็จจะมีส่วนหัวของคุกกี้ในคำขอในอนาคต แต่การดึงข้อมูลดูเหมือนจะไม่สนใจส่วนหัวนั้นและคำขอทั้งหมดของฉันที่ทำด้วยการดึงข้อมูลนั้นไม่ได้รับอนุญาต

เป็นเพราะการดึงข้อมูลยังไม่พร้อมหรือการดึงข้อมูลไม่ทำงานกับคุกกี้

ฉันสร้างแอปของฉันด้วย Webpack ฉันยังใช้ Fetch ใน React Native ซึ่งไม่มีปัญหาเดียวกัน

คำตอบ:


280

การดึงข้อมูลไม่ได้ใช้คุกกี้เป็นค่าเริ่มต้น หากต้องการเปิดใช้งานคุกกี้ให้ทำดังนี้

fetch(url, {
  credentials: "same-origin"
}).then(...).catch(...);

55
แหล่งกำเนิดเดียวกันไม่ทำงานอีกต่อไปรวมถึง (ดูคำตอบของ @ Jerry): developers.google.com/web/updates/2015/03/introduction-to-fetch
jpic

7
@jpic: 'รวม' ใช้งานได้เฉพาะกับคำขอข้ามที่มา แต่ไม่ใช้สำหรับคำขอที่มาดั้งเดิม เอกสารอย่างเป็นทางการ: github.com/github/fetch#sending-cookies
HoldOffHunger

อะไรคือเหตุผลที่จะมีคุกกี้แบบ httponly หากพวกเขาสามารถอ่านได้ใน js ด้วยการดึงข้อมูล?
Martin Bajcar

4
ผมเชื่อว่าsame-origin(ซึ่งจะยังคงทำงาน) หมายความว่าส่วนหัวมากขึ้นจะได้รับการเคารพ (คุกกี้ ฯลฯ ) แต่รหัสของคุณจะมีการ จำกัด การเข้าถึงการตอบสนอง
Coderer

2
@JohnBalvinAriasThx ดังที่ฉันเข้าใจในภายหลังการมีคุกกี้ httponly หมายความว่าไม่สามารถอ่านได้document.cookieแต่ยังสามารถใช้งานได้กับ ajax หรือดึงคำขอ
Martin Bajcar

186

นอกจากคำตอบของ @ Khanetor สำหรับผู้ที่ทำงานกับคำขอข้ามสายงาน: credentials: 'include'

ตัวอย่างคำขอเรียก JSON:

fetch(url, {
  method: 'GET',
  credentials: 'include'
})
  .then((response) => response.json())
  .then((json) => {
    console.log('Gotcha');
  }).catch((err) => {
    console.log(err);
});

https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials


9
คุณตั้งค่าคุกกี้อย่างไร
pomo

2
คุกกี้ถูกตั้งค่าจากฝั่งเซิร์ฟเวอร์ ในกรณีของฉันฉันใช้คุกกี้ httponly
Khanetor

3
@Khanetor ฉันสามารถตั้งค่าคุกกี้โดยใช้ document.cookie โดย javascript แล้วส่งคำขอได้หรือไม่
ospider

@ospider คุณสามารถส่งได้ที่ส่วนหัว
10101010

2
@ospider ฉันพบว่าเพียงแค่ตั้งค่าในdocument.cookieก็เพียงพอที่จะรวมไว้ในคำขอ
skwidbreth

36

เพิ่งได้รับการแก้ไข เพียงสองฉ วันแห่งความโหดร้าย

สำหรับฉันความลับมีดังต่อไปนี้:

  1. ฉันโทร POST / api / auth และดูว่าได้รับคุกกี้เรียบร้อยแล้ว

  2. จากนั้นโทรหา GET / api / users / ด้วยcredentials: 'include'และได้รับ 401 unauth เนื่องจากไม่มีการส่งคุกกี้ใด ๆ มาพร้อมกับคำขอ

KEY คือการตั้งค่าcredentials: 'include'สำหรับการ/api/authโทรครั้งแรกเกินไป


1
ฉันมีปัญหาของคุณอย่างแน่นอน คุกกี้เซสชันจะไม่ถูกส่งไปยังคำขอข้อมูล GET ดังนั้น 401. ฉันได้ลอง Axios และ Fetch แล้ว ผลลัพธ์เดียวกัน 2 ความเป็นไปได้: POST เข้าสู่ระบบไม่เก็บคุกกี้ที่ได้รับหรือข้อมูล GET ต่อไปนี้ไม่ได้ส่งคุกกี้ที่เก็บไว้
Rhubarb65

@ Rhubarb65 เพื่อที่จะได้รับรางวัลนี้คุณควรระบุcredentials: 'include'ไว้ก่อนPOST /api/auth
user1671599

ใช่ฉันมีมัน แต่มันก็เพียงพอแล้ว ฉันใช้พร็อกซี devserver (ไคลเอนต์ Http)
Rhubarb65

ใช่ฉันมีหนังสือรับรอง แต่ก็ไม่เพียงพอ ฉันใช้พร็อกซี devserver เพื่อรับ CORS ที่ผ่านมา: (ไคลเอ็นต์ http) - พร็อกซี - (เซิร์ฟเวอร์ https) ฉันเชื่อว่านี่หมายความว่าคุกกี้ sessionid จากเซิร์ฟเวอร์ไม่ได้ถูกตั้งค่าในเบราว์เซอร์เนื่องจากคุกกี้ที่ปลอดภัยต้องใช้ https ดังนั้นฉันจึงเพิ่มการตั้งค่าสถานะ https: จริงในพร็อกซีเซิร์ฟเวอร์ devserver และแก้ไขมัน
Rhubarb65

1
ไชโย คำตอบของคุณหมายความว่าใช้เวลาเพียงวันเดียวกับฉันในการดุร้าย :)
ไมเคิล

16

หากคุณกำลังอ่านสิ่งนี้ในปี 2019 credentials: "same-origin"เป็นค่าเริ่มต้น

fetch(url).then

1
แต่โปรดทราบว่าไม่ใช่ทุกคนที่ใช้เบราว์เซอร์ที่อัปเดตอย่างเพียงพอ ฉันเจอคำถามนี้เพราะ Firefox รุ่นของฉัน (60.x ล่าสุดใน Debian Stretch) ไม่ได้ตั้งค่าไว้ตามค่าเริ่มต้น
philh

2

เพียงเพิ่มคำตอบที่ถูกต้องที่นี่สำหรับ.net webapi2ผู้ใช้

หากคุณกำลังใช้งานcorsเนื่องจากเว็บไซต์ลูกค้าของคุณให้บริการจากที่อยู่อื่นเป็นของwebapiคุณคุณจะต้องรวมSupportsCredentials=trueอยู่ในการกำหนดค่าฝั่งเซิร์ฟเวอร์

        // Access-Control-Allow-Origin
        // https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
        var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
        cors.SupportsCredentials = true;
        config.EnableCors(cors);

0

สิ่งนี้ใช้ได้กับฉัน:

import Cookies from 'universal-cookie';
const cookies = new Cookies();

function headers(set_cookie=false) {
  let headers = {
    'Accept':       'application/json',
    'Content-Type': 'application/json',
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
    headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}

จากนั้นสร้างสายของคุณ:

export function fetchTests(user_id) {
  return function (dispatch) {
   let data = {
    method:      'POST',
    credentials: 'same-origin',
    mode:        'same-origin',
    body:        JSON.stringify({
                     user_id: user_id
                }),
    headers:     headers(true)
   };
   return fetch('/api/v1/tests/listing/', data)
      .then(response => response.json())
      .then(json => dispatch(receiveTests(json)));
    };
  }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.