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進行生成.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM