如何从 JWT 令牌中获取用户 ID

Posted

技术标签:

【中文标题】如何从 JWT 令牌中获取用户 ID【英文标题】:How to get user id from JWT token 【发布时间】:2021-07-05 17:11:16 【问题描述】:

我正在尝试获取用户 ID,以便我可以在 mongoose 中连接模型并跟踪每个用户发布的内容。但为了做到这一点,我需要从 jwt 令牌中获取用户 ID,但我不知道如何。 这是一个 MERN 应用程序,我试图从 react 中获取 id,但没有成功。这是我的代码:

使用 jwt 进行身份验证

const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const util = require("util");

const passwordHash = require("../../config/passwordHash")
//get middleware
const authenticateUser = require("../middleware/authenticateUser");
const validateBodyWith = require("../middleware/validateUserWith");

//data validators
const  loginValidator, registerValidator  = require("../validation");
//load User model
const  User  = require("../../models");

const jwtSign = util.promisify( jwt.sign );

//get currently validated user
router.post("/authenticated", authenticateUser, (req,res)=>
  // console.log(req.user);
  res.json(req.user);
);

 //log in an existent user by signing and returning a secure json web token
 // for the client application to store and include with requests

router.post("/login", validateBodyWith(loginValidator), async(req,res)=>
 
  const email,password = req.body;
  console.log(req.body);

  try
    const user = 
      await User
      .findOne(email)
      // .populate('records');
    if(!user)
      //user not found by email
      return res.status(404).json(default:"your email or password is invalid")
    
  
    const 
      password: encryptedPassword,
      // User object without the password
      ...secureUser
     = user._doc;
    console.log("user----:",secureUser)

    const isMatch = await bcrypt.compare( password, encryptedPassword );
    
    if( !isMatch ) 
      // User's password is invalid.
      return res.status(404).json( default: "Email or password is invalid." );
    

    const payload = 
      id:secureUser._id,
      email:secureUser.email
    ;
    console.log(payload);
    //create a signed web token to send back to the client for reauthentication
    const token =  await jwtSign(
      payload,
      process.env.JWT_SECRET,
      
        expiresIn:31556926 //one year in seconds
      
    );

    return res.json(
      sucess:true,
      token: "Bearer " + token,
      user:secureUser
    )
  catch(err)

    console.log(err);
    res.status(500).json(default:"something went wrong trying to log in ")
  

);

// creates a new user for authentication 

router.post("/register", validateBodyWith(registerValidator), async(req,res)=>
  console.log(req.body)
  try
    const  name, email, password  = req.body;

    const user = await User.findOne( email );

    if (user) 
      // User already exists error.
      return res.status(400).json( email: "Email already exists." );
    

    const newUser = new User(
      name,
      email,
      password: await passwordHash( password )
    );

    await newUser.save();

    const 
      password: encryptedPassword,
      // User object without the password
      ...secureUser
     = newUser._doc;

    res.json( secureUser );

  catch(err)
    console.log(err);
    res.status(500).json( default: "Something went wrong creating your account." );

  

);
module.exports = router; 

中间件:

const passport = require('passport');

const authenticateUser = passport.authenticate('jwt',session:false);

module.exports = authenticateUser;
const mapValidationErrors = errors => errors.reduce( (errors, field, message) => ( ...errors, [field]: message ),  );

const validateBodyWith = validator => ( req, res, next ) => 

    const result = validator( req.body );

    // Body data valid! Continue to the next step...
    if( true === result ) return next();

    // Validation failed! Send and error response.
    res.status(400).json( mapValidationErrors(result) );



module.exports = validateBodyWith;
const validatorFactory = require("./validatorFactory");

const loginValidator = validatorFactory(
  email:  type: "email" ,
  password:  type: "string", empty: false 
);

module.exports = loginValidator;
const validatorFactory = require("./validatorFactory");

const registerValidator = validatorFactory(
  name:type:"string", empty:false,
  email:  type: "email" ,
  password:  type: "string", empty: false 
  
);

module.exports = registerValidator;
const Validator = require("fastest-validator");
const   ObjectID  = require("mongodb");

const v = new Validator(
  defaults: 
      objectID: 
          ObjectID
      
  
);

const validatorFactory = schema => v.compile(
  $$strict: "remove",
  ...schema
);

module.exports = validatorFactory;

【问题讨论】:

【参考方案1】:

如果你使用护照,那么你的用户ID可以从req.user.id检索到

我建议您详细阅读@http://www.passportjs.org/packages/passport-jwt/,因为您可以将 JWT 代码从授权标头或 cookie 从客户端传递到服务器端。

在请求中包含 JWT

策略会先检查请求 用于标准授权标头。如果此标头存在并且 如果没有身份验证方案,则方案匹配 options.authScheme 或 'JWT' 指定,则将从中检索令牌。例如

授权:JWT JSON_WEB_TOKEN_STRING..... 如果授权 未找到具有预期方案的标头,请求正文将是 检查与 options.tokenBodyField 或匹配的字段 如果未指定选项,则为 auth_token。

最后,将检查 URL 查询参数是否匹配字段 options.tokenQueryParameterName 或 auth_token 如果选项是 未指定。

【讨论】:

以上是关于如何从 JWT 令牌中获取用户 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jwt 令牌获取用户 ID

如何使用 jwt 令牌获取用户 ID

如何从 Node.js 中的 jwt 令牌获取 user.id?

Laravel,如何从自定义表的 jwt 令牌获取登录用户

如何从 jwt 令牌获取确切的用户以及用户在 laravel 中的确切帖子

如何从.Net Core API 中的身份验证 JWT 令牌中获取身份用户?