jwt加meta元資訊實現登入後校驗

lixiange發表於2019-10-09

前端的路由許可權驗證一般分為兩種:

1路由元資訊meta

主要思想是可以在路由中設定meta:{}來判斷訪問哪些路由需要指定的許可權,在進入路由時可以在路由前置鉤子router.beforeEach()中判斷是否滿足條件,如果不滿足就執行指定的操作,如果返回就放行(next())

(1)驗證使用者是否登入

當使用者在輸入的登入資訊正確後在後端使用jwt生成一個金鑰,將金鑰返回給前端,作為token儲存在localstorage中,當訪問每一個api介面時進行請求攔截,將token作為請求頭傳送給伺服器,伺服器會在verify介面中對比token是否正確,在訪問每一個頁面時在路由前置鉤子router.beforeEach()中判斷是否有token或者是否過期,如果沒有或者過期了就不能訪問設定必須登入才能訪問的許可權,把他next到login頁面

程式碼演示

1,當輸入資訊後進行後端驗證,如果正確,生成token

app.post('/login',(req,res)=>{

​    console.log(req.headers)

​    let username=req.body.username;

​    console.log(username)

​    if(username=='admin'){

​        //登入成功了返回一個token,

​        res.json({

​            code:0,

​            username:'admin',

​            token:jwt.sign({username:'admin'},secret,{expiresIn:60})

​        })

​    }else{

​        res.json({

​            code:1,

​            data:'使用者名稱不存在'

​        })

​    }

})
複製程式碼

2,在store中呼叫介面,把使用者名稱存到vuex中,將token儲存到localstorage中

 async toLogin({commit},username){

​      //請求介面

​    let r=  await login(username);

​    if(r.code==0){

​      commit('changeUsername',r.username)
//這裡的setLocal是在api資料夾中封裝的一個方法
​     setLocal('token',r.token)

​    }else{

​    return Promise.reject(r.data)

​    }

​    },
複製程式碼

3,封裝一個自己的axios,在其中進行請求攔截和響應攔截

import {getLocal} from './local'

//建立一個類

class AjaxRequest{

​    constructor(){

​        this.baseURL = process.env.NODE_ENV =="production"?'/':'http://localhost:3030'

​        this.timeout=3000;

​        this.queue={};//存放每一次的請求,為了在第一次請求時顯示loading動畫

​    }

​    merge(options){

​        return{...options,baseURL:this.baseURL,timeout:this.timeout}

​    }

​    //封裝請求攔截,響應攔截

​    setInterceptor(instance,url){

​        instance.interceptors.request.use((config)=>{

​         
//將token作為請求頭傳到伺服器
​            config.headers.Authorization=getLocal('token');

​            if(Object.keys(this.queue).length===0){

​                store.commit('showLoading')

​           }

​            

​          this.queue[url]=url;

​            return config

​        })

​        instance.interceptors.response.use((res)=>{

​            delete this.queue[url]

​            if(Object.keys(this.queue).length===0){

​                store.commit('hideLoading')

​            }

​           

​            return res.data

​        })

​    }

​    request(options){

​        let instance=axios.create();

​        this.setInterceptor(instance,options.url);//在請求資料的時候設定攔截

​        let config=this.merge(options)

​        return instance(config)

​    }

}
複製程式碼

4 在服務端寫一個介面驗證token是否失效或者是否有token

app.get('/verify',(req,res)=>{

​    let token=req.headers.authorization

​    jwt.verify(token,secret,(err,decode)=>{

​        if(err){

​            return res.json({

​                code:1,

​                data:'token失效了'

​            })

​        }else{

​            return res.json({

​                code:0,

​               username: decode.username,

​               token:jwt.sign({username:'admin'},secret,{

​                   expiresIn:20

​               })
複製程式碼

​ 5,在路由前置鉤子中判斷

router.beforeEach(async(to,from,next)=>{

  let isLogin= await store.dispatch('verify');

  console.log(isLogin)

  //console.log(isLogin)

  //是否需要登入才能訪問

  let needLogin=to.matched.some(match=>match.meta.needLogin)

  console.log(to)

  console.log(needLogin)

  if(needLogin){

​    if(isLogin){

​      //登入過了

​      console.log('guo')

​      next()

​    }else{

​      console.log('hahha')

​      next("/login")

​    }

  }else{

​    if(isLogin && to.path==='/login'){

​      next('/');

​    }else{

​      next()

​    }}})
複製程式碼

2路由的動態載入

相關文章