Solon + EasyQuery + ElementPlus 实现后台管理系统之 08-权限认证优化
AI 摘要
文章聚焦 Solon + EasyQuery + ElementPlus 后台管理系统的按钮级权限优化:前端用 Pinia 仓库存储用户权限标识,封装 hasPerms 方法,在模板中 v-if 控制按钮显隐;后端基于 Sa-Token 实现 StpInterface 返回权限集合,并用 @SaCheckPermission 注解做 API 级校验,实现前后端一致的细粒度权限闭环,防止越权并提升体验。
精确到按钮级别的权限认证
基础原理
按钮级权限控制不是锦上添花,而是保障系统安全和用户体验的刚需,原因在于:
- 数据安全与操作合规:不同角色的用户能执行的操作不同(比如普通员工只能查看数据,管理员能删除 / 编辑),如果仅做页面级权限,用户可能通过伪造请求(比如绕过前端手动调接口)执行越权操作,按钮级控制能从前端直接屏蔽非法操作入口,减少恶意请求。
- 提升用户体验:避免给用户展示看得见但点不了的按钮,或点击后提示无权限的尴尬场景,让界面只显示用户真正能操作的功能,降低使用困惑。
- 统一权限逻辑:前端和后端权限规则对齐,避免前端显示按钮但后端拒绝请求的不一致问题,减少前后端联调成本。
前端实现按钮级别的权限认证的核心逻辑:先获取用户权限标记集合 ->在渲染按钮时校验权限 -> 最终决定按钮是否显示/禁用。
前端优化
编写登录用户数据仓库(store/currentUser.js),存储当前登录用户权限标记列表:
import {ref, computed, reactive} from 'vue'
import { defineStore } from 'pinia'
export const useCurrentUserStore = defineStore('currentUser', () => {
// 登录用户信息实体
let currentUser = reactive({})
// 当前用户菜单列表
let currentMenu = reactive([])
// 当前用户权限标记
let currentPerms = reactive([])
// 设置登录用户信息实体
function setCurrentUser(currentUser) {
this.currentUser = currentUser
}
// 设置当前用户菜单列表
function setCurrentMenu(currentMenu) {
this.currentMenu = currentMenu
}
// 设置当前用户权限标记
function setCurrentPerms(currentPerms) {
this.currentPerms = currentPerms
}
function hasPerms(identifier) {
// 判断当前用户是否拥有指定权限标记
return this.currentPerms.includes(identifier)
}
return { currentUser, setCurrentUser, currentMenu, setCurrentMenu, currentPerms, setCurrentPerms, hasPerms }
})编写权限工具类(plugins/PermsUtil.js),优化将用户权限标记存储到仓库中方法:
// 将用户权限菜单存储到仓库中
useCurrentUserStore().setCurrentMenu(toTreeList(response.data, false))
// 将用户权限标记存储到仓库中(包含所有类型的权限)
useCurrentUserStore().setCurrentPerms(response.data.map(perm => perm.identifier))编写页面组件,完善按钮级别的权限认证:
<el-button type="warning" @click="showAddDialog" v-if="useCurrentUserStore().hasPerms('system:users:add')">
添加用户
</el-button>在浏览器中测试:
后端 API 的权限认证
基础原理
参考文档:https://sa-token.cc/doc.html#/use/jur-auth、https://sa-token.cc/doc.html#/use/at-check
后端 API 是系统数据和业务操作的唯一入口,前端权限认证仅为体验层防护,后端权限认证才是真正的安全兜底,原因在于:
- 防越权操作:前端权限可被轻易绕过(比如通过 Apifox、抓包工具直接调用 API,或修改前端代码),如果后端不校验权限,恶意用户能执行删除数据、修改配置等高危操作,直接威胁系统安全。
- 符合业务规则:不同角色的用户本就该有不同操作范围(如普通员工只能查数据,管理员能删数据),API 权限认证是业务规则在后端的落地,确保什么人能做什么事。
- 降低系统风险:即使前端漏洞导致权限控制失效,后端的权限校验仍能拦截非法请求,避免单点漏洞引发全系统风险。
后端 API 实现权限认证的核心逻辑:登录生成身份凭证 Token -> 接口调用时校验凭证有效性并关联用户 -> 查询用户权限集合与 API 权限要求匹配 -> 匹配成功放行/失败拦截。
后端优化
编写权限认证是嫌累(cn.duozai.sadmin.config.StpInterfaceImpl),返回一个账号所拥有的权限码集合:
/**
* SaToken权限认证实现类
*/
@Component
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一个账号所拥有的权限码集合
* @visduo
*
* @param loginId 登录id
* @param loginType 登录类型
* @return 权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
// 从会话中获取权限列表(获取当前登录用户权限列表时存入)
List<PermsEntity> permsList = (List<PermsEntity>) StpUtil.getSession().get("perms");
// 遍历权限列表,获取权限标识列表
List<String> identifierList = new ArrayList<>();
for (PermsEntity permsEntity : permsList) {
identifierList.add(permsEntity.getIdentifier());
}
// 返回权限标识列表
return identifierList;
}
/**
* 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
* @visduo
*
* @param loginId 登录id
* @param loginType 登录类型
* @return 角色标识集合
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
return new ArrayList<>();
}
}编写控制器,完善方法级别的权限认证:
@SaCheckPermission("system:users:add") // 注解校验
@Post
@Mapping("/add")
public ResponseResult add() {
// ...
}
如无特殊说明,网站中的系列文章均为作者「@多仔」原创编辑,版权归作者「@多仔」所有,资源引用部分已注明来源,AIGC 创作部分已注明标识,拒绝未经授权的任何个人或组织以任何形式转载、复制、修改、发布或用于商业目的。
文章中可能会存在些许错别字内容描述不完整、表述不准确、排版布局异常等问题,文章中提及的软件、依赖、框架等程序可能随其版本更新迭代而产生变化,文章中的相关代码片段、例图、文本等内容仅供参考。
如若转载,请注明出处:https://www.duox.dev/post/139.html
文章中可能会存在些许错别字内容描述不完整、表述不准确、排版布局异常等问题,文章中提及的软件、依赖、框架等程序可能随其版本更新迭代而产生变化,文章中的相关代码片段、例图、文本等内容仅供参考。
如若转载,请注明出处:https://www.duox.dev/post/139.html
- 上一篇:Stable Diffusion AIGC 视觉设计实战教程之 09-ControlNet 插件
- 下一篇:没有了