通常情況下,瀏覽器會對頁面進行快取,此時可以透過後退訪問剛纔的頁面,如: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