[Record three] Vue+node+koa2+mysql+nginx+redis, full-stack development of small programs and administrator management system projects-token verification login status

All projects that involve user login and registration need a login state to verify the user's login status. Commonly used login desks are nothing more than tokens, sessions, and other identifiers. Here I am using the token field. The token generally contains the user's personal information, such as account number, account id, user name, etc. It is more secure to add a custom salt (salt) and encrypt it together to prevent leakage of user information. Let's use it together:

Speaking of tokens, I would definitely think of how the back end knows whether the token given to me by the front end is the valid value that I passed to him? That is to say, the backend needs to have a value to compare with the token passed by the frontend to know the validity. Therefore, when the backend generates the token, it also needs to save the generated token for use. I chose redis here. It is a database, stored in the form of key-value pairs, so that I can store the generated tokens. As for the installation and deployment of redis, it is not cumbersome here, and will be used directly here.
Create a redis folder in the project root directory. Create a redis.js file under it.

//redis.js
const Redis = require('ioredis')//导入模块
const redis = {
    
    
    port: 6379,          // Redis port
    host: '127.0.0.1',   // Redis host
    prefix: '***', //存诸前缀
    ttl: 60 * 60 * 24 * 7 * 1000,  //过期时间   
    family: 4,
    db: 0
}
const redisClient = new Redis(redis)
//导出备用
module.exports = redisClient

So redis can be used.

This article uses jsonwebtoken for encryption and decryption.
Because encryption and decryption are things that many interfaces need to use, so I write these methods to the public part.
A common.js is built under the utils file to store public methods.

//common.js
const secret = require('./secret')//导入自定义的盐
const jwt = require('jsonwebtoken')//导入jsonwebtoken
const verify = util.promisify(jwt.verify) // token解密
const common = {
    
    //定义一个对象
  //加密
  //后端生成唯一的key
  /*
  * paylod:包含来用户的信息
  * secret.secret 自定义的盐(salt)
  * expiresIn 设置这个token的有效期
  */
  //jwt.sign是jsonwebtoken模块的一个方法,可以将传入的信息加密
  getToken(paylod, expiresIn) {
    
    
    return jwt.sign(paylod, secret.secret, expiresIn)
  },
  //解密
  //根据收到的token获取用户信息
  getUserInfo(token) {
    
    
    return verify(token, secret.secret) 
  },
}
//导出这个对象给外部使用
module.exports=common

Create a new secret.js file to store custom information

Insert picture description here
⚠️ Here it is recommended that the salt should be written in a random manner, the better, and all kinds of characters should be added and written out of order.

encryption

We encrypt user information when the user logs in successfully. So I write in my administrator login interface.

My admin.js file under the routes file

//admin.js
const router = require('koa-router')()
const api = require('../controllers/api')
const redisClient = require('../redis/redis.js')
const common = require('../util/comon')

router.prefix('/admin')
//管理员登录
router.post('/userLogin', async (ctx, next) => {
    
    
	/*写你的接口逻辑*/
	//定义一个用户信息对象
	const paylod = {
    
    
        name: '登录用户的用户名',
        userid: '登录用户的id',//登录时可查表查拿到用户id
        author: '[email protected]',
        type:'***',
        timestamp: new Date()//加个时间戳保证加密后token的唯一性
    }
    
    /*核心代码*/
    
    // 调用上面公共的token加密方法(注:这里是没有传盐进去的,我是直接在common文件引入来盐)
    // expiresIn设置token的有效期是7天
    const token = await common.getToken(paylod, {
    
     expiresIn: '7 days' })
    //每次登录之前先清除掉所有的有关此用户的key(根据用户id)
    let preToken = await redisClient.get(result.userid)
    //这个preToken就是当初登录时redis存下来的key
    await redisClient.del(preToken)
    //用token作为key、自定义的token前缀+token作为值 传key给前端作为校验
    await redisClient.set(token, secret.identif + token)
    //再生成一对键值对 用来记录是属于哪个用户的token 用户id作为key 传给前端的token(上一条键值对的key)作为值
    await redisClient.set(result.userid,token)
    ctx.body = {
    
    
        status: 200,
        code: 200,
        message: '登录成功',
        data: result,
        token: token//将token传给前端
    }
}

In this way, after the login is successful, the front end can receive the unique token generated by the back end, and I also generated two pairs of key-value pairs. One pair uses the token as the key and a custom token prefix as the value; one pair uses the user id as the key and token as the value. Get the user id when the user logs in, clear the record with this user id as the key in redis, and then save a record with the token as the key. In this way, it can be ensured that every time a user logs in, the user has only one legal key (the so-called login status of the same account in multiple places will crowd out the login status of other people).

Decrypt

After the encryption is completed, the client request must bring the login state token to manipulate the data, but it is impossible to transmit the user's data on the client side, which is too insecure, so that the data that I added the user information to when generating the token above Useful, as long as I decrypt it, I can know the user information carried by this token. This token client does not know the user information when it sees it, so it is relatively safer.

In common.js, I wrote a token that gets passed in from the front end (passed in through the request header, not in the form of parameters)

//common.js
 //根据请求头的信息获取前端传入的token
 getHeaderToken(ctx) {
    
     
   if (ctx.header && ctx.header.token) {
    
     
     return ctx.header.token
   }
 }
const common = require('../util/comon')
//删除管理员
router.post('/****', async (ctx, next) => {
    
    
	let token = await common.getHeaderToken(ctx)
	let userInfo = await common.getUserInfo(token)
	//用户名
	console.log(userInfo.name)
	//用户id
	console.log(userInfo.userid)
}

Therefore, as long as the front-end passes in the token, the back-end can know the user's information carried by the token, which facilitates the necessary conditions for the back-end to process data.

The above is this introduction to the use of tokens, and the following will introduce requesting permissions based on the login console control interface.

Previous: Writing interface routing
Next: Token controlling interface permissions

Guess you like

Origin blog.csdn.net/Smell_rookie/article/details/108704245