问题并不难,但是这个问题之前被松哥忽略了。前两天有朋友提出这个问题。我觉得有必要写一篇文章来和大家讨论一下这个问题。先看一个小视频:简单配置视频地址就可以解决404问题。接下来我就和大家仔细的解释一下这件事情的来龙去脉。1、职责划分在传统的前后端开发中,权限管理主要是通过过滤器或者拦截器来进行的(权限管理框架本身也是通过过滤器链来实现功能的),如果用户没有某个角色或者某一个权限没有就不能访问某一个页面。但是在前后端分离中,页面跳转都交给了前端,后端只提供数据。这时候权限管理就不能再按照之前的思路了。首先要明确,前端是展示给用户的。显示或隐藏所有菜单的目的不是为了实现权限管理,而是为了给用户一个好的体验(隐藏用户没有权限的按钮,避免用户点击403后的提示,提高用户体验),你不能依赖前端隐藏控件实现权限管理,即数据安全不能依赖前端。这就像普通的表单提交一样。前端的数据校验是为了提高效率和用户体验,后端才是数据完整性的真正保障。因此,真正的数据安全管理是在后台实现的。在后台的界面设计过程中,需要保证每个界面在满足一定权限的基础上才能访问。数据接口地址是暴露的,即使暴露了,只要你没有相应的角色/权限,你是访问不到的。为了良好的用户体验,前端需要隐藏用户无法访问的界面或菜单。跳转页面、隐藏/显示按钮等,都是在前端实现的。2、存在的问题目前后台分离后,可能会面临前端职责的问题:用户直接在地址栏输入某个页面的路径怎么办?这时候如果不做额外的处理,用户确实可以通过直接输入某个路径进入系统中的某个页面,但是不用担心数据泄露,因为没有相关的角色/权限,并且用户无法访问相关界面,即使进入相关页面也看不到数据。但是,如果用户不这样操作,进入了一个空白页面,用户体验就不好,弹出一个空白页面,有些用户会不知所措。此时,我们可以使用Vue中的前置导航守卫来监控页面跳转。如果用户想去一个未授权的页面,我们可以直接在路由前的导航守卫中拦截并重定向到登录页面,或者只停留在当前页面不让用户跳转,或者给用户一点未经授权的提示信息。以vhr中的代码为例,我在main.js中定义了pre-routenavigationguard:router.beforeEach((to,from,next)=>{if(to.path=='/'){next();}else{if(window.sessionStorage.getItem("user")){initMenu(router,store);next();}else{next('/?redirect='+to.path);}}})这个方法有点类似于Java中的filter。to表示去哪里,有点像HttpServletResponse;from表示从哪??里来,有点像HttpServletRequest;所有的页面路由/跳转都会在这里被监控。主要逻辑如下:如果去的地址是'/',即去的地方是登录页面,则直接执行next方法表示释放。如果去的地址不是'/',则看用户是否登录,如果用户已经登录,先初始化菜单,然后调用next方法继续往下,想去哪里.如果没有登录,调用next方法,跳转路径为'/',即返回登录页面,同时携带一个redirect参数,这个是重定向地址,这个参数的作用如下如下:比如我本来输入'/aa/bb',结果因为没有登录,自动跳转到项目登录页面。当我登录成功后,它会自动跳回'/aa/bb'。有了这个配置,用户就不怕乱跳了。如果不登录,随便输入一个地址,就会回到登录页面。3.404问题上面的配置还有一个404问题。当用户没有登录时,如果在浏览器中输入一个不存在的地址,会自动回到登录页面,没有问题,但是如果用户已经登录了,在浏览器中输入一个不存在的地址浏览器,这个404是在你没有做任何定义的时候才会出现的,所谓的404页面其实就是一片空白。解决这个问题,很多朋友首先想到的是能不能在前端路由导航守卫中进行判断。当要跳转时,先判断跳转路径是否存在,存在则跳转。转,否则不要跳。3.1动态路由的思路好像还行,其实还有更简单的方法,就是利用vue-router中的动态路由。举个简单的例子,我们有一个用户展示的页面,会根据不同的用户id展示不同的用户数据,所以我们可以在router.js中这样定义路由:routes:[//动态路径参数以冒号开头{path:'/user/:id',component:User}]注意这里标记的参数id前面加了一个:。定义完成后,以后像/user/1和/user/2会映射到同一个路由。而地面中的1、2等参数可以通过this.$route.params.id获取。上面是设置一个参数,我们也可以设置多个参数,可以参考官方给的一个表格:【外链图片传输失败,源站可能有防盗链机制,建议保存图片直接上传(img-9CBWcZv3-1584424148156)(http://img.itboyhub.com/2020/...]如果有多个参数,也可以通过this.$route获取参数的值。params.注意在动态路由匹配中,如果我们从/user/1切换到/user/2,原来的User组件不会被销毁,也意味着该组件的生命周期钩子函数不会被再次调用,所以如何刷新数据,这时候我们可以使用beforeRouteUpdate导航守卫,在导航守卫中完成数据更新:router.beforeRouteUpdate((to,from,next)=>{//刷新数据})3.2解决404最后,就是我们这篇文章要说的404问题了,看完上一节,如何解决404其实很容易理解。我们可以使用通配符*来匹配任意路径,例如下面的匹配格式:{//会匹配所有路径path:'*'}这个匹配规则会匹配所有路径,通常用来解决404问题的前端页面。也可以自己定义一些前缀,例如如下:{//将匹配任何以`/javaboy-`开头的路径path:'/javaboy-*'}当我们使用通配符时,我们可以通过this.$route.params.pathMatch获取通配符匹配的路径,例如用户请求路径为/javaboy-aaa,则this.$route.params.pathMatch的值为aaa。另一个重点是通配符路径的顺序。如果路径中包含通配符,一般来说应该放在路由的末尾。
