通常情况下,浏览器会对页面进行缓存,此时可以通过后退访问刚才的页面,如:Web应用登出后,通过浏览器的回退能够访问刚才被缓存的页面,这样在有些情况下是不够安全的,解决防止后退的方法如下:
// login.vue <template> ... </template> <script> export default { name: "login", data() { return {} } }, created() {}, methods: { login() { // 请求登录接口 ... localStorage.setItem('login_token', token); this.$router.push('/'); } } } </script> <style scoped> </style>
// home.vue <template> ... </template> <script> export default { name: "home", data() { return {} } }, created() {}, methods: { login() { ... localStorage.removeItem('login_token'); this.$router.push('/login'); } } } </script> <style scoped> </style>
方法1:禁止浏览器缓存页面:将以下代码加在JSP中,或者Struts的action中。
// 防止缓存 // 不对页面进行缓存,再次访问时将从服务器重新获取最新版本 response.setHeader("Cache-Control","no-cache"); // 任何情况下都不缓存页面 response.setHeader("Cache-Control","no-store"); // 使缓存过期 response.setDateHeader("Expires", 0); // HTTP 1.0 向后兼容 response.setHeader("Pragma","no-cache");
方法2:在路由配置文件中使用全局前置守卫进行鉴权。
// router.js文件: import Vue from 'vue' import VueRouter from 'vue-router' import { Message } from 'element-ui' const routes = [ { // 首页 path: '/', component: import(() => '@/home/index'), }, { // 登录页 path: '/login', component: import(() => '@/login/index'), }, // 其他路由... ]; const router = new VueRouter({ mode: 'hash', base: process.env.BASE_URL, routes }) // 全局前置路由导航守卫 router.beforeEach((to, from, next) => { const loginToken = localStorage.getItem('login_token'); if (!loginToken) { Message.warning({ message: '授权失败,请重新登录!' }) next('/login') } else { next() } }) export default router
如果只是判断退出后是否清空token,控制台会出现以下错误提示:
RangeError: Maximum call stack size exceeded
通常是由于无限递归调用导致的。在这个情况下,很可能是因为在next('/login')
的时候,路由守卫又触发了,导致循环调用。解决方案:要解决这个问题,可以在路由配置中明确区分哪些路由需要身份验证,并在路由守卫中添加条件以避免对不需要身份验证的路由进行重定向。
以下是修正后的代码示例:
// 1.确保路由配置中标记需要身份验证的路由: 在路由配置中,确保需要身份验证的路由使用 `meta` 属性标记 const routes = [ { // 首页 path: **'/',** component: () => import('@/home/index'), meta: { requiresAuth: true // 需要身份验证 }, }, { // 登录页 path: '/login', component: () => import('@/login/index'), }, // 其他路由... ]; // 2.在路由守卫中添加条件:使用 `to.matched.some(record => record.meta.requiresAuth)` 来检查目标路由是否需要身份验证。在路由配置中明确区分哪些路由需要身份验证,并在路由守卫中添加条件以避免对不需要身份验证的路由进行重定向 router.beforeEach((to, from, next) => { const loginToken = localStorage.getItem('login_token'); // 检查目标路由是否需要身份验证 if (to.matched.some(record => record.meta.requiresAuth) && !loginToken) { Message.warning({ message: '授权失败,请重新登录!' }) next('/login') // => next({ path: '/login' }) 去登录页 } else { next() } })
总结:通过这种方式,当用户没有登录时,只有在访问需要身份验证的路由时才会重定向到登录页面,而不会在不需要身份验证的路由(如主页)上形成循环调用,从而避免 Maximum call stack size exceeded
错误。
解释:
router.beforeEach
方法是全局前置守卫,它会在每次路由跳转前执行。to.matched.some(record => record.meta.requiresAuth)
检查目标路由是否需要认证。如果用户未登录(
!loginToken
),则显示警告消息并重定向到登录页面。如果用户已登录或目标路由不需要认证,则调用
next()
继续访问目标路由。
注意事项:
确保在登录成功后将
login_token
存储到localStorage
中,并在用户登出时清除它。
作者:落日弥漫的橘_
链接:https://juejin.cn/post/7432197440778420276