前端鉴权

前端鉴权

前端权限的控制从本质上来说,就是控制前端视图层的展示和前端所发送的请求 ,但是只有前端权限控制没有后端权限控制是万万不可的,前端权限只是达到一个锦上添花的效果

前端权限的意义

1.降低非法操作的可能性
比如页面上的一个按钮,通过控制台改变按钮的属性,如果前端没有权限控制虽然点击了,但是不会有效果,如果有权限设置的话,没有权限的用户我们可以让其按钮隐藏

2.尽可能排除不必要请求,减轻服务器压力
不具备权限的请求,就应该压根不需要发送

3.提高用户体验

前端权限的控制思路

首先我们准备一个404界面,然后在路由的最后面添加一个

{
    
    
	path:"*",	 //代表当在前面的路由没有匹配到时,所有的错误路由都会跳转到404
	component:404界面
}

在做下面所有的操作都需要后台返回一个数据,也就是在登录页面的登录按钮中找出点击登录时候触发事件,一般是login 方法在login方法中找出返回登陆者的数据,也是后台从数据库中读取到的用户信息,打印出数据,从当中找出相应的数据来实现console.log(res)

菜单的控制

菜单主要是导航栏的显示
由于数据获取在login组件中,而左侧导航栏显示组件在其他home 组件中,所以要通过vuex 来传递数据,在home 组件中存一个menuList:[] 这是左侧导航栏要存入的数据

vuex的代码

state:{
    
    
	rightList:JSON.parse(sessionStroage.getItem('righrList')||'[]')  
	//代表从数据中提取出来的左侧导航栏数据,不能直接修改,要通过mutations方法来修改,因为缓存存的是字符串,所以要转换成数组,并且由于最开始是没有数据所以是空数组
}
mutations:{
    
    
	setRightList(state,data){
    
    
		state.rightList=data
		sessionStroage.setItem('rightList',JSON.stringify(data))
		//通过setItem方法将数据存储起来,因为缓存存储是一个字符串,而数据是一个数组
	}
}

login登录组件

//再登录方法下面的代码
login(){
    
    
	//省略部分代码
	this.$store.commit('setRightList',res.rights)
}

home左侧导航栏组件

import {
    
    mapState} from "vuex"
data(){
    
    
	return{
    
    
		menulist:[] //左侧导航栏存入的数据
	}
}
created(){
    
    
	//因为返回的数据rightList就是按照一二级权限来展示的,如果后端返回的数据不是我们想要的格式我们可以将其变成我们想要的格式(menuList)再来存储
	this.menuList=this.rightList  //定义左侧导航栏内部数据等于后台返回的数据
}
computed:{
    
    
	...mapState(['rightList']) //获取此用户登录过后rightList数据
}

上面代码实现有一个bug也就是数据持久化的问题,刷新重新渲染,因此要将数据保存到sessionStorage中,在vuex中添加代码

一个额外的功能,退出清空本地 sessionStroage 当中的数据,和vuex当中的数据
找出页面中的退出按钮,在其组件中的代码

//退出按钮触发的方法logout()
logout(){
    
    
	//删除sessionStroage中的数据
	sessionStroage.clear();//removeItem也是ok的
	//删除vuex中的数据,因为清空sessionstroage当中的数据就已经是空数组,所以我们只需要刷新当前界面就OK,跳转之后就刷新
	this.$router.push('./login')
	window.location.reload();
}

界面的控制

如果用户没有登陆,手动在地址栏敲入管理界面的地址,这时候就需要跳转登陆界面
如果用户已经登陆,但是他在手动敲入非权限内的地址,也应该跳转到404或者提示没有权限

正常的逻辑是通过登录界面,登录成功之后跳到管理平台界面,但是如果用户直接敲入管理平台的地址,也是可以跳过登录的步骤,所以应该在某个时机判断用户是否登录

  • 使用拦截器判断用户是否登录

判断token是否存在,也是找出登录方法(login)

登录组件的代码

login(){
    
    
	this.$refs.loginFormRef.validate(
		async valid=>{
    
    
			if(!vaild) return
			const {
    
    data:res} =await this.$http.post("login",this.loginFrom)
			if(res.meta.status !=200) return this.$message.error('登录失败')//$message是一个插件的用法
			this.$store.commit('setRightList',res.rights)
			this.$store.commit('setUserName',res.data.username)
			//将token存储到本地中
			sessionStroage.setItem('token',res.data.token)
			this.$message.success('登录成功')
			this.$router.push('./home')
		}
	)
}

登录过后再来判断在什么时机进行跳转,使用导航守卫,因为可以伪造token
router 路由管理下面的代码

//在常规路由下面添加一个方法
router.beforeEach((to,from,next)=>{
    
    
	if(to.path ==='./login'{
    
    next()}//跳转到登录界面不拦截
	else{
    
    
	//这里是进入其他界面,首先判断有无token没有跳转到登录界面,有的话就执行,记住next()方法是一定要调用的不然就不执行
	const token=sessionStroage.getItem('token')  
		if(!token){
    
    next('./login')}
		else{
    
    next()}
	}
})
动态路由的使用

由于某些人没有权限,所以常规来说他就不应该存有这个路由,更不能地址栏输入
首先把子路由,也就是有的人权限不够的路由注释掉,在上面定义
路由组件的代码

import store from '@/store'
Vue.use(Router)
const userRule={
    
    path:'./users',component:users} //超级管理员具备的用户信息界面,一般人是不应该拥有这个路由
const goodRule = {
    
    path:'./goods',component:goodlist} //食物界面,一般人也不应该有
//将路由写成一个对象后期只要判断这个对象中有没有其中的二级路由就行了
const ruleMapping = {
    
     
	'users': userRule,
	 'goods': goodsRule
}
//省略部分代码,向上面这种权限路由就应该在前面定义,后面动态添加
export function initDynamicRoutes(){
    
    
//定义一个方法将其导出,根据二级权限,对路由规则进行动态的添加
	console.log(router)
	const currentRoutes = router.options.routes
	const rightList = store.state.rightList 
	rightList.forEach(item => {
    
    
		item.children.forEach(item =>
		//此时的item就是二级权限
		 {
    
     currentRoutes[2].children.push(ruleMapping[item.path])
		})
	})
	router.addRoutes(currentRoutes) //router.addRoutes方法,将修改过后的路由对象重新添加router中
}

login 登录界面的代码

import {
    
    initDynamicRoutes} from '@/routes'//将方法导入进来
login(){
    
    
//省略部分代码
//登录成功之后,根据用户所具备的权限动态添加路由规则
//在返回的数据中一般在二级权限当中你能找到相关路由
	initDynamicRoutes()//执行方法
}

这样写完有一个坑,就是刷新router也会重新加载,还是会跳转到404
因此我们要在app.vue 当中添加代码

import {
    
     initDynamicRoutes } from '@/router.js' 
export default {
    
    
name: 'app', 
	created() {
    
    	 //利用生命周期最开始就重新加载路由规则
		initDynamicRoutes()
	}
}

按钮的控制

比如修改,删除等,没有权限的话这些按钮应该隐藏或禁用
按钮控制

虽然⽤户可以看到某些界⾯了, 但是这个界⾯的⼀些按钮,该⽤户可能是没有权限的.因此, 我们需要对组件中的⼀些按钮进⾏控制. ⽤户不具备权限的按钮就隐藏或者禁⽤, ⽽在这块中, 可以把该逻辑放到⾃定义指令中,通过自定义指令

首先在其添加一个自定义事件 v-permission=’{action:“add”}’ 来控制不同权限按钮的显示与隐藏

创建permission.js

import Vue from 'vue'
import router from '@/router.js'
 Vue.directive('permission', {
    
      //自定义指令的注册directive
	inserted: function(el, binding){
    
     //inserted这个函数在插入到动节点的时候被调用
	//el当前使用指令的元素,binding就是自定义指令后面的值
	const action = binding.value.action
	const currentRight = router.currentRoute.meta if(currentRight) {
    
    
	if(currentRight.indexOf(action) == -1) {
    
    
		// 不具备权限
	const type = binding.value.effect if(type === 'disabled') {
    
    
	el.disabled = true el.classList.add('is-disabled')
	} else {
    
     el.parentNode.removeChild(el)
		}
	}
	}
	}
})

main.js 导入

import './utils/permission.js'

请求和响应的控制

如果用户通过非常规操作手动在调试器当中将禁用的按钮变成启用的状态,此时发出的请求,应该被拦截
未完

猜你喜欢

转载自blog.csdn.net/weixin_48255917/article/details/109695059
今日推荐