Use jsonwebtoken to implement identity authentication in node

In modern webapplications, user authentication is a very important and indispensable part. The use Node.jsand Expressframework can easily implement user identity authentication. In the process, jsonwebtokenthis JWTprotocol-based module can help us implement a safe and reliable authentication mechanism, allowing us to easily generate, parse and verify JWT. This article mainly introduces how to use modules in the framework Node.jsto implement user authentication.Expressjsonwebtoken

1. What is jwt

jwt introduction : https://restfulapi.cn/jwt

JWT( JSON Web Token) is an JSONopen standard based on , for transmitting claims over the web in a secure manner . JWTTypically used for authentication and authorization . It is a self-contained authentication mechanism consisting ofthree parts: header, payload and signature . JWTThe header and payload are encoded Base64strings JSON, and the signature is a string calculated by hashing the header and payload using a key. JWTIt can be transmitted between the client and the server, and the data can be protected from tampering during transmission. Since it is stateless, it simplifies Webapplication development and maintenance.
insert image description here

2. Basic use of jsonwebtoken

jsonwebtokenis a Node.jslibrary for creating, decoding and validating JWTtokens ( JSON Web Tokens). In Webapplications, these tokens are typically used for authentication and authorization .

Here are the basic steps how to use Node.jsin the app .jsonwebtoken

1. Install jsonwebtoken

First, you need to add the jsonwebtoken package to your project using npm or yarn:

npm install jsonwebtoken --save

or

yarn add jsonwebtoken

2. Import and use

Then, import jsonwebtoken in your code:

const jwt = require('jsonwebtoken');

3. Create a token

Create a token:

let token = jwt.sign({
    
     foo: 'bar' }, 'shhhhh');

In the above code, we jwt.signcreated a new token using method.
This method requirestwo parameters

  • An object containing your payload(the data in this object will be encoded into the generated token) such as: userInfo,
  • The secret string used to sign tokens .

4. Verify the token

Verify a token:

jwt.verify(token, 'shhhhh', (err, decoded) => {
    
    
  if (err) {
    
    
    // 处理错误
  } else {
    
    
    // 使用解码后的令牌数据
  }
});

Use jwt.verifymethods to decode and verify a token.

The method requiresthree parameters

  • decoded token ,
  • the same secret string used for signing ,
  • Callback function to be called when the operation completes .

Notice

  • All tokens should be HTTPSsent via-only to prevent interception.

  • The secret string should remain private within your application and not be known by others.

  • Any information stored in the token can be decoded by anyone with the secret. Therefore, you should never store sensitive information (such as passwords or bank account information) in tokens .

3. Application example in express

In actual projects, we can use jsonwebtokenmodules to implement identity authentication. jsonwebtokenIs JSON Web Tokens(JWT)a protocol-based implementation module that can be used for generation, parsing, and verification JWT. JWTis an JSONopen standard based on (RFC 7519), for the secure transmission of claims over the web.

Here is an example of using expressand jsonwebtokenimplementing authentication:

const express = require('express');
const jwt = require('jsonwebtoken');

const app = express();

// 定义一个中间件函数,用于身份认证
function verifyToken(req, res, next) {
    
    
  // 从请求头中获取token
  const token = req.headers['authorization'];
  if (!token) {
    
    
    return res.status(401).send({
    
    
      auth: false,
      message: 'No token provided.'
    });
  }

  // 验证token是否有效
  jwt.verify(token, process.env.SECRET_KEY, (err, decoded) => {
    
    
    if (err) {
    
    
      return res.status(500).send({
    
    
        auth: false,
        message: 'Failed to authenticate token.'
      });
    }

    // 将解码的用户信息存储到请求对象中
    req.userId = decoded.id;
    next();
  });
}

// 定义一个路由,需要身份认证
app.get('/api/protected', verifyToken, (req, res, next) => {
    
    
  // 返回受保护的数据
  res.status(200).send({
    
    
    message: 'Access granted.'
  });
});

// 定义一个路由,用于登录,返回token
app.post('/api/login', (req, res, next) => {
    
    
  // 从数据库中获取用户信息
  const user = {
    
     id: 123 };

  // 生成token
  const token = jwt.sign({
    
     id: user.id }, process.env.SECRET_KEY, {
    
    
    expiresIn: 60 * 60 // token有效期为1小时
  });

  // 返回token
  res.status(200).send({
    
    
    auth: true,
    token: token
  });
});

// 启动服务器,监听端口
app.listen(3000, () => {
    
    
  console.log('Server started on port 3000');
});

In the above example, we defined a middleware function verifyTokenfor authentication. This function is obtained from the request header tokenand jsonwebtoken的verifyvalidated by the method token. If the verification is passed, the user information will be stored in the request object for subsequent routing functions to use.

We also define two routing functions, /api/protectedand /api/login. /api/protectedAuthentication is required to access, and /api/loginit is used for login, and the generated one is returned token.

In actual projects, we should SECRET_KEYput such sensitive information as environment variables to improve security. In addition, we can also use jsonwebtokenother functions provided, such as verified tokensignature algorithm, payloadand headerother information.

Four, jwt logic extraction

In the above example, we use jwt to implement identity authentication, but this is only authenticated in one interface. If there are more interfaces, do we have to add this authentication middleware every time? In this way, not to mention whether the development and implementation are tiring or redundant, it is also very unreasonable from the perspective of maintenance. Therefore, we should extract the authentication logic to facilitate interface calling and maintenance. Specific steps are as follows:

1. Create a new jwt.js file

This file encapsulates three functions

  • token generation
  • token authentication
  • Exclude which interfaces can be accessed without authentication, for example /login,
// jwt.js
const jwt = require("jsonwebtoken");
const {
    
     promisify } = require("util");
const {
    
     uuid } = require("../config/config.default");
const tojwt = promisify(jwt.sign);
const verfiy = promisify(jwt.verify);

// 生成token
module.exports.createToken = async (userinfo) => {
    
    
  var token = await tojwt({
    
     userinfo }, uuid, {
    
    
    expiresIn: 60 * 60 * 24,
  });
  return token;
};

// jwt认证的中间件
const jwtAuthMiddleware = async (req, res, next) => {
    
    
  var token = req.headers.authorization;
  token = token ? token.split("Bearer ")[1] : null;
  if (!token) {
    
    
    return res.status(402).json({
    
     error: "请传入token" });
  }
  if (token) {
    
    
    try {
    
    
      let userinfo = await verfiy(token, uuid);
      req.user = userinfo;
      next();
    } catch (error) {
    
    
      res.status("402").json({
    
     error: "无效的token" });
    }
  } else {
    
    
    next();
  }
};

// 承认的url排除列表
const jwtAuthExcluedList = ['/api/login', '/api/register'];
// 检查排除列表的中间件
module.exports.jwtAuthExclued = (req, res, next) => {
    
    
  // 检查请求 URL 是否在排除 jwtAuth 的列表里面
  if (jwtAuthExcluedList.includes(req.path)){
    
    
    next(); // 在列表里,跳过后续中间件
  } else {
    
     
    jwtAuthMiddleware(req, res, next); // 不在列表里,就调用jwt中间件进行身份认证
  }
};

After encapsulating in this way, we only need to add the middleware used to realize the authentication jwtAuthExclued of the interface before accessing the route, and call the generation in the interface .tokenlogincreateTokentoken

2. Generate token in the login interface

for example:

  • loginController
// login
// 用户登录
exports.login = async (req, res) => {
    
    
  // 客户端数据验证
  // 链接数据库查询
  var dbBack = await User.findOne(req.body)
  if (!dbBack) {
    
    
    return res.status(402).json({
    
     error: "邮箱或者密码不正确" })
  }

  dbBack = dbBack.toJSON()
  dbBack.token = await createToken(dbBack)
  res.status(200).json(dbBack)
}

3. Add global authentication middleware

  • app.js
const express = require("express");
const app = express();
const {
    
     jwtAuthExclued } = require("./util/jwt");
const router = require("./router");


// 添加排除jwt中间件
app.use(jwtAuthExclued); 
// 添加路由中间件
app.use('/api', router);

Five, jwt and session comparison

Here is a comparison table JWTwith Session:

Contrast factor JWT Session
storage Stored on the client side, does not require the server to maintain session state. Stored on the server, the server needs to maintain session information.
safety The encryption is stricter, but if the token is stolen, the attacker can use it arbitrarily. If the sessionID is stolen, an attacker can log in as a user.
performance The token needs to be verified and decoded every time a request is made, and the performance is poor. Just look up the sessionID to get the session information, and the performance is better.
Scalability It is easier to expand in a multi-server or cross-domain environment. In a multi-server environment, sessions need to be synchronized, and the scalability is poor.
data size JWT is larger in size than sessionID and thus requires more bandwidth. The size of sessionID is stable and requires less bandwidth.
Expire date Different expiration times can be set for each token. All sessions usually have the same expiration time.
client storage location Can be stored in Cookie, LocalStorage, SessionStorage Stored in cookies.
cross-domain issues No cross-domain issues, and friendly to mobile applications. Cross-domain issues are complex and require the server to support CORS.
state Stateless, the server does not need to save user information. Stateful, the server needs to save user information.
scenes to be used Used for authentication and information exchange, especially suitable for single-page applications (SPA) and projects with front-end and back-end separation Mainly used to record user status and adapt to traditional back-end rendering Web services

Generally speaking, it JWTis suitable for APIservices with front-end and back-end separation. It can simplify the storage requirements of the server, provide better cross-platform compatibility and scalability, and also provide a safe and reliable identity authentication mechanism . It Sessionis suitable for server-rendered web applications, which can provide higher security and callability, and can also reduce the traffic burden on the client . Different scenarios need to choose the most suitable identity authentication scheme, and choose according to actual needs.

6. Summary

In this article, we explored how to implement authentication in the framework Node.jsof . We start by introducing the basics of protocols and modules, then show how to use them in to generate, parse, and validate . Through an example in an actual project, we demonstrate how to use it in combination with routing middleware to implement a user authentication mechanism based on . Using it can provide a more secure and reliable user authentication scheme for our web applications, and the advantages are also obvious: there is no need to save information on the server side, and it has the characteristics of scalability and cross-platform compatibility. Through the introduction of this article, I believe that readers have been able to master the basic usage methods and principles, and can use it in actual projects to implement a safe and reliable identity authentication mechanism.ExpressjsonwebtokenJWTjsonwebtokenExpressjsonwebtokenJWTjsonwebtokentokenjsonwebtokenjwtsessionjsonwebtokenjsonwebtoken

Guess you like

Origin blog.csdn.net/jieyucx/article/details/131951952