【SpringSecurity新手村系列】(7)基于资源权限码(Authority)的接口权限控制实战

简介: 本章完成从“用户-角色-权限资源”数据模型到 `@PreAuthorize` 方法级拦截的完整闭环。和上一章“角色控制(Role)”不同,本章重点是 **资源权限码(Authority)**,即 `clue:list`、`clue:edit` 这类细粒度权限。你将得到一套能直接用于企业项目的权限控制方案,同时规避 `Controller 未注册`、`Mapper SQL 字段写错`、`权限码字段映射错位` 等高频坑位。

第七章 基于资源权限码(Authority)的接口权限控制实战

本章完成从“用户-角色-权限资源”数据模型到 @PreAuthorize 方法级拦截的完整闭环。和上一章“角色控制(Role)”不同,本章重点是 资源权限码(Authority),即 clue:listclue:edit 这类细粒度权限。你将得到一套能直接用于企业项目的权限控制方案,同时规避 Controller 未注册Mapper SQL 字段写错权限码字段映射错位 等高频坑位。


一、问题切入:为什么从角色升级到资源权限

在 RBAC 的第一阶段,我们常用 hasRole('ADMIN') 做控制,这对“大权限分层”足够,但在真实业务里会出现三个痛点:

  1. 同一角色下能力差异大:同是运营角色,有人可导出、有人只能查看
  2. 接口粒度需要更细/api/clue/list/api/clue/edit/api/clue/del 权限应独立
  3. 角色扩展会爆炸:用角色拼业务能力会导致角色数量快速膨胀

因此,本章采用更细粒度的控制方式:

  • 角色负责“人群分组”
  • 权限码(Authority)负责“具体动作授权”

也就是:用户 -> 角色 -> 资源权限码 -> 接口拦截


二、权限模型与调用链

从项目结构看,本章已经具备“权限码驱动授权”的核心骨架:

  • Users 实现 UserDetails,并在 getAuthorities() 返回权限集合
  • PermissionsMapper.selectByUserId 负责查出用户拥有的权限
  • ClueController 使用 @PreAuthorize("hasAuthority('...')") 做方法级权限控制
  • SecurityConfig 已开启 @EnableMethodSecurity

整体链路如下:

登录 -> UserServiceImpl.loadUserByUsername()
    -> 查询用户 permissionsList
    -> Users.getAuthorities() 转成 GrantedAuthority
    -> 放入 Authentication
    -> 调用接口时 @PreAuthorize(hasAuthority(...)) 匹配

只要这条链每一环都打通,方法级鉴权就能稳定生效。


三、核心代码解读(按实际项目)

3.1 开启方法级权限拦截

SecurityConfig 上的配置是关键总开关:

@EnableMethodSecurity
@Configuration
public class SecurityConfig {
   
    // ...
}

没有这个注解,@PreAuthorize 不会生效。

同时项目里保留了通用登录校验:

.authorizeHttpRequests((authorizeHttpRequests) ->{
   
    authorizeHttpRequests
        .requestMatchers("/tologin", "/common/captcha").permitAll()
        .anyRequest().authenticated();
})

意思是:先保证“必须登录”,再在方法层做“是否有某个资源权限码”。

3.2 用户权限装载:从数据库到 GrantedAuthority

UserServiceImpl 在登录时装载用户权限:

List<Permissions> permissionsList = permissionsMapper.selectByUserId(users.getId());
users.setPermissionsList(permissionsList);
return users;

Users#getAuthorities() 再把 permissionsList 转为 Spring Security 可识别的权限集合:

for (Permissions permissions : this.permissionsList) {
   
    authorities.add(new SimpleGrantedAuthority(permissions.getCode()));
}

注意这里的关键点:传给 SimpleGrantedAuthority 的必须是最终参与匹配的权限码字符串

3.3 方法级权限控制写法

ClueController 采用资源权限码做拦截:

@PreAuthorize("hasAuthority('clue:list')")
@RequestMapping("/api/clue/list")
public String clueList(){
   
    return "clueList";
}

@PreAuthorize("hasAnyAuthority('clue:export','clue:download')")
@RequestMapping("/api/clue/export")
public String clueExport(){
   
    return "clueExport";
}

这套写法比 hasRole 更细,能够直接落到业务动作级别。


四、ss07 当前实现里的关键坑位(必须修)

下面这些是我根据你的 ss07 源码直接定位出的实战问题。

4.1 ClueController 缺少 @Controller 注解

当前类定义只有:

public class ClueController {
   

没有 @Controller@RestController,Spring 不会注册该 Bean,@PreAuthorize 自然也不会触发。

建议改为:

@Controller
public class ClueController {
   

4.2 Users.getAuthorities() 使用了不存在的字段 permissions.getCode()

Permissions 实体字段是:

  • permKey
  • permName
  • permType
  • path
  • method

并没有 code 字段,因此当前代码会编译失败或运行异常。应改为:

authorities.add(new SimpleGrantedAuthority(permissions.getPermKey()));

并保证数据库 perm_key 存的就是 clue:listclue:edit 等权限码。

4.3 PermissionsMapper.xml SQL 有别名与字段拼写错误

当前 SQL 片段:

from permissions
left join role_permissions rp on p.id = rp.premission_id

问题有两个:

  1. permissions 没有起别名 p,却用了 p.id
  2. premission_id 疑似拼写错误(常见应为 permission_id

建议修正示例:

select p.*
from permissions p
left join role_permissions rp on p.id = rp.permission_id
left join roles r on rp.role_id = r.id
left join user_roles ur on r.id = ur.role_id
where ur.user_id = #{id}

4.4 LoginInfoUtil 强转有风险

当前实现直接:

return (Users) authentication.getPrincipal();

未登录或匿名场景会触发类型转换异常。建议加空值和类型判断。


五、推荐的“资源权限控制”标准写法

5.1 数据层建议

permissions 表建议至少包含:

  • perm_key:权限码(如 clue:list
  • perm_name:权限名称(如“线索查看”)
  • pathmethod:可选,用于审计或动态鉴权

并通过 role_permissions 建立角色到权限资源的关联。

5.2 代码层建议

  1. 登录阶段只做一次权限装载
  2. 统一用 hasAuthority / hasAnyAuthority 控制动作权限
  3. 接口命名和权限码保持一致规则(资源:动作)

示例:

clue:list
clue:view
clue:add
clue:edit
clue:del
clue:export

5.3 命名规范建议

  • 推荐统一:模块:动作
  • 动作用有限集合:list/view/add/edit/del/export/approve
  • 不要混用大小写,统一小写,降低误配风险

六、与角色控制(Role)的区别与配合

维度 Role(角色) Authority(资源权限码)
粒度
典型表达式 hasRole('ADMIN') hasAuthority('clue:edit')
适用场景 模块级入口、菜单级隔离 接口级动作控制
是否自动加前缀 hasRole 自动补 ROLE_ hasAuthority 不补前缀

最佳实践是二者结合:

  • URL 层做基础登录和大粒度限制
  • 方法层做资源动作级控制

七、快速自测清单

  1. 修复 ClueController 注解后,确认 /api/clue/* 能正确映射
  2. 登录普通用户,访问 @PreAuthorize("hasAuthority('clue:list')") 接口,验证放行
  3. 同一用户访问 clue:del,验证 403
  4. 赋予该用户 clue:del 权限后重新登录,验证可通过
  5. 打印 Authentication#getAuthorities(),确认权限码来自 perm_key
  6. 故意写错权限码(如 clue:delete),验证拦截行为符合预期

八、总结

本章的核心目标:基于资源权限码的精细化接口控制。关键不是写了多少注解,而是把“数据库权限码 -> UserDetails 权限集合 -> 方法拦截表达式”这条链打通并保持一致。

如果这条链任一处命名不一致、字段错位、Bean 未注册,权限看起来“写了但不生效”。反过来,一旦链路统一,你就能非常稳定地扩展到更多模块(客户、合同、回款、审批等),并把安全控制从“角色粗分”升级为“动作级可审计控制”。


编辑者:Flittly
更新时间:2026年4月

目录
相关文章
|
6天前
|
缓存 人工智能 自然语言处理
我对比了8个Claude API中转站,踩了不少坑,总结给你
本文是个人开发者耗时1周实测的8大Claude中转平台横向评测,聚焦Claude Code真实体验:以加权均价(¥/M token)、内部汇率、缓存支持、模型真实性及稳定性为核心指标。
2486 17
|
18天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
本文介绍了Claude Code终端AI助手的使用指南,主要内容包括:1)常用命令如版本查看、项目启动和更新;2)三种工作模式切换及界面说明;3)核心功能指令速查表,包含初始化、压缩对话、清除历史等操作;4)详细解析了/init、/help、/clear、/compact、/memory等关键命令的使用场景和语法。文章通过丰富的界面截图和场景示例,帮助开发者快速掌握如何通过命令行和交互界面高效使用Claude Code进行项目开发,特别强调了CLAUDE.md文件作为项目知识库的核心作用。
15945 47
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
|
24天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
34944 57
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
13天前
|
人工智能 JavaScript Ubuntu
低成本搭建AIP自动化写作系统:Hermes保姆级使用教程,长文和逐步实操贴图
我带着怀疑的态度,深度使用了几天,聚焦微信公众号AIP自动化写作场景,写出来的几篇文章,几乎没有什么修改,至少合乎我本人的意愿,而且排版风格,也越来越完善,同样是起码过得了我自己这一关。 这个其实OpenClaw早可以实现了,但是目前我觉得最大的区别是,Hermes会自主总结提炼,并更新你的写作技能。 相信就冲这一点,就值得一试。 这篇帖子主要就Hermes部署使用,作一个非常详细的介绍,几乎一步一贴图。 关于Hermes,无论你赞成哪种声音,我希望都是你自己动手行动过,发自内心的选择!
3051 29
|
2天前
|
云安全 人工智能 安全
|
3天前
|
人工智能 测试技术 API
阿里Qwen3.6-27B正式开源:网友直呼“太牛了”!
阿里云千问3.6系列重磅开源Qwen3.6-27B稠密大模型!官网:https://t.aliyun.com/U/JbblVp 仅270亿参数,编程能力媲美千亿模型,在SWE-bench等权威基准中表现卓越。支持多模态理解、本地部署及OpenClaw等智能体集成,已开放Hugging Face与ModelScope下载。
|
2天前
|
机器学习/深度学习 缓存 测试技术
DeepSeek-V4开源:百万上下文,Agent能力比肩顶级闭源模型
DeepSeek-V4正式开源!含V4-Pro(1.6T参数)与V4-Flash(284B参数)双版本,均支持百万token上下文。首创混合注意力架构,Agent能力、世界知识与推理性能全面领先开源模型,数学/代码评测比肩顶级闭源模型。
1320 6