## 4. 權限管理
> 參考鏈接:
>
> json web token入門教程 http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
>
> jwt官網 https://jwt.io/
### 4.1 token驗證
我們通過jwt進行用戶認證,jwt的原理是:服務器認證以后,生成一個json對象,發回給用戶.
```js
{
"id":"001",
"姓名":"小明",
"角色":"管理員",
"到期時間":"2019年3月3日12時30分"
}
```
以后用戶與服務端通信的時候,都要發回這個json對象。服務器完全靠這個對象認定用戶身份(一般是通過這個對象的中id去數據庫請求數據)。為了防止用戶篡改數據,服務器會在生成這個對象的時候,加上簽名。就像這種形式:
`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`
關于JWT保存更新的業務流程如下:
1. 保存:登錄后保存token
2. 添加:每次發送請求之前檢查token是否存在,存在,添加到請求頭中,發送請求
3. 更新:每次發送請求服務器返回數據之后更新token
主要邏輯包括:
1. 登錄之后,在`localStorage`中保存token
2. 每次發送請求之前,使用axios請求攔截器將token放到請求頭中
3. 每次發送請求服務器返回數據之后在axios的響應攔截器中更新token
```js
//1.登錄之后保存token login.vue
async login(){
const data = await LOGIN({ name: this.user,pass: this.pass })
//保存token
localStorage.setItem('token',data.token)
//查看是否保存成功
console.log(localStorage.getItem('token'))
}
```
```js
//每次發送請求之前,講token放到請求頭中 api/http.js
//---使用axios的請求攔截器,每次發送請求之前攔截一下
instance.interceptors.request.use(function (config) {
// 給頭添加token
if (localStorage.getItem('token')){//存在token,加入頭
config.headers.authorization=localStorage.getItem('token')
}
return config;
}, function (error) {
// 對請求錯誤做些什么
return Promise.reject(error);
});
//完成之后,記得發送一個請求,看看是否正確添加token
//---響應攔截器,服務器響應后先到達這里
instance.interceptors.response.use(function (response) {
if(response.data.code=='2000'){//成功響應,更新token
if(response.data.token){
localStorage.setItem('token',response.data.token)
}
}else{
//錯誤處理 根據不同的狀態碼,進行錯誤處理
}
return response.data;
}, function (error) {
// 對響應錯誤做點什么
return Promise.reject(error);
});
```
### 4.2 對頁面的訪問權限
除了對token的操作,我們還要判斷用戶有沒有權限訪問這個頁面(有些頁面是用戶必須登錄才能訪問的),具體配置要使用Vue Router的導航守衛
> 參考鏈接:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
在全局前置守衛中進行驗證
```js
//在router/index.js進行配置
//在每次進行路由跳轉之前進行
router.beforeEach((to,from,next)=>{//增加登錄驗證
const isLogin=localStorage.getItem('token')?true:false;
if(to.path=='/login'){//如果是登錄頁面,不需要token
next();
}else{//如果不是登錄頁面就要判斷是否登錄
isLogin?next():next('/login');
}
})
```