• vue & nodejs jwt 的基于token身份验证


    现在比较流行的验证方式,是带着token的登录验证

    原理

    1. 登陆时,客户端发送用户名密码
    2. 服务端验证用户名密码是否正确,校验通过就会生成一个有时效的token串,发送给客户端
    3. 客户端储存token,一般都会存储在localStorage或者cookie里面(vue可以存储与vuex)
    4. 客户端每次请求时都带有token,可以将其放在请求头里,每次请求都携带token
    5. 服务端验证token,所有需要校验身份的接口都会被校验token,若token解析后的数据包含用户身份信息,则身份验证通过,返回数据
    
    

    完整例子

    下面来看一个比较完整的例子,有问题可以和我交流哦,我也挺菜的:
    第一步,客户端发送用户名和密码; (一般是post过去)
    第二步,验证用户名密码是否正确,校验通过就会生成一个有时效的token串,发送给客户端

            if (data.toString() === req.body.pass){
                // 登陆成功,添加token验证
                let sid = req.body.pass + req.body.seccode; //密码 和 验证码组成其sid
                let jwt = new JwtUtil(sid); //将用户sid传入,生成token
                let token = jwt.generateToken();
                res.send({status:200,msg:'登陆成功',token:token});
            }else{
                res.send({status:404,msg:'口令错误'})
            }
    

    第三步,客户端储存token,一般都会存储在localStorage或者cookie里面(这里我存储在vuex里面,进行统一管理)
    第四步,客户端每次请求时都带有token,可以将其放在请求头里,每次请求都携带token

                      //使用vuex对全局token进行状态管理
                      this.$store.dispatch("set_token",res.data.token);
                      //设置:全局带token
                      this.$http.defaults.headers.common['token'] = this.$store.state.token;
    

    store 里index.js:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    //使用vuex
    Vue.use(Vuex);
    
    //一个store  , Vuex.store的 实例
    const store = new Vuex.Store({
        state: {
            token : ''
        },
        getters:{            //  Getter相当于vue中的computed计算属性
            getToken: (state) => {return state.token;}
        },
        mutations: {
            set_token(state,ltoken) {   //第一个参数是拿到state对象
                localStorage.setItem('token',ltoken);
                state.token = ltoken;
            },
            del_token(state) {
                localStorage.removeItem('token');
                state.token = '';
            }
        },
        actions: {      //注册actions,类似vue里面的methods 
            //通过这个修改state里面的值
            // 可以直接用mutations修改,但是官方建议使用actions去调用mutations去修改
            set_token(context,token) {
                context.commit("set_token",token);
            },
            del_token(context){
                context.commit("del_token");
            }
        }
    })
    
    export default 
    

    最后一步,服务端验证token,所有需要校验身份的接口都会被校验token,若token解析后的数据包含用户身份信息,则身份验证通过,返回数据
    (这里,除了一些特定接口,不拦截之外,把拦截的 都需要进行验证)
    (我这里是: /api/fr/articles 前台获取文章列表的接口不需要拦截; /api/imgCode 生成二维码的接口不需要拦截 /api/lone 登录发token的接口不需要拦截)
    其他都需要拦截。

    app.use(function (req, res, next){
        //一共三个接口不需要拦截:
        //  /imgCode   /lone /api/fr/articles
        if (req.url != '/api/fr/articles' && req.url != '/api/imgCode' && req.url != '/api/lone') {
            let token = req.headers.token;
            let jwt = new JwtUtil(token);
            let result = jwt.verifyToken();
            console.log('result是:',result);
            // 如果考验通过就next,否则就返回登陆信息不正确
            if (result == 'err') {
                console.log(result);
                res.send({status: 403, msg: '登录已过期,请重新登录',res: result});
                // res.render('login.html');
            } else {
                next();
            }
        } else {
            next();
        }
    });
    

    其中:jwt.js怎么写呢?参考于这篇文章: nodejs 基于token的身份验证

    // 引入模块依赖
    const fs = require('fs');
    const path = require('path');
    const jwt = require('jsonwebtoken');
    // 创建 token 类
    class Jwt {
        constructor(data) {
            this.data = data;
    
        }
    
        //生成token
        generateToken() {
            let data = this.data;
            let created = Math.floor(Date.now() / 1000);
            let cert = fs.readFileSync(path.join(__dirname, '../server/pem/rsa_private_key.pem'));//私钥 可以自己生成
            let token = jwt.sign({
                data,
                exp: created + 60 * 30,
            }, cert, {algorithm: 'RS256'});
            return token;
        }
    
        // 校验token
        verifyToken() {
            let token = this.data;
            let cert = fs.readFileSync(path.join(__dirname, '../server/pem/rsa_public_key.pem'));//公钥 可以自己生成
            let res;
            try {
                let result = jwt.verify(token, cert, {algorithms: ['RS256']}) || {};
                let {exp = 0} = result, current = Math.floor(Date.now() / 1000);
                if (current <= exp) {
                    res = result.data || {};
                }
            } catch (e) {
                res = 'err';
            }
            return res;
        }
    }
    
    module.exports = Jwt;
    

    公私密钥对,一般可以选择openssl进行生成.

  • 相关阅读:
    .NET 高效开发之不可错过的实用工具(第一的当然是ReSharper插件)
    灵活运用 SQL SERVER FOR XML PATH 转
    Python 3.X 要使用urllib.request 来抓取网络资源。转
    22-1 拖拽与烟花案例
    21、bootstrap框架
    20、promise与ajax jsonp
    18、MySQL
    19、AJAX
    17、php
    16-1 ECMA5与ECMA6的函数定义
  • 原文地址:https://www.cnblogs.com/whyaza/p/11605314.html
Copyright © 2020-2023  润新知