Ambil API dengan Cookie

199

Saya mencoba API Ambil baru tetapi mengalami masalah dengan Cookie. Secara khusus, setelah login berhasil, ada header Cookie di permintaan masa depan, tetapi Ambil tampaknya mengabaikan header itu, dan semua permintaan saya yang dibuat dengan Ambil tidak sah.

Apakah karena Pengambilan masih belum siap atau Pengambilan tidak bekerja dengan Cookie?

Saya membangun aplikasi saya dengan Webpack. Saya juga menggunakan Fetch in React Native, yang tidak memiliki masalah yang sama.

Khanetor
sumber

Jawaban:

279

Ambil tidak menggunakan cookie secara default. Untuk mengaktifkan cookie, lakukan ini:

fetch(url, {
  credentials: "same-origin"
}).then(...).catch(...);
Khanetor
sumber
55
sama-asal tidak berfungsi lagi, termasuk tidak (lihat jawaban @ Jerry): developers.google.com/web/updates/2015/03/introduction-to-fetch
jpic
7
@ jpic: 'sertakan' hanya berfungsi untuk permintaan lintas-asal, tetapi tidak untuk permintaan asal-sama. Dokumen resmi: github.com/github/fetch#sending-cookies
HoldOffHunger
Apa alasannya untuk memiliki cookie httpon jika dapat dibaca dalam js dengan mengambil?
Martin Bajcar
4
Saya percaya same-origin(yang tidak masih bekerja) berarti bahwa lebih header akan dihormati (cookies, dll) tapi kode Anda akan memiliki akses terbatas ke respon.
Coderer
2
@JohnBalvinAriasThx. Seperti yang saya pahami kemudian, memiliki cookie httpon berarti itu tidak dapat dibaca oleh document.cookie, tetapi masih tersedia untuk ajax atau mengambil permintaan.
Martin Bajcar
184

Selain jawaban @ Khanetor, bagi mereka yang bekerja dengan permintaan lintas-asal: credentials: 'include'

Contoh permintaan pengambilan 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

zurfyx
sumber
9
bagaimana Anda mengatur cookie?
pomo
2
Cookie diatur dari sisi server. Dalam kasus saya, saya menggunakan cookie httponly.
Khanetor
3
@Khanetor, bisakah saya mengatur cookie menggunakan document.cookie dengan javascript, dan kemudian mengirim permintaan?
ospider
@ospider Anda dapat mengirimnya di header.
10101010
2
@ospider, saya menemukan bahwa hanya pengaturan nilai document.cookiesudah cukup untuk dimasukkan dalam permintaan.
skwidbreth
35

Baru saja dipecahkan. Hanya dua f. hari-hari brutforce

Bagi saya rahasianya adalah sebagai berikut:

  1. Saya menelepon POST / api / auth dan melihat bahwa cookie berhasil diterima.

  2. Kemudian memanggil GET / api / pengguna / dengan credentials: 'include'dan mendapat 401 tidak sah, karena tidak ada cookie yang dikirim dengan permintaan.

KUNCI untuk mengatur panggilan credentials: 'include'pertama /api/authjuga.

pengguna1671599
sumber
1
Saya punya masalah persis Anda. Cookie sesi tidak pernah dikirim pada permintaan data GET. jadi 401. Saya sudah mencoba Axios dan Fetch. hasil yang sama. 2 kemungkinan: POST login tidak menyimpan cookie yang diterima atau data GET berikut tidak mengirim cookie yang disimpan
Rhubarb65
@ Rhubarb65, untuk memenangkan ini kamu harus menentukan credentials: 'include'untuk yang pertamaPOST /api/auth
user1671599
Ya, saya sudah memilikinya tetapi cukup ingin. Saya menggunakan proxy devserver (client Http)
Rhubarb65
Ya, saya memiliki kredensial tetapi itu tidak cukup. Saya menggunakan proxy devserver untuk melewati CORS: (klien http) - proxy - (server https). Saya percaya ini berarti bahwa cookie sessionid dari server tidak disetel di browser karena cookie aman memerlukan https. Jadi saya menambahkan flag https: true di proxy devserver dan memperbaikinya
Rhubarb65
1
Bersorak sorai. Jawaban Anda berarti hanya butuh saya 1 hari bruteforce. :)
Michael
16

Jika Anda membaca ini di 2019, credentials: "same-origin"adalah nilai default.

fetch(url).then
alextrastero
sumber
1
Tetapi perhatikan bahwa tidak semua orang menggunakan browser yang cukup diperbarui. Saya menemukan pertanyaan ini karena versi Firefox saya sendiri (60.x, yang terbaru di Debian Stretch) tidak menetapkan itu secara default.
philh
2

Hanya menambahkan jawaban yang benar di sini untuk .net webapi2pengguna.

Jika Anda menggunakan corskarena situs klien Anda dilayani dari alamat yang berbeda dengan Anda, webapimaka Anda juga perlu memasukkan SupportsCredentials=truepada konfigurasi sisi server.

        // 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);
Mark Dornian
sumber
0

Ini bekerja untuk saya:

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;
}

Kemudian buat panggilan Anda:

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)));
    };
  }
aarkerio
sumber