jwt刷新后req.user丢失数据

Posted

技术标签:

【中文标题】jwt刷新后req.user丢失数据【英文标题】:req.user losing data after jwt refresh 【发布时间】:2021-04-13 15:31:52 【问题描述】:

首先让我提供所有相关代码,然后我将解释我的问题

我的中间件来验证 jwt

module.exports.authenticateToken = (req, res, next) => 
  const authHeader = req.headers["authorization"];
  const token = authHeader && authHeader.split(" ")[1];

  if (!token) 
    return res.status(401).json( success: false, msg: "not authorized" );
  

  jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, (err, user) => 
    if (err) 
      return res
        .status(403)
        .json( success: false, msg: "jwt cannot be verified" );
    
    req.user = user;
    next();
  );
;

生成访问和刷新令牌的代码

module.exports.generateAccessToken = (user) => 
  const payload = 
    sub: user._id,
    name: user.username,
  ;

  return jwt.sign(payload, process.env.ACCESS_TOKEN_SECRET, 
    expiresIn: "20s",
  );
;

module.exports.generateRefreshToken = (user) => 
  const payload = 
    sub: user._id,
    name: user.username,
  ;

  return jwt.sign(payload, process.env.REFRESH_TOKEN_SECRET);

这就是用户登录时发生的情况(我将刷新令牌存储在数组 rn 中,当我让所有这些正常工作时,我会更改它)

module.exports.postAuthLogin = async (req, res) => 
  const  username, password  = req.body;

  try 
    const user = await User.findOne( username );

    if (!user) 
      return res.status(401).json( success: false, msg: "Invalid username" );
    

    const passwordIsValid = validatePasswordHash(
      password,
      user.salt,
      user.hash
    );

    if (!passwordIsValid) 
      return res.status(401).json( success: false, msg: "Invalid password" );
    

    const accessToken = generateAccessToken(user);
    const refreshToken = generateRefreshToken(user);

    refreshTokens.push(refreshToken);
    res.status(200).json( success: true, accessToken, refreshToken );
   catch (err) 
    return res.json( msg: err.toString() );
  
;

最后,这是当用户请求刷新令牌时运行的内容

module.exports.postAuthRefreshToken = (req, res) => 
  const  refreshToken  = req.body;

  if (!refreshToken) 
    return res
      .status(401)
      .json( success: false, msg: "must provide a refresh token" );
  

  if (!refreshTokens.includes(refreshToken)) 
    return res.status(403).json(
      success: false,
      msg: "refresh token was deleted you must login again",
    );
  

  jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) => 
    const accessToken = generateAccessToken(user);
    res.status(200).json( success: true, accessToken );
  );
;

所以我的问题最初是当我登录并获取刷新和访问令牌时,然后我请求一个受 authenticateToken 中间件保护的路由,我在该路由中的 req.user 看起来像这样


  sub: '5ff5f16f4203ade4d1b63da8',
  name: 'test1',
  iat: 1610055109,
  exp: 1610055129

但是当我的令牌过期并且我请求一个新令牌时,它确实得到验证并且我能够访问受保护的路由但是我的 req.user 看起来像这样

 iat: 1610055143, exp: 1610055163 

我已经为这个问题苦苦挣扎了一段时间,所以任何帮助都将不胜感激,如果您需要更多信息,只需说点什么,生病 100% 提供它

【问题讨论】:

【参考方案1】:

问题来了

jwt.verify(refreshToken, process.env.REFRESH_TOKEN_SECRET, (err, user) => 
    const accessToken = generateAccessToken(user);
    res.status(200).json( success: true, accessToken );
  );

“用户”实际上是解码后的有效载荷


  sub: '5ff5f16f4203ade4d1b63da8',
  name: 'test1',
  iat: 1610055109,
  exp: 1610055129

然后您将其传递给 generateAccessToken 并尝试访问未定义的字段 _id 和用户名。

您可以将有效负载字段更改为


  _id: '5ff5f16f4203ade4d1b63da8',
  username: 'test1',
  iat: 1610055109,
  exp: 1610055129

因此,当传递解码后的有效负载时,它仍然具有相同的字段名称。 或者您可以使用 payload.sub 再次从 DB 中获取用户,然后将用户传递给 generateAccessToken。

【讨论】:

OHHHHH,我明白了,谢谢你,当我看到用户时,我立刻想到,由于某种原因,它会拥有我的用户应该拥有的所有正常字段。我会重构它,但谢谢

以上是关于jwt刷新后req.user丢失数据的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS Express req[user] 在多次刷新时未定义

用户权限更改后 JWT 刷新

使用刷新令牌对 JWT 的端点 /logout 执行的操作

过期后使用刷新令牌获取访问令牌(JWT)

Django REST JWT 刷新

vue: 解决vuex页面刷新数据丢失问题