前端的路由許可權驗證一般分為兩種:
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路由的動態載入