Tìm nạp API bằng Cookie


198

Tôi đang thử API Fetch mới nhưng gặp sự cố với Cookies. Cụ thể, sau khi đăng nhập thành công, có một tiêu đề Cookie trong các yêu cầu trong tương lai, nhưng Fetch dường như bỏ qua các tiêu đề đó và tất cả các yêu cầu của tôi được thực hiện với Fetch đều không được phép.

Có phải vì Fetch vẫn chưa sẵn sàng hoặc Fetch không hoạt động với Cookies?

Tôi xây dựng ứng dụng của mình với Webpack. Tôi cũng sử dụng Fetch trong React Native, không có vấn đề tương tự.

Câu trả lời:


279

Tìm nạp không sử dụng cookie theo mặc định. Để bật cookie, hãy làm điều này:

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

54
cùng nguồn gốc không còn hoạt động nữa, bao gồm (xem câu trả lời của @ Jerry): developers.google.com/web/updates/2015/03/int
sinhtion

7
@jpic: 'bao gồm' chỉ hoạt động cho các yêu cầu có nguồn gốc chéo, nhưng không hoạt động cho các yêu cầu cùng nguồn gốc. Tài liệu chính thức: github.com/github/fetch#seinating-cookies
Hold OfferHunger

Lý do sau đó để có cookie httponly là gì nếu chúng có thể đọc được trong js với fetch?
Martin Bajcar

4
Tôi tin rằng same-origin( vẫn không hoạt động) có nghĩa là nhiều tiêu đề sẽ được tôn trọng (cookie, v.v.) nhưng mã của bạn sẽ có quyền truy cập hạn chế vào phản hồi.
Bộ giải mã

2
@JohnBalvinAriasThx. Như sau này tôi đã hiểu, có cookie httponly có nghĩa là nó không thể đọc được document.cookie, nhưng vẫn có sẵn cho các yêu cầu ajax hoặc tìm nạp.
Martin Bajcar

183

Ngoài câu trả lời của @ Khanetor, cho những người đang làm việc với các yêu cầu nguồn gốc chéo: credentials: 'include'

Yêu cầu tìm nạp JSON mẫu:

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
Làm thế nào để bạn thiết lập cookie mặc dù?
pomo

2
Cookie được đặt từ phía máy chủ. Trong trường hợp của tôi, tôi đã sử dụng cookie httponly.
Khanetor

3
@Khanetor Tôi có thể đặt cookie bằng document.cookie bằng javascript, sau đó gửi yêu cầu không?
ospider

@ospider Bạn có thể gửi nó trong tiêu đề.
10101010

2
@ospider Tôi thấy rằng chỉ cần đặt giá trị trong document.cookielà đủ để nó được bao gồm trong các yêu cầu.
skwidbreth

35

Vừa giải quyết. Chỉ cần hai f. ngày tàn bạo

Đối với tôi, bí mật là như sau:

  1. Tôi đã gọi POST / api / auth và thấy rằng cookie đã được nhận thành công.

  2. Sau đó, gọi GET / api / users / with credentials: 'include'và nhận được 401 unauth, vì không có cookie nào được gửi cùng với yêu cầu.

Phím này cũng được đặt credentials: 'include'cho /api/authcuộc gọi đầu tiên .


1
Tôi có chính xác vấn đề của bạn. Cookie phiên không bao giờ được gửi theo yêu cầu dữ liệu GET. vì vậy 401. Tôi đã thử Axios và Fetch. cùng một kết quả. 2 khả năng: POST đăng nhập không lưu trữ cookie đã nhận hoặc dữ liệu GET sau đây không gửi cookie được lưu trữ
Rhubarb65

@ Rhubarb65, để giành chiến thắng này, bạn nên chỉ định credentials: 'include'cho người dùng đầu tiênPOST /api/auth
user1671599

Vâng, tôi đã có điều đó nhưng nó muốn đủ. Tôi sử dụng proxy devserver (ứng dụng khách http)
Rhubarb65

Vâng, tôi đã có thông tin nhưng nó không đủ. Tôi đã sử dụng proxy devserver để vượt qua CORS: (client http) - proxy - (máy chủ https). Tôi tin rằng điều này có nghĩa là cookie sessionid từ máy chủ không được đặt trong trình duyệt vì cookie an toàn yêu cầu https. Vì vậy, tôi đã thêm cờ https: true trong proxy devserver và nó đã sửa nó
Rhubarb65

1
Vâng chúc mừng. Câu trả lời của bạn có nghĩa là tôi chỉ mất 1 ngày bruteforce. :)
Michael

15

Nếu bạn đang đọc điều này vào năm 2019, credentials: "same-origin"là giá trị mặc định.

fetch(url).then

Nhưng lưu ý rằng không phải ai cũng sử dụng trình duyệt được cập nhật đầy đủ. Tôi đã gặp câu hỏi này bởi vì phiên bản Firefox của riêng tôi (60.x, phiên bản gần đây nhất trong Debian Stretch) không được đặt theo mặc định.
philh

2

Chỉ cần thêm vào các câu trả lời chính xác ở đây cho .net webapi2người dùng.

Nếu bạn đang sử dụng corsvì trang web khách của bạn được phục vụ từ một địa chỉ khác như địa chỉ của bạn webapithì bạn cũng cần đưa SupportsCredentials=truevào cấu hình phía máy chủ.

        // 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

Điều này làm việc cho tôi:

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

Sau đó, xây dựng cuộc gọi của bạn:

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)));
    };
  }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.