JS怎樣實現前端路由攔截 5種路由攔截方案保障前端頁面權限

前端路由攔截的核心是通過在路由跳轉前后進行權限判斷,決定用戶是否能訪問特定頁面。常見實現方式包括:1. 全局路由守衛(如 vue 的 beforeeach 或 react 的 usenavigate 鉤子),集中管理權限并控制跳轉;2. 組件級別權限控制(如 react 的 hoc),靈活控制單個組件的訪問權限;3. 服務端渲染(ssr)時在服務器校驗權限,提高安全性但增加復雜度;4. 使用路由配置中的 meta 字段存儲權限信息,在全局守衛中統一校驗;5. 動態路由,根據用戶權限動態生成路由表以實現精細化控制。spa 中推薦使用全局路由守衛和組件級控制相結合的方式,并注意處理異步權限驗證及避免重定向死循環問題。

JS怎樣實現前端路由攔截 5種路由攔截方案保障前端頁面權限

前端路由攔截,簡單來說,就是控制用戶能否訪問特定頁面。實現方式多種多樣,核心在于在路由跳轉前后進行判斷,決定是否允許跳轉。

JS怎樣實現前端路由攔截 5種路由攔截方案保障前端頁面權限

解決方案

JS怎樣實現前端路由攔截 5種路由攔截方案保障前端頁面權限

前端路由攔截的本質是在路由跳轉前后進行權限判斷。常見的實現方案包括:

立即學習前端免費學習筆記(深入)”;

  1. 全局路由守衛 (vue router / React Router): 這是最常用的方法。在路由跳轉前,通過 beforeEach (Vue) 或 useNavigate (React) 鉤子,檢查用戶權限。如果權限不足,可以重定向到登錄頁或其他授權頁面。這種方式集中管理路由權限,方便維護。

    JS怎樣實現前端路由攔截 5種路由攔截方案保障前端頁面權限

    • Vue Router 示例:
    router.beforeEach((to, from, next) => {   const requiresAuth = to.matched.some(record => record.meta.requiresAuth);   const isLoggedIn = localStorage.getItem('token'); // 假設使用 token 驗證    if (requiresAuth && !isLoggedIn) {     next('/login'); // 重定向到登錄頁   } else {     next(); // 允許跳轉   } });
    • React Router 示例 (使用 useNavigate 鉤子):
    import { useNavigate, useLocation } from 'react-router-dom'; import { useEffect } from 'react';  function AuthGuard({ children, requiredRoles }) {   const navigate = useNavigate();   const location = useLocation();   const isLoggedIn = localStorage.getItem('token'); // 假設使用 token 驗證   const userRole = localStorage.getItem('role'); // 假設存儲用戶角色    useEffect(() => {     if (!isLoggedIn) {       navigate('/login', { replace: true, state: { from: location } }); // 保存當前 location,登錄后跳轉回來     } else if (requiredRoles && !requiredRoles.includes(userRole)) {       navigate('/unauthorized'); // 重定向到無權限頁面     }   }, [isLoggedIn, navigate, location, requiredRoles, userRole]);    return children; }  export default AuthGuard;
  2. 組件級別權限控制 (Higher-Order Components – HOC): 通過高階組件包裹需要權限控制的組件,在組件渲染前進行權限判斷。這種方式更靈活,可以針對單個組件進行權限控制。

    // React 示例 function withAuth(WrappedComponent, requiredRole) {   return function(props) {     const isLoggedIn = localStorage.getItem('token');     const userRole = localStorage.getItem('role');      if (!isLoggedIn || (requiredRole && userRole !== requiredRole)) {       return <div>您沒有權限訪問此頁面</div>; // 可以重定向到其他頁面     }      return <WrappedComponent {...props} />;   }; }  // 使用 const AdminDashboard = withAuth(Dashboard, 'admin'); // 只有 admin 角色才能訪問
  3. 服務端渲染 (SSR) 時的權限控制: 在服務端進行權限判斷,只有擁有權限的用戶才能獲取到頁面內容。這種方式安全性更高,但實現復雜度也更高。

    • 例如,在 Next.JS 中,可以在 getServerSideProps 函數中進行權限校驗。
    export async function getServerSideProps(context) {   const { req, res } = context;   const token = req.cookies.token; // 從 cookie 中獲取 token    if (!token) {     return {       redirect: {         destination: '/login',         permanent: false,       },     };   }    // 校驗 token,獲取用戶信息   try {     const user = await verifyToken(token); // 假設 verifyToken 是一個校驗 token 的函數     return {       props: { user },     };   } catch (error) {     return {       redirect: {         destination: '/login',         permanent: false,       },     };   } }  function MyPage({ user }) {   // ... }  export default MyPage;
  4. 路由配置中的 Meta 字段: 在路由配置中添加 meta 字段,用于存儲權限信息。然后在全局路由守衛中讀取 meta 字段,進行權限判斷。這種方式可以更清晰地管理路由權限。

    // Vue Router 示例 const routes = [   {     path: '/admin',     component: AdminDashboard,     meta: { requiresAuth: true, role: 'admin' },   },   // ... ];  router.beforeEach((to, from, next) => {   if (to.meta.requiresAuth) {     const isLoggedIn = localStorage.getItem('token');     const userRole = localStorage.getItem('role');      if (!isLoggedIn) {       next('/login');     } else if (to.meta.role && userRole !== to.meta.role) {       next('/unauthorized');     } else {       next();     }   } else {     next();   } });
  5. 動態路由: 根據用戶的權限動態生成路由表。這種方式可以更精細地控制用戶的訪問權限,但實現復雜度較高。

    • 例如,在用戶登錄后,從服務器獲取用戶擁有的權限列表,然后根據權限列表動態生成路由表。

單頁面應用(SPA)路由攔截的最佳實踐是什么?

SPA 的路由攔截核心在于客戶端,因此全局路由守衛和組件級別權限控制是常用的選擇。全局路由守衛集中管理,易于維護;組件級別權限控制更靈活,適合復雜場景。選擇哪種方式取決于項目的具體需求和復雜度。SSR 也是一種選擇,但會增加項目的復雜度。

如何處理異步權限驗證

權限驗證往往需要從服務器獲取用戶信息,這是一個異步過程。在全局路由守衛中,可以使用 async/await 或 promise 來處理異步權限驗證。

// Vue Router 示例 router.beforeEach(async (to, from, next) => {   if (to.meta.requiresAuth) {     const isLoggedIn = localStorage.getItem('token');      if (!isLoggedIn) {       next('/login');       return;     }      try {       // 假設 getUserInfo 是一個異步函數,用于從服務器獲取用戶信息       const user = await getUserInfo();       // 將用戶信息存儲到 Vuex 或其他狀態管理工具中       store.commit('setUser', user);       next();     } catch (error) {       // 處理錯誤,例如 token 過期       localStorage.removeItem('token');       next('/login');     }   } else {     next();   } });

如何避免路由攔截的死循環?

路由攔截的死循環通常發生在重定向到登錄頁時,登錄頁又需要登錄才能訪問。為了避免這種情況,可以在路由守衛中判斷當前是否已經位于登錄頁,如果是,則直接放行。

// Vue Router 示例 router.beforeEach((to, from, next) => {   if (to.path === '/login') {     next(); // 如果已經在登錄頁,則直接放行     return;   }    if (to.meta.requiresAuth) {     const isLoggedIn = localStorage.getItem('token');      if (!isLoggedIn) {       next('/login');     } else {       next();     }   } else {     next();   } });

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享