登录控制是各类管理系统的基础功能,实现方案也是成熟的。
思路
业界常规做法如下:
- 用户登录之后,服务器返回用户的信息(用户id, 姓名,用户名)和Token。前端把这些数据写入到localStorage中。
- 当用户打算进入受保护页面时,前端程序检查是拿到token或者用户id。如果没有,说明用户没登录,直接跳转到登录页面。
- 如果检查通过就正常进入页面,需要从后台取数据的时候,在Request Header中带上Token, 供服务端做身份验证。
对应这个思路,程序上做如下修改:第一、二 两点修改 vue router 设置使用路由守卫(Route guard)来实现 ;第三点修改 axios 配置,使用axios拦截器来实现。
实现
- 在router中用 meta requiresAuth 来区分需不需要登录
{
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")
},
- 使用路由守卫判断 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发送请求之前在Request Header中带上Token, 收到返回之后检查返回结果。如果token过期或者请求上没带token了,服务端会返回401状态码。前端收到401之后,主动跳转到登录页面。
//在请求发出前Header中加上 token
apiClient.interceptors.request.use(config => {
let token = localStorage.getItem("accessToken");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
//如果服务端返回401,则跳转到登录页面
apiClient.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response.status == 401) {
router.push({ name: "Login" });
} else {
return Promise.reject(error);
}
}
);
总结
上面的做法有两点非常标准。
- 基于token的认证,token写在header中,header名称为 Authorization, 值的形式为"Bearer {token}" 这种形式
- 没有权限的请求,服务端返回标准HTTP状态码401表示