Solon + EasyQuery + ElementPlus 实现后台管理系统之 08-权限认证优化

精确到按钮级别的权限认证

基础原理

按钮级权限控制不是锦上添花,而是保障系统安全和用户体验的刚需,原因在于:

  • 数据安全与操作合规:不同角色的用户能执行的操作不同(比如普通员工只能查看数据,管理员能删除 / 编辑),如果仅做页面级权限,用户可能通过伪造请求(比如绕过前端手动调接口)执行越权操作,按钮级控制能从前端直接屏蔽非法操作入口,减少恶意请求。
  • 提升用户体验:避免给用户展示看得见但点不了的按钮,或点击后提示无权限的尴尬场景,让界面只显示用户真正能操作的功能,降低使用困惑。
  • 统一权限逻辑:前端和后端权限规则对齐,避免前端显示按钮但后端拒绝请求的不一致问题,减少前后端联调成本。

前端实现按钮级别的权限认证的核心逻辑:先获取用户权限标记集合 ->在渲染按钮时校验权限 -> 最终决定按钮是否显示/禁用。

前端优化

编写登录用户数据仓库(store/currentUser.js),存储当前登录用户权限标记列表:

javascript 复制代码
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),优化将用户权限标记存储到仓库中方法:

javascript 复制代码
// 将用户权限菜单存储到仓库中
useCurrentUserStore().setCurrentMenu(toTreeList(response.data, false))

// 将用户权限标记存储到仓库中(包含所有类型的权限)
useCurrentUserStore().setCurrentPerms(response.data.map(perm => perm.identifier))

编写页面组件,完善按钮级别的权限认证:

html 复制代码
<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),返回一个账号所拥有的权限码集合:

java 复制代码
/**
 * 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<>();
    }

}

编写控制器,完善方法级别的权限认证:

java 复制代码
@SaCheckPermission("system:users:add")	// 注解校验
@Post
@Mapping("/add")
public ResponseResult add() {
	// ...
}
相关推荐
没有bug.的程序员2 小时前
负载均衡的真正含义:从算法到架构的深度解析
java·jvm·算法·微服务·架构·负载均衡
yc_xym2 小时前
[项目实践]言聚论坛(后端)
java·项目开发
LambdaCat2 小时前
如何用 Prompt 让 AI 主动发现设计问题
java·ai·ai编程
changlianzhifu12 小时前
分账系统:从“资金管道“到“增长引擎“,重塑商业价值分配新范式
java·服务器·前端
吃喝不愁霸王餐APP开发者2 小时前
Java应用对接美团开放平台API时的HTTPS双向认证与证书管理实践
java·开发语言·https
宠..2 小时前
QButtonGroup
java·服务器·开发语言·前端·数据库·c++·qt
码luffyliu2 小时前
Go 语言并发编程:为何它能甩开 Java 等传统后端语言?
java·后端·golang·go
星火开发设计2 小时前
快速排序详解:原理、C++实现与优化技巧
java·c++·算法·排序算法·快速排序·知识
写代码的【黑咖啡】2 小时前
Python中的文件操作详解
java·前端·python