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

Posted

技术标签:

【中文标题】如何使用 Node、Express、Axios 在 ReactJS 前端设置带有 JWT 令牌的 cookie【英文标题】:How to set cookie with JWT token in ReactJS frontend using Node, Express, Axios 【发布时间】:2021-08-24 05:24:56 【问题描述】:

所以我可以使用邮递员成功地将访问令牌放入 cookie 并且验证工作正常,但是在我的前端登录时,访问令牌没有放入 cookie

这是我的路由/Users.js

router.post('/login', async (req, res) => 
    const  username, password  = req.body;

    const user = await Users.findOne( where: username: username);

    if(!user) res.status(400).json(error: `Username does not exist!`);

    bcrypt.compare(password, user.password).then((match) => 
        if(!match) res.status(400).json(error: 'Wrong password!')

        const accessToken = createTokens(user);

        res.cookie('access-token', accessToken, 
            maxAge: 60*60*24*30*1000, //30 days
            secure: false,
            httpOnly: false
        );

        user.password = undefined;

        res.json(accessToken);
    )
);

控制器/jwt.js

const  sign, verify  = require('jsonwebtoken');

const createTokens = (user) => 
    const accessToken = sign(
         username: user.username, id: user.user_id , 
        'e2ereactsecret'
    );
    return accessToken;
;

const validateToken = (req, res, next) => 
    const accessToken = req.cookies['access-token']

    if (!accessToken) 
        return res.status(400).json(error: 'User not authenticated!')

    try 
         const validToken = verify(accessToken, 'e2ereactsecret')
         if(validToken) 
            req.authenticated = true
            return next();
         
     catch(err) 
        return res.status(400).json(error: err)
    
;

module.exports =  createTokens, validateToken ;

这是我的反应前端中的登录功能:

    const login = (e) => 
        e.preventDefault();

        const config =  headers: "Content-Type":"application/json";
        const data =  username: username, password: password ;
        axios.post('http://localhost:4000/users/login', data, config).then((res) => 
            console.log(res);
          );
    

这是我通过 console.log 得到的,令牌在那里,但它没有进入 cookie。

data: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZ…DYzfQ.dm1nUa-9z7AQkvirCTM3jrC9a_mx_hsA2waDqQs3cD8", status: 200, statusText: "OK", headers: …, config: …, …
config: url: "http://localhost:4000/users/login", method: "post", data: "\"username\":\"juan\",\"password\":\"password123\"", headers: …, transformRequest: Array(1), …
data: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6Imp1YW4iLCJpZCI6MiwiaWF0IjoxNjIzMDM0NDYzfQ.dm1nUa-9z7AQkvirCTM3jrC9a_mx_hsA2waDqQs3cD8"
headers: content-length: "141", content-type: "application/json; charset=utf-8"
request: XMLHttpRequest readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, onreadystatechange: ƒ, …
status: 200
statusText: "OK"
__proto__: Object

我现在真的很困惑。哈哈。

【问题讨论】:

【参考方案1】:

您的后端和前端位于两个不同的域中,每个域分别存储其 cookie。

在 React 中存储 cookie,可以使用 vanilla js 的方式:

const login = (e) => 
    e.preventDefault();

    const config =  headers: "Content-Type":"application/json";
    const data =  username: username, password: password ;
    axios.post('http://localhost:4000/users/login', data, config).then((res) => 
        document.cookie = "token=" + res./*token location*/
        console.log(res, document.cookie);
      );

您可以通过https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie了解更多关于这种方式的信息

还有一些库也可以为您执行此操作。 react-cookie 和 Universal-cookie 是两个。

【讨论】:

我认为从react中设置cookie是违背将jwt放在cookie中的目的,当你在cookie中使用jwt时你应该将它设置为httpOnly,也就是说js不能访问它跨度> 【参考方案2】:

尝试将 httpOnly 设置更改为 true。

httpOnly 设置意味着无法使用 javascript 读取 cookie,但仍可以在 HTTP 请求中将其发送回服务器。如果没有此设置,XSS 攻击可能会使用 document.cookie 来获取存储的 cookie 及其值的列表。

【讨论】:

以上是关于如何使用 Node、Express、Axios 在 ReactJS 前端设置带有 JWT 令牌的 cookie的主要内容,如果未能解决你的问题,请参考以下文章

Node.js与Express联合中间件express-fileupload使用axios实现文件上传

与 react、express、axios、node 和 mysql 相关的 CORS 问题

Node 中 express.js 和 axios.js 的区别

上传图片文件到服务器node.js express axios

一:练手的项目简介(node express vue elementui axios)

如何在 Node-Express / Vue Web 应用程序中管理 OAuth?