你好,我是大圣。
在上一讲中,我们使用组件库完成了项目的搭建,并且引入了 Element3 和 axios 等基础库。基于 Element3,我们可以很方便地使用组件搭建项目。而使用 axios,可以很方便地获取后端数据。在项目中,权限系统的控制需要前后端配合完成,而且权限系统也是后端管理系统中常见的一个难点。不过,今天我们主要从前端的角度,来聊一下项目的权限系统。
下面,我们先从登录权限谈起,因为登录权限对于一个项目来说是必备的功能模块。完成了登录选项的设置后,下一步需要做的是管理项目中的页面权限,而角色权限在这一过程中则可以帮助我们精细化地去控制页面权限。
登录权限
继续上一讲我们搭建起来的项目,你可以看到现在所有的页面都可以直接访问了,通常来说管理系统的内部页面都需要登录之后才可以访问,比如个人中心、订单页面等等。首先,我们来设计一个这样的权限限制功能,它能保证某些页面在登录之后才能访问。
为了实现这个功能,我们首先需要模拟登录的接口和页面。我们先新增路由页面,进入到项目目录下,在 router.js 中新增路由配置。下面的代码中,routes 数组新增 /login 路由访问。
import Login from '../components/Login.vue'
const routes = [
...
{
path: '/login',
component: Login,
hidden: true,
}
]
然后,我们进入到 src/components/Login.vue 组件中,组件的代码如下所示。在代码中,我们能看到,用户在输入用户名和密码之后,把用户名和密码传递给后端,然后就可以实现登录认证。
handleLogin() {
formRef.value.validate(async valid => {
if (valid) {
loading.value = true
const {code, message} = await useStore.login(loginForm)
loading.value = false
if(code===0){
router.replace( toPath || '/')
}else{
message({
message: '登录失败',
type: 'error'
})
}
} else {
console.log('error submit!!')
return false
}
})
}
由于我们的项目是一个前端项目,所以我们需要在 Vite 内部做数据结构的模拟。我们在 src 目录下面新建 mock 目录,用来放置假数据的结构。我们写死一个用户名 dasheng,使用用户名 dasheng 登录成功之后,我们把用户名、过期日期等重要信息进行加密,生成一个 token 返回给前端。
这个 token 就算是一个钥匙,对于那些需要权限才能读取到的页面数据,前端需要带上这个钥匙才能读取到数据,否则访问那些页面的时候就会显示没有权限。
{
url: '/geek-admin/user/login',
type: 'post',
response: config => {
const { username } = config.body
const token = tokens[username]
// mock error
if (user!=='dasheng') {
return {
code: 60204,
message: 'Account and password are incorrect.'
}
}
return {
code: 20000,
data: token
}
}
}
我们回到前端页面,登录成功后,首先需要做的事情,就是把这个 token 存储在本地存储里面,留着后续发送数据。这一步的实现比较简单,直接把 token 存储到 localStorage 中就可以了。我们拿到这个 token 后,为了进行接口权限认证,要把 token 放在 HTTP 请求的 header 内部。
我们看下面的代码,在 axios 的请求发出之前,我们在配置中使用 getToken 从 localStorage 中读取 token,放在请求的 header 里发送。由于我们使用了请求拦截的方式,所以所有的后端数据发送的时候,都会带上这个 token,完成受限数据的请求。
service.interceptors.request.use(
config => {
const token = getToken()
// do something before request is sent
if (token) {
config.headers.gtoken = token
}
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
通过上面的操作,我们完成了前端网络请求的 token 限制。但是还有一个需求没有实现,就是用户没有登录某个受限页面的时候,或者说没有 token 的时候,如果直接访问受限页面,比如个人中心,那么就需要让 vue-router 拦截这次页面的跳转。
与 vue-router 拦截页面的跳转,并显示无权限的报错信息相比,直接跳转登录页是现在更流行的交互方式。但这种方式需要在 vue-router 上加一层限制,这层限制就是说,在路由跳转的时候做权限认证,我们把 vue-router 的这个功能称作导航守卫。
关于导航守卫的 API,你可以从 Vue Router 的官网看到很详细的介绍。这里我们实际应用下,下面的代码中,我们在 router.beforeEach 函数中设置一个全局的守卫。
每次页面跳转的时候,vue-router 会自动执行守卫函数,如果函数返回 false 的话,页面跳转就会失败。不过,我们也可以手动地跳转到其他页面。现在我们设置的路由很简单,如果 token 不存在的话直接跳转登录页面,否则返回 true,页面正常跳转。