基于Node.js的token验证

基于Node.js的token验证

一、服务器端

1. 目录结构

基于Node.js的token验证

2. 实现步骤

  • 下载Win64OpenSSL_Light-1_1_1c生成公钥和私钥,在将公钥和私钥放入pem文件夹中

    基于Node.js的token验证

    将openssl的安装路径添加到系统环境变量中:C:\Program Files\OpenSSL-Win64\bin
    生成私钥: openssl genrsa -out rsa_private_key.pem 1024
    用私钥生成公钥:openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

    可选:
    对私钥进行pkcs8编码:openssl pkcs8 -in rsa_private_key.pem -topk8 -out pkcs9_rsa_private_key.pem -inform PEM -outform PEM -nocrypt
    生成加密的私钥:openssl genrsa -aes256 -passout pass:123456 -out aes_rsa_private_key.pem 1024
    通过加密私钥生成公钥:openssl rsa -in aes_rsa_private_key.pem -passin pass:123456 -pubout -out rsa_public_key.pem

  • 创建jwt.js模块,写入生成token和验证token的方法

    /* 一、引入模块依赖 */
    const fs = require(‘fs‘);
    const path = require(‘path‘);
    const jwt = require(‘jsonwebtoken‘);
    
    /* 二、生成token */
    function generateToken(data) {
        let created = Math.floor(Date.now() / 1000); // 创建token生成的时间(s)
        let cert = fs.readFileSync(path.join(__dirname, ‘./pem/rsa_private_key.pem‘)); //私钥 可以自己生成
        let token = jwt.sign({
            data,
            exp: created + 60 * 60, // 生成后1小时失效
        }, cert, { algorithm: ‘RS256‘ });
        return token;
    }
    
    /* 三、校验token */
    function verifyToken(token) {
        let cert = fs.readFileSync(path.join(__dirname, ‘./pem/rsa_public_key.pem‘)); //公钥 可以自己生成
        let res;
        try {
            if (token !== undefined) {
                let result = jwt.verify(token, cert, { algorithms: [‘RS256‘] }) || {};
                res = result.data || {};
            }
        } catch (e) {
            res = e;
        }
        return res;
    }
    
    /* 导出生成和校验token的方法 */
    module.exports = { generateToken, verifyToken };
    
  • 在登录的路由中生成token

    res.send({ code: 1, token: jwt.generateToken(result[0]) });

    即利用jwt.js中生成token的方法生成字符串并返回给客户端

  • 创建中间件,拦截特定的url进行token验证

    app.use((req, res, next) => {
        if (req.url != ‘/user/login‘ && (req.url.startsWith("/user") || req.url.startsWith("/orders"))) {
            let token = req.headers.token;
            let result = jwt.verifyToken(token);
            // 如果考验通过就next,否则就返回登陆信息不正确
            if (result === undefined) {
                res.send({ status: 403, msg: "未提供证书" })
            } else if (result.name == ‘TokenExpiredError‘) {
                res.send({ status: 403, msg: ‘登录超时,请重新登录‘ });
            } else if (result.name == "JsonWebTokenError") {
                res.send({ status: 403, msg: ‘证书出错‘ })
            } else {
                req.user = result;
                next();
            }
        } else {
            next();
        }
    });
    

二、浏览器端(vue)

  • axios模块做一些初始化;客户端发送请求时,为请求加上token字符串,并使得post可以对象的方式传递参数;客户端收到响应后,根据服务器返回的token的状态,对storage里的token进行增删操作,并设置vuex中的相关变量。

    import axios from "axios";
    import qs from "qs";
    import store from ‘./store‘
    
    const Axios = axios.create({
        baseURL: "http://localhost:5050/",
        withCredentials: true
    })
    Axios.interceptors.request.use(
        config => {
            // console.log("进入请求拦截器...");
            //this.axios.post(
            //"user/signin",
            //{uname:dingding , upwd:123456}
            //)
            if (config.method === "post") {
                config.data = qs.stringify(config.data) // post(‘/‘, {请求的参数}),将post中req对象转为字符串(即发送post请求时,可以使用对象)
            }
            if (localStorage.getItem("token")) {
                config.headers.token = localStorage.getItem("token");
            }
            if (sessionStorage.getItem("token")) {
                config.headers.token = sessionStorage.getItem("token");
            }
            return config;
        },
        error => {
            console.log("===发送请求拦截器报错===")
            console.log(error);
            console.log("===end===");
            Promise.reject(error);
        }
    );
    Axios.interceptors.response.use(
        res => {
            // console.log("触发响应拦截器...")
            if (res.data.status == 403) {
                localStorage.removeItem("token");
                sessionStorage.removeItem("token");
                store.commit("setIslogin", false);
                store.commit("setUname", "");
            } else if (res.data.code == -1) {
                store.commit("setIslogin", false);
                store.commit("setUname", "");
                //alert(res.data.msg+" 请先登录 !");
            } else if (res.data.token) {
                store.commit("setUname", res.data.uname);
                store.commit("setIslogin", true);
                if (res.remember === "true") {
                    localStorage.setItem("token", res.data.token);
                } else {
                    sessionStorage.setItem("token", res.data.token);
                }
            }
            return res;
        },
        error => {
    
        }
    )
    export default {
        install: function(Vue, Option) {
            Vue.prototype.axios = Axios;
        }
    }
    
  • 将初始化后的axios.js模块导入main.js

    import axios from ‘./axios‘

基于Node.js的token验证

上一篇:JSON.parse() 和 JSON.stringify() 的作用和注意点


下一篇:下载与安装Node.js 并配置国内镜像