文档目录
glen
· 预计阅读 3 分钟

第 7 章 前端权限控制:按钮该不该显示

本文导航
第 7 章 前端权限控制:按钮该不该显示

第 7 章 前端权限控制:按钮该不该显示

后端负责「能不能做」,前端负责「让不让人看见」。这一章说明 owl-ui 提供的两种权限工具,以及它们的区别。

权限数据从哪来

登录后,前端会:

  1. 保存 accessToken;
  2. 调用 /users/me/permissions 获取权限标识;
  3. 写入 Pinia 的 useUserStore().permissions;
  4. 缓存到 localStorage,TTL 24 小时。

超管拿到的权限是 ["*:*:*"]。

方式一:hasPerms(推荐)

import { hasPerms } from "@bit-labs.cn/owl-ui";

const canCreate = hasPerms("admin:user:Create");

实现逻辑:

export const hasPerms = (value: string | Array<string>): boolean => {
  if (!value) return false;
  const allPerms = "*:*:*";
  const { permissions } = useUserStoreHook();
  if (!permissions) return false;
  if (permissions.length === 1 && permissions[0] === allPerms) return true;
  const isAuths = isString(value)
    ? permissions.includes(value)
    : isIncludeAllChildren(value, permissions);
  return isAuths;
};

要点:

  • 字符串:包含即通过;
  • 数组:要求全部包含才通过;
  • 超管通配符 *:*:* 直接通过;
  • 比较的是后端返回的权限标识,必须完全一致。

在模板里用

<script setup lang="ts">
import { hasPerms } from "@bit-labs.cn/owl-ui";
</script>

<template>
  <el-button
    v-if="hasPerms('admin:user:Create')"
    type="primary"
    @click="openCreate"
  >
    新建用户
  </el-button>
</template>

用 Perms 组件

<script setup lang="ts">
import { Perms } from "@bit-labs.cn/owl-ui";
</script>

<template>
  <Perms value="admin:user:Create">
    <el-button type="primary">新建用户</el-button>
  </Perms>
</template>

Perms 内部就是 hasPerms,通过则渲染插槽,否则不渲染。

方式二:v-auth / Auth(基于路由 meta)

owl-ui 还提供了:

<el-button v-auth="'btn.add'">新增</el-button>
<Auth value="btn.add">
  <el-button>新增</el-button>
</Auth>

它们底层是 hasAuth:

function hasAuth(value: string | Array<string>): boolean {
  const metaAuths = router.currentRoute.value.meta.auths;
  if (!metaAuths) return false;
  return isString(value)
    ? metaAuths.includes(value)
    : isIncludeAllChildren(value, metaAuths);
}

区别:

hasPerms / Perms hasAuth / v-auth / Auth
数据源 登录接口返回的 permissions 当前路由 meta.auths
适合 后端权限标识 前端静态配置的按钮编码
当前后台 菜单数据不含 auths 需要自己在路由 meta 里填

结论:对接 owl-admin 的后端权限时,用 hasPerms 或 Perms。v-auth 更适合前端自己定义一套与后端无关的页面内编码。

权限标识必须与后端一致

前端写:

hasPerms("admin:user:Create");

后端按钮菜单携带:

admin:user:Create

大小写、冒号、方法名都要一致。最常见的错误是前端写路由名 user:create 或中文标题。

隐藏按钮不等于安全

前端隐藏只是体验:

用户看不到按钮 ≠ 用户不能调接口

真正的边界在 PermissionCheck 中间件。如果只做前端隐藏、接口仍是 AccessAuthenticated,用户完全可以手工调接口。

正确组合:

  • 路由用 AccessAuthorized;
  • 角色分配对应按钮菜单;
  • 前端用 hasPerms 隐藏按钮。

常见问题

超管看不到按钮

检查 permissions 是否包含 *:*:*。超管登录后应调用权限接口并写入 store;如果用了旧缓存,清掉 localStorage。

普通用户菜单正常,按钮全没了

按钮菜单没有分配给角色,或前端缓存的权限是空的。先查 /users/me/permissions。

权限改了,页面没变

前端缓存 24 小时。重新登录,或调用 fetchAndCachePermissions() 刷新。

数组写法不生效

hasPerms(["a", "b"]) 要求两个权限都有。只想满足其一,用 hasPerms("a") || hasPerms("b")。

自检

  • [ ] 知道 hasPerms 的数据来自 /users/me/permissions;
  • [ ] 知道数组是「全部满足」;
  • [ ] 知道 v-auth 依赖路由 meta.auths,与后端权限标识不是一回事;
  • [ ] 前端隐藏的同时,后端接口级别正确;
  • [ ] 能处理权限缓存导致的「按钮不更新」。

评论

加载评论中…

上一篇 第 6 章 权限计算与生效:菜单、策略与缓存 下一篇 第 8 章 新模块接入权限与排查手册

BitLabs © 2026 · 论坛讨论 · 博客长文 · 文档手册