zoukankan      html  css  js  c++  java
  • 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进行生成.

  • 相关阅读:
    自定义时间工具类
    http和https
    客户端是什么意思
    19.在HTTP 1.0中,状态码401的含义是(?);如果返回“找不到文件”的提示,则可用 header 函数,其语句为(?)写出http常见的状态码和含义,至少5个.[完善题目]
    20.谈谈对mvc的认识。
    18.有一个网页地址, 比如PHP开发资源网主页: http://www.phpres.com/index.html,如何得到它的内容?
    17.如何修改SESSION的生存时间。
    16.语句include和require的区别是什么?为避免多次包含同一文件,可用(?)语句代替它们?
    14.对于大流量的网站,您采用什么样的方法来解决访问量问题?
    15.用PHP写出显示客户端IP与服务器IP的代码,如何防止用户使用代理的情况?[添加更多详情]
  • 原文地址:https://www.cnblogs.com/whyaza/p/11605314.html
Copyright © 2011-2022 走看看