【问题标题】:Fetch API with Cookie使用 Cookie 获取 API
【发布时间】:2016-04-06 02:59:14
【问题描述】:

我正在试用新的 Fetch API,但遇到了 Cookie 问题。具体来说,在成功登录后,以后的请求中有一个 Cookie 标头,但 Fetch 似乎忽略了该标头,并且我使用 Fetch 发出的所有请求都是未经授权的。

是因为 Fetch 还没有准备好还是 Fetch 不能使用 Cookie?

我使用 Webpack 构建我的应用程序。我也在 React Native 中使用了 Fetch,它没有同样的问题。

【问题讨论】:

    标签: cookies fetch-api


    【解决方案1】:

    Fetch 默认不使用 cookie。要启用 cookie,do this:

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

    【讨论】:

    • same-origin 不再起作用,include 起作用(见@Jerry 的回答):developers.google.com/web/updates/2015/03/introduction-to-fetch
    • @jpic: 'include' 仅适用于跨域请求,不适用于同源请求。官方文档:github.com/github/fetch#sending-cookies
    • 我相信same-origin(这确实仍然有效)意味着将尊重更多的标头(cookie 等),但您的代码将有限地访问响应。
    • @MartinBajcar 参数 "credentials" 在 fetch 中没有读取任何 cookie,它只是作为一扇门,如果打开(credentials: 'include'),cookie 将允许通过,如果没有打开则他们不是。
    • @JohnBalvinAriasThx。正如我后来理解的那样,拥有 cookie httponly 意味着 document.cookie 无法读取它,但仍可用于 ajax 或 fetch 请求。
    【解决方案2】:

    除了@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

    【讨论】:

    • 你如何设置cookie?
    • cookie 是从服务器端设置的。就我而言,我使用的是 httponly cookie。
    • @Khanetor 我可以通过javascript使用document.cookie设置cookie,然后发送请求吗?
    • 有趣的事实:我想通过使用它来涵盖同源和跨源获取的两种情况,但我做不到,但它确实适用于跨源请求。 =)
    • @ospider 我发现只需在document.cookie 中设置值就足以将其包含在请求中。
    【解决方案3】:

    刚刚解决了。只有两个f。蛮力的日子

    对我来说,秘诀在于:

    1. 我调用了 POST /api/auth,发现 cookie 已成功接收。

    2. 然后使用 credentials: 'include' 调用 GET /api/users/ 并获得 401 unauth,因为请求中没有发送任何 cookie。

    关键是也为第一个/api/auth调用设置credentials: 'include'

    【讨论】:

    • 我有你的问题。会话 cookie 永远不会在 GET 数据请求中发送。所以401。我试过Axios和Fetch。同样的结果。 2种可能:登录POST不存储接收到的cookie或者后面的GET数据不发送存储的cookie
    • @Rhubarb65,要赢得这场比赛,你应该指定credentials: 'include' 作为第一个POST /api/auth
    • 干杯。您的回答意味着我只用了 1 天的蛮力。 :)
    • 我欠你一大瓶肥啤酒。在过去的 3 个小时里,我一直在用头撞桌子,试图解决这个问题。谢谢你 x1000。
    • 另外,别做我。确保获取 URL 是 127.0.0.1 而不是 localhost,否则不会设置 Cookie。
    【解决方案4】:

    如果您在 2019 年阅读本文,credentials: "same-origin" 是默认值。

    fetch(url).then
    

    【讨论】:

    • 但请注意,并非每个人都在使用足够更新的浏览器。我遇到这个问题是因为我自己的 Firefox 版本(60.x,Debian Stretch 中的最新版本)没有默认设置。
    【解决方案5】:

    只需在此处为.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);
    

    【讨论】:

    • 'cors.SupportsCredentials = true;'拯救了我的一天,谢谢。
    【解决方案6】:

    在浏览器端以编程方式覆盖 Cookie 标头不起作用

    fetch 文档中,提到了Note that some names are forbidden.。而Cookie 恰好是被禁止的标头名称之一,不能以编程方式对其进行修改。以如下代码为例:

    • 在页面https://httpbin.org/的Chrome DevTools控制台中执行,Cookie: 'xxx=yyy'将被忽略,如果有document.cookie的值,浏览器将始终作为cookie发送。
    • 如果在不同的来源上执行,则不会发送任何 cookie。
    fetch('https://httpbin.org/cookies', {
      headers: {
        Cookie: 'xxx=yyy'
      }
    }).then(response => response.json())
    .then(data => console.log(JSON.stringify(data, null, 2)));
    

    附:您可以通过在 chrome 浏览器中打开 https://httpbin.org/cookies/set/foo/bar 来创建示例 cookie foo=bar

    详情请见Forbidden header name

    【讨论】:

      【解决方案7】:

      我的问题是我的 cookie 设置在特定的 URL 路径上(例如,/auth),但我是 fetching 到不同的路径。我需要将我的 cookie 的 path 设置为 /

      【讨论】:

        【解决方案8】:

        这对我有用:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-14
          • 2021-06-13
          • 2018-11-14
          • 2017-04-28
          • 1970-01-01
          相关资源
          最近更新 更多