大家好,又见面了,我是你们的朋友全栈君。
vue后台管理系统流程(面试必选)
后台页面的权限验证与安全性是非常重要的,可以说是一个后台项目一开始就必须考虑和搭建的基础核心功能 我们前端所要做的是: 不同的权限对应着不同的路由,同时侧边栏也需要根据不同的权限 , 异步生成.
技术栈主要有:
vue,vue-router,vuex,axios,vue-cli 3.x
(没有
webpack.config.js
配置文件,取而代之的是
vue.config.js
文件),
fiddle.php,nodejs
(
express
框架配合myspl
搭建过一个简单的后台系统框架,cookie.session
配合使用,验证登录状态,但是我们这个项目使用的是token来验证)
一. 登入界面
登录: 当用户填写完账号和密码后向服务端验证是否正确, 服务端返回一个token
, 拿到token之后(我会将这个token
存储到cookie
中,保证刷新页面后能记住用户登录), 前端会根据token在去拉取一个user_info
的接口来获取用户的详细信息(如用户权限,用户名等等信息)
权限验证: 通过token获取用户对应的role(角色), 动态根据用户的role算出其对应有权限的路由, 通过router.addRoutes
动态挂载这些路由. 这些都是通过VUEX全局管理控制的(补充说在这里插入代码片明: 刷新页面后vuex
的内容也会丢失)
具体实施: 首先做一个静态登入页面,两个input
的框, 一个登录账号,一个登录密码,在放置一个登录按钮,绑定click
事件,点击登录
之后向服务端提交账号和密码进行验证,在向服务端提交账号和密码之前我们前端还可以进行一次简单的校验,减轻服务器压力,优化前端代码(后台设置校验是为了防止有人绕过前端,直接去后台登入)
click
绑定登录按钮,当点击按钮,提交账号密码,登录成功之后 , 在这里推荐是用第三方登录平台不重定向到首页,
this.showDialog = true
//弹出选择第三方平台的dialog
,利用this.$store.dispatch
提交username
信息到vuex
中的异步action
,并将token
储存在cookie
之中,这样下次打开页面的时候能记住用户的登录状态,不用在登录页面重新登录了.
注意: 为了安全性,我司在后台所有
token
有效期都是seeion
,就是浏览器关闭了就丢失了,重新打开浏览器都需要重新登录一次,确保用户不会因为电脑遗失或者其他原因被人随意使用账号 1.1. 获取用户信息
用户登录成功之后,我们在全局钩子router.beforeEach
中拦截路由,判断是否已获得token
,在获取token
之后我们就要去获取用户的基本信息了
(同时要注意一点的是: 我们之后存储一个用户
token
,并没有存储别的用户信息{用户名,用户头像等}) (假设我把用户权限和用户名存在本地,如果我在这时候有另一台电脑登录并修改了自己的用户名,那再用之前的电脑登录,那么他会默认去读取本地cookie中的名字,并不会去拉取新的用户信息)
所以现在的策略:
- 页面会从cookie中查看是否存在token
- 没有 2.1. (就走一遍上部分的流程重新登录)
- 如果有token,就会把这个token返给后端去拉取user_info,保证用户信息是最新的. 3.1. (如果做了单点登录功能的话, 用户信息存储在本地也是可以得,当你一台电脑登录时,另一台会被提下线,所以总会重新登录获取最新的内容)
- 而且从代码层面我建议还是把 login和get_user_info两件事分开比较好,在这个后端全面微服务的年代,后端同学也想写优雅的代码~
二. 权限篇
在工作中,前端会有一个路由表,他表示了每一个路由可访问的权限.
用户登录之后,通过token获取用户的role(角色信息) 动态根据用户的role 算出其对应应有权限的路由
再通过router.addRouetes
动态挂载路由(这些都只是路由级的,后端的权限是逃不掉的)
现在,就是前端来控制页面级的权限,不同权限的用户显示不同的侧边栏和限制其所能进入的页面(还有少许的按钮级别的权限控制)
后端会验证每一个涉及请求的操作,验证其是否有该操作的权限,每一个后台的请求不管是get
还是post
都会让前端在请求header
里面携带用户token
, 后端会根据改token
来验证在token
是否有权限执行该操作,如果没有权限就会抛出一个对应的状态码,前端测到状态码,做出相应的操作
后台的请求: 常见的有一般有四种,分别对应了 增删改查 , PUT: 向指定资源位置上传其最新内容。 DELETE: 请求服务器删除Request-URI所标识的资源。 POST: 向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。 GET: 向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
三. 具体实现
- 创建
vue
实例的时候将vue-router
挂载 , 但这个时候vue-router
挂载一些登录或者不用权限的公用的页面 - 当用户登录后, 获取用
role
, 将role
和路由表每个页面需要的权限作比较, 生成最终用户可访问的路由表 - 调用
router.addRoutes(store.getters.addRouters)
添加用户可访问的路由 使用vuex
管理路由表, 根据vuex
中可访问的路由渲染侧边栏组件router.js
中书写实现路由表:
- 首先
- 我们要实现如首页和登录页和一些不用权限的公用页面
vue-router
如登录页和首页 - 之后实例化
vue
的时候只挂载上面不用权限的路由export default new Router
({routers
: 上面的路由}) - 异步挂载路由: 动态需要根据权限加载路由表,在这里我们根据
vue-router
官方推荐的方法meta
路线元字段(可以meta在定义路径时包含字段,写在你children里面) - 标签来标示页面访问的权限有哪些
meta: {role: [‘admin’ , ‘super_editor’]}
表示该页面只有admin
个超级编辑才能有资格进入
注意事项: 这里有一个需要非常注意的地方就是404 页面一定要最后加载 , 如果放在
constantRouterMap
一同声明了 404 , 后面的所有页面都会拦截404 main.js数据入口文档(关键的main.js)
在main.js
中主要用的是
router.beforeEach(to,from,next) => {
if (store.getters.token) {
if (to.path === ‘/login’) {
next ({
path: ‘/‘})
}
}
也就是登录之后
,判断是否有token
,
如果没有,那就在免登录白名单中查找,
如果有就是直接进入,
如果没有那么就跳转到登录页
如果有,并且入口路径to是从/login登录页中进入的,
那么就redirect
重定向跳转到首页,
否则先判断当前用户是否已拉取完user_info
信息if(store.getters.roles.length === 0)
,
如果是,那么user_info
拉取infostore.dispatch(‘GetInfo方法名’).then
在从这个异步操作中获取所有的值,const roles = res.data.role
,
生成可访问的路由表store.dispatch(‘GenerateRoutes’, {roles})
,在获取到可访问的路由表后,
我们在动态添加可访问的路由表router.addRoutes(store.getters.addRouters)
,
在通过next({ …to , replace: true})hack
方法 确保addRouters
已完成 , set the replace: true
如果没有拉取到info
信息就返回err .catch(err => {console.log(err)})
如果当有用户权限的时候,说明所有可访问路由已生成 ,
如果没权限的页面会自动进入404页面
如果页面没有token
时,
如果在页面登入的白名单中,就直接进入if(whiteList.indexOf(to.path) !== -1){next()}
,
否则全部重定向到登入页面
下面是store/permission.js
这里就是干一件是
,通过用户权限和之前在router.js
里面asyncRouterMap
的每一个页面所需要的权限做匹配 , 最后返回一个该用户能够访问路由有哪些
这是一个vuex
状态管理模式,vuex
的状态管理是响应式的,当vue
组件从store
中读取状态的时候,若store
中的状态发生改变 ,
那么相应的组件也会发生改变
但是,你不能直接改变store
中的状态.改变store
中的状态唯一的途径就是,显示的提交(commit ) mutation
.
在vue
组件中获取vuex
状态 封装hasPermission
函数,
判断进入页面是否需要权限,还有封装vuex
中mobule
模块
侧边栏
基于element-ui
(vue
常用的UI框架)的NavMenu
侧边栏来实现的
遍历之前算出来的permission_routers
,
通过vuex
拿到之后动态v-for
渲染(这里因为一些业务需要要加很多判断,比如我们定义路由的时候会加很多参数)
hidden:true
是否显示,默认为flase
redirect: noredirect
如果重定向为conredirect
那么重定向不会再面包屑中显示 name: ‘router-name’
**名称由(必须设置!!)**使用 meta: {role title icon noCache} role: [‘admin’ , ‘editor’]
将控制页面角色(您可以设置多个角色)
title: ‘title’
子菜单和面包屑中显示的名称(推荐集)
icon: ‘svg-name’
侧边栏中显示的图标 noCache: true
如果fasle
,页面将不会被缓存(默认为false
)
侧边栏高亮问题: element-ui
官方給了default-active:default-active=”$route.path”
将default-active
一直指向当前路由就可以了,就是这么简单
按钮级别权限控制
现在是通过获取到用户的role
之后,在前端用v-if
手动判断来区分不同权限对应的按钮的。
理由前面也说了,我们的权限判断是交给后端来做的,每个操作后端都会进行权限判断。而且我觉得其实前端真正需要按钮级别判断的地方不是很多,如果一个页面有很多种不同权限的按钮,我觉得更多的应该是考虑产品层面是否设计合理。
axios拦截器
首先我们通过reques
t拦截器在每个请求头里面塞入token
,好让后端对请求进行权限验证。
并创建一个resques
拦截器,当服务端返回特殊的状态码,我们统一做处理,如没权限或者token
失效等操作。
两步验证
首先考虑到安全性,简简单单一个账号 密码的方式很难保证安装性,推荐借助腾讯的微信或qq作为第三方绑定 或者是在一些特殊的,有参与支付等一些事关自身利益的,设置二级密码
账号和密码验证成功之后还需要绑定一个第三方平台验证,只需要在原有登录的逻辑上改造一下就好,登录成功之后,
不直接跳到首页而是让用户两步登录,选择登录平台,第三方平台登录一样要通过OAuth2.0
授权
如微信还必须是你授权账号的一级域名。
所以你授权的域名是vue-element-admin.com
,你就必须重定向到vue-element-admin.com/xxx/
下面,所以你需要写一个重定向的服务,如vue-element-admin.com/auth/redirect?a.com
跳到该页面时会再次重定向给a.com
。
所以我们后台也需要开一个authredirect
页面:代码。他的作用是第三方登录成功之后会默认跳到授权的页面,授权的页面会再次重定向回我们的后台,由于是spa
,
改变路由的体验不好,我们通过window.opener.location.href
的方式改变hash
,在login.js
里面再监听hash
的变化。当hash
变化时,获取之前第三方登录成功返回的code
与第一步账号密码登录之后返回的userid
一同发送给服务端验证是否正确,
如果正确,这时候就是真正的登录成功。
外卖后台管理系统
后台界面的首页: 是由element
的
时间区间插件 , 省市区级联插件, 树形插件选择不同的角色;
这几个条件, 来筛选对应条件的数据 我们把后台返回的数据放到Echarts
的折线图,饼状图里面,
每次登录系统每个角色看到的这个统计数据是不一的,这取决于我们前端利用token
拉取的user_info
接口中所获取的信息,参数是不一样的 , 这样做到了有公司管理者对公司整体的运营情况的一个把握
我们的有一些系统给入驻的商家时候,他们可以添加商店 , 我们审核 ,给予相应的权限,
我们前端在通过token
获取roel
,根据用户的roel
动态算出其拥有权限的路由,
之后通过router.addRouters
动态挂载这些路由
商户可以上传一些菜品 , 图片 , 价格等参数 ,
我们后台人员会检测到每个商家的经营情况 , 动态的给他们推送一些活动 , 首页置顶之类的;
这里我们使用了
element
的Upload上传插件; Transfer 穿梭框插件, Form插件, Table表格插件, Pagination 分页插件
在利用flex布局,布局: 头部固定,左边固定,右边自适应
display: flex; flex
布局中分为主轴方向和交叉轴: 主轴方向: 我们在弹性容器上通过flex-direction
修改主轴方向;
如果主轴方向改变那么交叉轴也会变它有几个属性,分为row
左->右 , column
上->下 , row-reverse
左<-右 , column-reverse
上<-下 弹性布局永远沿着主轴排列,
当主轴排列不下,我们可以通过flex-wrap
进行换行 , nowrap
,不换行 一行显示 , wrap
换行下一行显示 , wrap-reverse
反向换行 复合属性: flex-flow = flex-drection flex-wrap
复合属性flex = flex-grow flex-shrink flex-basis flex-grow
: 放大比例 flex-shrink
生效前的尺寸 flex-basis
设置的是元素在主轴上的初始尺寸
主轴上元素的对齐方式: justify-content: flex-start
默认左->右 , flex-end
左<-右 , center
居中 , space-between
左右对齐中间自适应 , space-around
平分剩余空间 交叉轴上的对齐方式: align-items stretch
: 默认值,会在交叉轴方向撑满 flex-start
沿前端 flex-end
沿交叉轴终点对齐 center
沿交叉轴中点对齐 baseline
沿第一行文字的基线对齐…
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/197715.html原文链接:https://javaforall.cn