当前位置: 首页 > Web前端 > HTML5

单页应用中登录状态保持和页面访问权限控制的解决办法

时间:2023-04-05 01:49:02 HTML5

单页应用中登录状态维护和页面访问控制的解决方案返回一个新的html和相关的css和js资源,比如大家熟悉的JSP,这类网站就是多页网站,也叫多页应用。这种应用最明显的缺点是页面切换响应速度慢,静态资源重复加载等。但是单页应用(SPA)不需要请求新的资源,比如html、css、js在页面跳转的时候,节省了大量的http请求,加快了页面切换速度。但它也带来了一个明显的缺点,就是在应用第一次加载时必须获取所有页面,导致首屏加载时间较长。幸运的是,服务端渲染(SSR)技术可以很好的解决这个问题。整体来说,对于中小型应用来说,在当今强调前后端分离的时代,单页应用是一个不错的选择。接下来分享的是我在使用vue、vue-router和vuex开发单页面应用时遇到的一些问题和相应的解决方案。单页应用的访问权限单页应用不需要为每个页面新建一个html文件和几个css、js文件,页面切换不需要后台控制。看似对前端开发者非常友好,但实际情况是,对于大多数单页应用来说,前端开发者需要考虑的东西更多。主要在于页面访问权限的控制。例如hash方式,用户可以手动改变url的hash值来访问不同的路由,但是在实际应用中,需要对用户的操作进行判断和控制,比如有些路由需要登录有访问权限,以及一些路由对应的页面需要特殊权限访问等。我把单页应用中的页面类型分为以下两种:登录页面需要登录才能访问的页面权限控制登录页面。登录页面的特殊之处在于,登录页面只有在用户需要登录的时候才会打开,是可见的,即如果用户的登录状态没有过期,则用户无法访问登录页面的路由.在vue应用中控制登录后需要访问的页面的权限,通常在mounted方法中发送ajax请求获取数据。但是在单页应用中,用户可以通过改变url中的hash值来访问不同的路由,但是对于一些页面,比如个人中心,需要用户登录才能获取有效数据进行展示。虽然有一种简单的处理方式:允许用户访问该路由的页面,但ajax获取不到有效数据,但显然不是最佳方案。更好的方法是通过vue-router的生命周期功能在进入这些路由之前判断用户是否登录,如果没有登录则重定向到登录页面的路由。router.beforeEach((to,from,next)=>{if(to.path=='/login'){//路由访问登录页面if(login){//登录状态有效,跳转到首页next('/');}else{//需要登录next();}}else{//访问其他路由if(login){//登录状态有效,允许访问next();}else{//需要登录,重定向到登录pagenext('/login');}}})登录状态经过上面的分析,问题最终指向了前端如何判断用户的登录状态。通常,前端只负责发送请求,根据响应显示不同的页面内容,而后端会通过sessionId或token来判断用户的登录状态是否过期。那么前端有哪些方法(where)来记录(保存)用户的登录状态是否有效呢?客户端存储sessionStorage、localStorage和cookie是前端常用的客户端存储方式。作为一种让后端具备记忆能力的解决方案,cookies通常会携带一些后端判断请求来自谁的信息,比如sessionId/token。前面说到,后台判断信息是否过期,一般不会将登录状态是否有效直接存入cookie。sessionStorage保存在浏览器中,可以在用户登录成功后使用setItem保存一个属性,在路由生命周期函数beforeEach中使用getItem判断是否登录。实现很简单,但是存在很多问题:sessionStorage的过期时间本身就决定了用户登录状态和sessionStorage有效期的同步。比如关闭浏览器后,不管后台是否设置了cookie的expire属性,都得重新登录。后台的登录状态已经过期,但是sessionStorage仍然有效,导致用户本能的访问页面,但是没有数据。用户只能通过一些操作(关闭浏览器窗口重新进入)使sessionStorage失效。后台登录状态有效,但是sessionStorage没有了,导致用户重新登录。sessionStorage是可读可写的。你可以很方便的在浏览器调试工具中执行clear等方法,也可以很方便的读取setItem的值。安全性低也决定了sessionStorage无法存储重要信息。LocalStorage除了过期时间与sessionStorage不同外,其他功能类似。applicationstorage存储在application中,一般在vuex中记录用户是否登录。在路由的生命周期函数beforeEach中读取这个数据,判断用户的登录状态是否有效。那么问题来了:登录成功后更新这个数据是没有问题的,我们什么时候需要更新这个数据呢?如果没有更新登录有效,则直接刷新页面后清空vuex。如果后台登录状态有效,是否还要重新登录?我的解决方案是:通过发送请求来判断登录状态是否有效。对于获取数据的请求,如果返回值中的信息提示需要重新登录,则清空vuex,重定向到登录页面。下面看看使用vuex记录登录状态时会遇到的所有情况和解决方法:router.beforeEach(async(to,from,next)=>{if(to.path=='/login'){//访问登录页面的路由if(store.login){//登录状态有效,跳转到首页//这种情况下,用户手动修改url中的hashnext('/');}else{//发送ajax判断登录状态是否有效constlogin=awaitajax();if(login){//修改store并重定向到首页store.commit('login',true);next('/');}else{next();}}}else{//访问其他路由if(store.login){//登录状态有效,允许访问next();}else{//访问其他路由不经过登录页面,这种情况一般是用户手动修改url中的hash//发送ajax判断登录状态是否有效constlogin=awaitajax();if(login){//修改商店允许访问store.commit('login',true);下一个();}else{next('/登录');}另外,对于每次获取数据的请求,如果后端的返回值提示用户的登录状态已经过期,那么在vuex中改变登录状态,重定向到登录页面:store.commit('login',false);location.href='/#/login';location.reload();