動態

詳情 返回 返回

打造一個可維護、可複用的前端權限控制方案(含完整Demo) - 動態 詳情

在這裏插入圖片描述

摘要

在現代 Web 應用中,權限控制已經不再是“後端的事”。隨着前後端分離、單頁應用(SPA)流行,前端權限控制逐漸成為用户體驗和系統安全的雙重關鍵。如果只靠後端控制,前端體驗太差;如果只靠前端控制,那就等於裸奔。怎麼權衡?怎麼落地?這就是本文要探討的重點。

引言

你是否遇到過:不同用户登錄後看到的菜單不同、某些按鈕灰了點不了、訪問一些頁面會自動跳轉 403 頁面?這都來自於“前端權限控制”的精細化設計。

現在的權限控制越來越細粒度,除了“角色”之外,還有“操作級”控制。比如同一個頁面裏,有的人能“查看”,有的人能“新增”,還有人只能“導出”。

這一套看似簡單,實則涉及:路由控制、組件控制、權限管理、後端驗證、緩存同步等多個環節。我們接下來就一步步來拆解。

前端權限控制系統設計思路

用户登錄後獲取權限信息

後端返回用户的角色、權限碼等信息,前端登錄成功後將其緩存(如 Vuex、Pinia、localStorage 等)。

示例數據結構

// 登錄成功後後端返回的數據結構
const user = {
  username: 'zsfan',
  role: 'admin',
  permissions: ['user:add', 'user:edit', 'dashboard:view']
};

根據權限控制:路由 + 菜單 + 按鈕

我們可以將權限碼掛載到路由元信息(meta)上,動態控制菜單顯示與頁面訪問權限。

權限路由守衞:不該進的頁面別讓進

動態路由 + 路由守衞實現控制

使用 Vue Router 的 beforeEach 方法做守衞,結合權限碼判斷是否有訪問權限。

示例代碼

// 路由配置中添加權限元信息
{
  path: '/user/add',
  component: () => import('@/views/UserAdd.vue'),
  meta: { permission: 'user:add' }
}
// 路由守衞控制訪問
router.beforeEach((to, from, next) => {
  const permissions = getUserPermissions(); // 從緩存或 Vuex 獲取權限列表
  const required = to.meta.permission;
  if (required && !permissions.includes(required)) {
    next('/403'); // 無權限跳轉403
  } else {
    next();
  }
});

控制按鈕和組件顯示:不該點的按鈕也隱藏掉

v-if + 權限判斷方法

讓按鈕或控件只在有權限時才顯示。

示例代碼

<!-- 只有有 user:add 權限才顯示 -->
<button v-if="hasPermission('user:add')">新增用户</button>
function hasPermission(code) {
  const permissions = getUserPermissions(); // 獲取權限
  return permissions.includes(code);
}

這樣做的好處是,不同用户登錄看到的按鈕完全不同,體驗非常清爽。

後端權限驗證:別信前端,核心操作必須後台校驗

前端權限只是“演戲”,真正的數據操作必須後端判斷權限

Node.js 示例代碼

app.post('/api/user/add', (req, res) => {
  const user = req.user; // 從 token 中解析的用户信息
  if (!user.permissions.includes('user:add')) {
    return res.status(403).json({ message: '你沒有新增用户的權限' });
  }
  // 有權限,正常處理
  res.json({ message: '新增成功' });
});

典型場景實戰

場景一:菜單根據權限動態渲染

// 動態生成菜單
const allMenus = [
  { name: '用户管理', path: '/user', permission: 'user:view' },
  { name: '添加用户', path: '/user/add', permission: 'user:add' }
];

const userMenus = allMenus.filter(menu =>
  user.permissions.includes(menu.permission)
);

場景二:按鈕級權限控制

有些功能你不希望每個員工都能用,比如“導出數據”、“重置密碼”——用權限碼控制按鈕顯示。

<button v-if="hasPermission('user:reset')">重置密碼</button>
<button v-if="hasPermission('user:export')">導出數據</button>

場景三:前端組件封裝權限指令(Vue自定義指令)

// 自定義權限指令 v-permission
app.directive('permission', {
  mounted(el, binding) {
    const permissions = getUserPermissions();
    if (!permissions.includes(binding.value)) {
      el.parentNode && el.parentNode.removeChild(el);
    }
  }
});
<!-- 使用 -->
<button v-permission="'user:edit'">編輯</button>

QA 問答環節

Q1:前端控制是不是多餘,反正後端也會攔?

不是。前端權限主要是提升用户體驗,讓用户不去點那些不能點的東西;後端才是真正的防線,負責攔截非法訪問。

Q2:權限碼應該放在哪管理?

建議所有權限碼統一定義和管理,比如:

// permission-codes.js
export const PERMISSIONS = {
  USER_ADD: 'user:add',
  USER_EDIT: 'user:edit',
  DASHBOARD_VIEW: 'dashboard:view'
};

這樣方便維護,防止拼寫錯誤。

Q3:權限緩存會不會被篡改?

可以結合 JWT 簽名 + 本地緩存控制,或者通過加密緩存,但要明白:前端緩存不能作為權限依據,只能作為顯示依據

總結

前端權限控制,説簡單也簡單,説複雜也能無限擴展。它的核心原則是:

  1. 前端只控制“界面展示”,不能控制“數據和行為”
  2. 權限要後端返回、前端解析
  3. 所有權限判斷必須同步做“後端驗證”

一個好的權限系統,不僅是安全保障,更是用户體驗的加分項。別再只靠“按鈕v-if”了,從系統架構層去考慮權限管理,才是真正的開發者思維。

user avatar yunxiao0816 頭像
點贊 1 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.