登錄控制是各類管理系統(tǒng)的基礎(chǔ)功能,實現(xiàn)方案也是成熟的妥凳。
思路
業(yè)界常規(guī)做法如下:
- 用戶登錄之后竟贯,服務(wù)器返回用戶的信息(用戶id, 姓名,用戶名)和Token逝钥。前端把這些數(shù)據(jù)寫入到localStorage中屑那。
- 當用戶打算進入受保護頁面時,前端程序檢查是拿到token或者用戶id。如果沒有持际,說明用戶沒登錄沃琅,直接跳轉(zhuǎn)到登錄頁面。
- 如果檢查通過就正常進入頁面蜘欲,需要從后臺取數(shù)據(jù)的時候益眉,在Request Header中帶上Token, 供服務(wù)端做身份驗證。
對應(yīng)這個思路姥份,程序上做如下修改:第一郭脂、二 兩點修改 vue router 設(shè)置使用路由守衛(wèi)(Route guard)來實現(xiàn) ;第三點修改 axios 配置殿衰,使用axios攔截器來實現(xiàn)朱庆。
實現(xiàn)
- 在router中用 meta requiresAuth 來區(qū)分需不需要登錄
{
path: "/",
name: "Login",
component: () =>
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
import(/* webpackChunkName: "login" */ "../views/Login.vue")
},
{
path: "/dashboard",
name: "Dashboard",
meta: {
requiresAuth: true //需要登錄才能訪問
},
component: () =>
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
import(/* webpackChunkName: "dashboard" */ "../views/Dashboard.vue")
},
- 使用路由守衛(wèi)判斷 1. 頁面是否需要登錄,2. 用戶有沒有拿到userId
router.beforeEach((to, from, next) => {
const loggedIn = localStorage.getItem("userId");
if (to.matched.some(record => record.meta.requiresAuth) && !loggedIn) {
next({ name: "Login" });
}
next();
});
在Axois發(fā)送請求之前在Request Header中帶上Token, 收到返回之后檢查返回結(jié)果闷祥。如果token過期或者請求上沒帶token了娱颊,服務(wù)端會返回401狀態(tài)碼。前端收到401之后凯砍,主動跳轉(zhuǎn)到登錄頁面箱硕。
//在請求發(fā)出前Header中加上 token
apiClient.interceptors.request.use(config => {
let token = localStorage.getItem("accessToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
//如果服務(wù)端返回401,則跳轉(zhuǎn)到登錄頁面
apiClient.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response.status == 401) {
router.push({ name: "Login" });
} else {
return Promise.reject(error);
}
}
);
總結(jié)
上面的做法有兩點非常標準。
- 基于token的認證悟衩,token寫在header中剧罩,header名稱為 Authorization, 值的形式為"Bearer {token}" 這種形式
- 沒有權(quán)限的請求座泳,服務(wù)端返回標準HTTP狀態(tài)碼401表示