如何使用 Axios 将 JWT 存储在 cookie 中?

Posted

技术标签:

【中文标题】如何使用 Axios 将 JWT 存储在 cookie 中?【英文标题】:How can I store a JWT in cookies using Axios? 【发布时间】:2019-07-06 06:05:01 【问题描述】:

我在我的 React 应用程序和 Axios 中使用 JWT 来处理 API 调用。我正在寻找一种将令牌存储在 cookie 中的方法,这样每次刷新浏览器时我都不会被重定向到再次登录。

这是我的 Axios 设置和我的登录调用:

let authToken = null; 

const axios = axiosAPI.create(
    baseURL: baseURL
);

// User login
export const loginUser = (data) => 
    return new Promise((resolve, reject) => 
        axios.post(`$baseURL/jwt-auth/v1/token`, data)
            .then((res) => 
                authToken = res.data.token;

                // Adds the token to the header
                axios.defaults.headers.common.Authorization = `Bearer $authToken`;

                resolve(res.data);
            )
            .catch((error) => 
                reject(error);
            );
    );
;

我不确定应该在哪里设置 cookie 以及如何设置它?

编辑:

我已经使用 js-cookie 重写了我的代码,所以它看起来像评论。

import axiosAPI from 'axios';
import Cookies from 'js-cookie';

let authToken = null;

const axios = axiosAPI.create(
    baseURL: `$baseURL`
);

// Check if user is logged in.
(function () 
    if (Cookies.get('token') === null) 
        // This means that there's no JWT and no user is logged in.
        axios.defaults.headers.common.Authorization = null;
     else 
        // This means that there's a JWT so someone must be logged in.
        axios.defaults.headers.common.Authorization = `Bearer $authToken`;
    
());

// User login
export const loginUser = (data) => 
    return new Promise((resolve, reject) => 
        axios.post(`$baseURL/jwt-auth/v1/token`, data)
            .then((res) => 
                authToken = res.data.token;

                Cookies.setToken('token', authToken);

                // Adds the token to the header
                axios.defaults.headers.common.Authorization = `Bearer $authToken`;

                resolve(res.data);
            )
            .catch((error) => 
                reject(error);
            );
    );
;

但是,这完全阻止了我登录,并且我收到错误“段数错误”。知道为什么这不起作用吗?

【问题讨论】:

您不能在 Ajax 调用中设置 cookie。看看我的老问题How to modify Cookie from Ajax call 【参考方案1】:

您可以在此处采用几个不同的选项来解决您遇到的问题,即简单地找到存储 JWT 的位置,以便您即使在刷新页面后也可以使用它。

    将 JWT 保存在您的 axios.post 回调中的 localStoragesessionStorage 中,以便您即使在页面刷新后也可以访问它。要了解哪种存储最适合您的应用,请参阅this。

    为了简短起见,存储在 localStorage 中的值将一直存在,直到您明确删除它们(您可以通过 JS 代码执行此操作)。此外,您在浏览器中打开到该域的任何选项卡都可以访问此域(如果您仍想使用新选项卡登录,这将非常有用)。另一方面,存储在 sessionStorage 中的值仅在选项卡关闭之前有效。它们也不能跨标签共享。

    使用它很简单:localStorage.setItem("JWT", authToken);sessionStorage.setItem("JWT", authToken); 在您的 authToken = res.data.token; 之后的回调中

    既然您已经有了存储 JWT 的位置,那么您需要做的就是确保在您的应用在页面加载(或刷新)时初始化时检查存储中是否存在 JWT。下面是一个如何使用 localStorage 的基本示例:

// This should be one of the first things that run on your app.

const axios = axiosAPI.create(
    baseURL: baseURL
);

// Check if user is logged in.
(function()  
  let authToken = localStorage.getItem("JWT");
  if (authToken === null) 
      // This means that there ISN'T JWT and no user is logged in.
      axios.defaults.headers.common.Authorization = null;
   else 
      // This means that there IS a JWT so someone must be logged in.
      axios.defaults.headers.common.Authorization = `Bearer $authToken`;
  
)();

这将确保用户不会在页面加载时退出(如果之前已登录)。

    将 JWT 保存在 客户端 cookie 中。在这里,cookie 被用作存储机制,因为您实际上并没有使用服务器端 cookie,因为您的身份验证都是围绕 JWT 构建的。您可以遵循与上述相同的代码模式,但将使用 document.cookie = "key=value" 设置 cookie 并使用 document.cookie 查看 所有 cookie。

    第二种方式不太常见,因为它迫使你做大量的体力劳动,比如解析所有的 cookie 并确保设置正确的cookie path 属性,以便只为所需的端点发送 cookie (否则你只是在创造不必要的开销)。如果您使用此选项,请阅读 this 以帮助您创建 cookie 以满足您的需求。 您还可以使用像 js-cookie 这样的辅助 JS 库来帮助操作客户端 cookie。

此外,我会通读 https://***.com/a/40376819/11048825 以进一步深入研究这两个选项,并了解每个选项的优缺点。

【讨论】:

尝试使用您的代码并使用 js-cookie 设置和获取 cookie。我已经编辑了原始帖子以显示我的新代码。知道为什么它不起作用吗? @G.Cox - 啊,我意识到我将Bearer $authToken 分配给页面加载时的axois 授权标头,而authToken 甚至没有在该匿名函数中定义。我已经纠正了我上面的错误。通过在匿名函数中的 if/else 语句之前执行 let authToken = Cookies.get('token'); 之类的操作,确保在代码中执行相同的操作。 @G.Cox - 此外,您的代码中还有另一个错字。而不是Cookies.setToken('token', authToken),应该是Cookies.set('token', authToken); 请勿使用 localStorage 或 sessionStorage 存储令牌,因为它们会暴露给 javascript,因此很容易受到跨站点脚本攻击。

以上是关于如何使用 Axios 将 JWT 存储在 cookie 中?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 vue 中存储、管理 REST API JWT 身份验证令牌?

如何使用 Node、Express、Axios 在 ReactJS 前端设置带有 JWT 令牌的 cookie

使用 Axios 发布请求的 JWT 授权

将 vuex 存储导入 axios 和 app.js 文件

在进行 ajax 调用时在 HTTP 标头中包含 JWT

如何在axios中配置授权承载令牌?