当前位置: 首页
AI教程
AI从零搭建用户权限系统的全流程记录

AI从零搭建用户权限系统的全流程记录

热心网友 时间:2026-06-24
转载

AI 从零搭建用户权限系统:完整过程复盘与经验分享

分享一次真实的开发实践:从空白仓库起步,借助 AI 从零构建了一套完整的 RBAC 权限管理系统。

我让 AI 从零做了一个用户权限系统,这是全过程记录

技术选型为:前端 Vue,后端 Java 17 + Spring Boot 3,数据库 MySQL,权限认证采用 SaToken。核心功能涵盖用户登录、用户管理、角色管理、权限分配与操作审计日志等模块。

如果按照传统方式,这个任务通常需要数天手动完成:设计数据库表结构、编写实体类、Service 层、Controller 层、单元测试,随后还要进行代码评审和修复 Bug。这次我决定尝试全新路径——让 Claude 从需求分析到代码生成完整跑通,同时验证之前总结的规则管理方法在实际项目中的可行性。

第一阶段:明确需求与方案规划

面对这类需求,直接让 AI 编写代码往往适得其反。对于涉及多个文件改动的任务,首要步骤是使用 /plan 指令让其生成规划方案——这是此前经验的教训:中途发现方向错误导致上下文失效,不得不重新开始。两次惨痛经历后,再也不敢跳过规划阶段。

首先让 Claude 读取现有项目代码结构,随后将需求提交给它:

/plan 这是一个AI开发一个rbac系统示例,现在处于刚刚初始化仓库,还没进行任何开发的状态。前端可以使用vue,后端使用ja va,版本使用17,数据库使用mysql。增加用户登录、用户管理与权限管理功能。RBAC 权限系统,要求:- 支持用户多角色分配- 基于角色的细粒度权限控制- 权限校验用 AOP 拦截,不在每个方法里手写- 角色和权限变更必须记录审计日志- 数据库用 MySQL

AI 对比分析了三种实现方案:

  1. 基于经典 RBAC 模型:用户关联角色,角色关联权限点,标准方案
  2. 基于策略模式:每个权限定义独立策略类,灵活性高但实现成本较大
  3. 基于 Spring Expression Language (SpEL):通过表达式动态定义权限,灵活但复杂度较高

最终选择了第一种方案。理由充分:RBAC 是行业标准,SaToken 原生支持角色与权限判断,团队其他成员易于接手。后两种方案虽灵活性更高,但学习成本显著增加,并非适用于所有场景。

确定方向后,Claude 将方案拆解为按依赖关系排序的任务清单:

1. 设计数据模型(User-Role-Permission 五张关系表)2. 写实体类和 Mapper(MyBatis-Plus)3. 写 Service 层(权限校验、角色分配)4. 写 AOP 拦截器(基于注解的权限校验)5. 写 Controller(用户/角色/权限 CRUD)6. 写审计日志7. 写全局异常处理

该清单作为后续开发的“施工蓝图”,每完成一项,进展一目了然。

第二阶段:定规则

这次没有采用三层规则分层,仅使用一个 CLAUDE.md 文件。原因很简单:该权限模块是一次性开发任务,并非需要长期维护的独立子系统。专门为其创建 L3 文件,后期维护成本可能超过收益。

CLAUDE.md 中的核心规则:

## 技术栈- Ja va 17, Spring Boot 3.x- MyBatis-Plus 3.5.x, SaToken 1.38.x- Hutool 5.8.x, Lombok 1.18.x## 代码规范- 使用 @RequirePermission 注解 + AOP 做权限校验- 禁止在 Controller 方法体内写权限判断逻辑- 使用 BusinessException 抛业务异常- 统一用 ApiResponse 包装返回结果## 查询规范- 使用 MyBatis-Plus LambdaQueryWrapper- 禁止手写 SQL 字符串拼接

核心原则:如果你不把规则说清楚,AI 就会按照其训练数据(全网代码平均值)来执行,而非你的团队规范。经历过多次踩坑后,规则文件的重要性不言而喻。

第三阶段:开始写代码

数据模型

先执行 /init 让 Claude 确认项目结构,然后从任务 1 开始。

RBAC 标准数据模型包含 5 张表:

┌─────────┐┌──────────────┐ ┌─────────┐│t_user │ ────▶│ t_user_role│◀────│ t_role││(用户)││(用户-角色)│ │(角色)│└─────────┘└──────────────┘ └────┬────┘│┌─────────────────┐│t_role_permission││ (角色-权限)│└─────────────────┘│ ┌──────┴─────┐ │t_permission│ │ (权限)│ └────────────┘

Claude 生成的实体类采用 MyBatis-Plus 注解,而非 JPA——这也得益于 CLAUDE.md 中提前明确了技术栈。以下是实际代码:

@Data@TableName("user_role")public class UserRole {@TableId(type = IdType.AUTO)private Long id;@TableField("user_id")private Long userId;@TableField("role_id")private Long roleId;@TableField(value = "create_time", fill = FieldFill.INSERT)private LocalDateTime createTime;}

使用 MyBatis-Plus 的最大优势是不必担心 EAGER/LAZY 加载策略——每次查询均为主动调用,N+1 问题通过手动优化查询逻辑来规避,后续会谈到这一点。

AOP 权限拦截器

先看 AOP 部分,这是权限系统的核心。

@RequirePermission 注解定义得非常简洁:

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface RequirePermission {/** * 权限标识,格式为 "resource:action" */String value();}

切面实现如下:

@Slf4j@Aspect@Component@RequiredArgsConstructorpublic class PermissionAspect {private final PermissionService permissionService;@Around("@annotation(requirePermission)")public Object checkPermission(ProceedingJoinPoint joinPoint,RequirePermission requirePermission) throws Throwable {if (!StpUtil.isLogin()) {throw new PermissionDeniedException("未登录或登录已过期");}String permissionCode = requirePermission.value();long userId = StpUtil.getLoginIdAsLong();boolean hasPermission = permissionService.hasPermission(userId, permissionCode);if (!hasPermission) {log.warn("用户 {} 尝试访问权限 {} 被拒绝", userId, permissionCode);throw new PermissionDeniedException("没有权限执行此操作");}return joinPoint.proceed();}}

用法是在 Controller 方法上直接添加注解:

@RequirePermission("role:create")@PostMappingpublic ApiResponse createRole(@Valid @RequestBody CreateRoleRequest request) {Role role = roleService.createRole(request);auditLogService.logAudit(...);return ApiResponse.success(role);}

这部分 Claude 生成的质量非常高。AOP + 自定义注解是 Spring 生态的标准模式,训练数据中样本充足。它主动使用了 SaToken 的 StpUtil.isLogin() 做登录检查,说明 AI 确实读取了项目的依赖配置。

权限校验的 Service 层

这里是第一个值得深入讨论的地方。

AI 生成的 hasPermission 方法:

@Overridepublic boolean hasPermission(Long userId, String permissionCode) {// 获取用户所有角色List roleCodes = userRoleService.getUserRoleCodes(userId);if (roleCodes.isEmpty()) {return false;}// 获取用户所有角色的权限List userPermissions = getUserPermissionCodes(userId);return userPermissions.contains(permissionCode);}

然后是 getUserPermissionCodes 的具体实现:

@Overridepublic List getUserPermissionCodes(Long userId) {List roles = userRoleService.getUserRoles(userId);if (CollUtil.isEmpty(roles)) {return List.of();}Set permissions = new HashSet<>();for (Role role : roles) {if (role.getStatus() != 1) continue;List permissionIds = rolePermissionService.getPermissionIdsByRoleId(role.getId());if (!permissionIds.isEmpty()) {List perms = listByIds(permissionIds);perms.stream().filter(p -> p.getStatus() == 1).map(Permission::getCode).forEach(permissions::add);}}return List.copyOf(permissions);}

这段代码实际上隐藏着一个 N+1 查询问题。对每个角色都需要调用 getPermissionIdsByRoleId,再对每个角色调用 listByIds 批量查询权限。假设用户有 3 个角色,意味着 6 次数据库查询(3 次查权限 ID + 3 次批量查权限详情)。

不过该项目是个人演示项目,数据量较小,暂时无需过度优化。如果用于真实生产环境,一定会要求 AI 改为一次 JOIN 查询或使用 IN 子句批量查询——这也是此前文章反复强调的:AI 不会主动考虑数据量增长后的性能问题。

审计日志

审计日志部分值得注意。AI 最初方案采用 AOP 切面自动记录,后来改为在 Controller 中手动调用 auditLogService.logAudit()

原因非常实际:AOP 切面虽然看似省事,但难以记录变更前后的具体值。例如“将用户从‘普通用户’改为‘管理员’”这类关键信息,AOP 只能获取方法名和参数,无法获取变更前的数据。手动调用虽然多写几行代码,但记录精度完全不在同一量级。

最终的 AuditLog 实体:

@Data@TableName("audit_log")public class AuditLog {@TableId(type = IdType.AUTO)private Long id;@TableField("operator_id")private Long operatorId;@TableField("operator_name")private String operatorName;@TableField("action")private String action;@TableField("target_type")private String targetType;@TableField("target_id")private Long targetId;@TableField("detail")private String detail;@TableField("ip_address")private String ipAddress;@TableField(value = "create_time", fill = FieldFill.INSERT)private LocalDateTime createTime;}

Controller 中调用的方式:

auditLogService.logAudit(StpUtil.getLoginIdAsLong(),StpUtil.getLoginIdAsString(),AuditAction.CREATE_ROLE.name(),"role",role.getId(),"创建角色: " + role.getName(),null);

AI 开发很少能一把过

整个权限模块的代码,从写完到正常运行,中间经历了多次调整。这其实是常态——借助 AI 编写代码时,一次需求描述清楚、AI 一次生成完毕、你一次评审通过,这种理想情况在实际中很少出现。

原因并不复杂:AI 不会主动考虑边界场景。当指示它“构建一套 RBAC 权限系统”时,它会提供标准 RBAC 实现,但标准实现并不一定契合你的项目。

本次主要反复调整集中在以下几个问题:

技术栈对齐

最初 AI 生成的代码混用了 JPA 和 MyBatis-Plus 两种 ORM——部分实体使用了 @Entity,部分使用了 @TableName。根本原因在于初始 CLAUDE.md 中未明确技术栈,AI 依据其训练数据默认选择了 JPA(Spring Boot 教程中 JPA 出现频率较高)。

在 CLAUDE.md 中添加“使用 MyBatis-Plus 3.5.x,禁止使用 JPA”之后,后续生成的代码统一了。

审计日志的记录方式

如前所述,AI 最初使用 AOP 切面自动记录审计日志,看似便捷,实际效果是信息过于粗糙——只能记录方法名,无法获取变更前后的具体值。

改为在 Controller 中手动调用后,每条审计日志的 detail 字段都能清晰描述具体操作,信息含量完全不同。

异常处理统一化

AI 生成的 Controller 中,部分地方抛出 RuntimeException,部分直接返回 null。在 CLAUDE.md 中添加“使用 BusinessException 抛业务异常”后,又编写了 GlobalExceptionHandler 进行统一处理:

@RestControllerAdvicepublic class GlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public ApiResponse handleBusinessException(BusinessException e) {return ApiResponse.error(e.getCode(), e.getMessage());}@ExceptionHandler(PermissionDeniedException.class)public ApiResponse handlePermissionDenied(PermissionDeniedException e) {return ApiResponse.error(403, e.getMessage());}}

需求写得越细,后面改的次数就越少

回顾这三个问题,均非技术难题,完全是“初始需求描述不够细化”所致。

现在养成了一种习惯:在让 AI 写代码之前,先花 10 分钟将需求细化到“无需追问”的程度。并非需要长篇大论的文档,而是在对话中清晰列出关键点:

/implement 按任务清单实现权限模块,注意以下几点:1. 使用 MyBatis-Plus,禁止使用 JPA2. 权限校验用 @RequirePermission 注解 + AOP 拦截3. 统一用 BusinessException 抛业务异常4. 审计日志在 Controller 里手动调用 logAudit 记录5. 所有返回结果用 ApiResponse 包装

这些点看似理所当然(如“使用 MyBatis-Plus”“抛 BusinessException”),但若不明确说明,AI 不会主动执行。AI 并非不懂 MyBatis-Plus,而是不知道你的项目已选定技术栈,需要遵循约定。

需求越细化,修改次数越少,上下文 token 浪费也越少。这个道理与带新人的经验一致:交代任务时若不明确,新人做出来的结果必然偏离预期,进而反复沟通,双方疲惫。

几个核心判断

完整流程跑下来,真正发挥价值的环节如下:

做得好的:

  • 数据模型设计——标准 RBAC 模型,AI 生成的表结构和关联关系未出现错误
  • 实体类和 Mapper——MyBatis-Plus 代码是 AI 最擅长的领域,生成质量与手写无显著差异
  • AOP 拦截器——标准模式,训练数据充足,一次编写正确
  • 全局异常处理——RestControllerAdvice 模板代码,AI 生成得十分完整

必须由人工完成:

  • 方案选择(RBAC vs 策略模式 vs SpEL)——属于架构决策,AI 只能列出选项,最终选择需要人拍板
  • 技术栈对齐——AI 默认混用 JPA/MyBatis,需要人员提前明确说明
  • 审计日志的记录方式——AOP 自动记录还是手动调用,这需要业务判断,而非单纯技术选择
  • 异常类型的统一化——AI 会混用 RuntimeException 与自定义异常,需要人工规范

AI 将标准任务处理得又快又好,但非标准的坑仍需自己趟过。将经验写入规则文件后,下次 AI 便不会再犯。这个闭环跑通后,开发效率确实显著提升。

来源:https://juejin.cn/post/7653410900831895579

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
阿里云Qoder CN灵码AI助手免费版及credits计费指南

阿里云Qoder CN灵码AI助手免费版及credits计费指南

阿里云QoderCN(原通义灵码)是一款AI智能编码助手,提供IDE插件、独立IDE等形态,覆盖编码及日常办公场景。产品分个人社区版(免费)、个人专业版、企业标准版和企业VPC版,采用Credits计费模式,支持多种AI模型。

时间:2026-07-06 16:30
基于大模型的城市文旅知识图谱构建与内容分发

基于大模型的城市文旅知识图谱构建与内容分发

大模型构建城市知识图谱时优先采信权威信源。贵港西江传媒联合《度假旅游》杂志,通过本地采编、期刊发布、阿里云多平台分发模式,产出产业文旅等结构化内容,提升AI知识库收录权重,为城市品牌长效传播提供可复制路径。

时间:2026-07-06 16:30
贵州文旅AIGEO内容运营本地媒体落地实践

贵州文旅AIGEO内容运营本地媒体落地实践

针对贵州文旅行业在阿里云平台的内容运营痛点,总结合规发文规则,包括弱化营销、避免引流信息与极限词。以《度假旅游杂志》在贵阳设立本地化运营站点为例,为黔域文旅商家产出合规原创内容,提升AI平台收录权重。同时指出商家常踩的审核红线,强调以干货分享获取自然流量。

时间:2026-07-06 16:29
阿里内部禁用Claude Code OpenCode成替代方案

阿里内部禁用Claude Code OpenCode成替代方案

ClaudeCode对国内用户定向封禁,网传阿里内部已全面禁用。OpenCode作为开源替代,支持接入多种AI模型,通过CCSwitch或手动配置可无缝迁移原有MCP与AgentSkill,规避账号风险。

时间:2026-07-06 16:29
年实测Homebrew安装配置国内源多种安装方式一篇搞定

年实测Homebrew安装配置国内源多种安装方式一篇搞定

Homebrew是macOS上流行的包管理工具,提供pkg安装包、脚本安装和Git克隆等多种安装方式。国内用户推荐使用镜像脚本安装并配置中科大或清华大学镜像源以加速下载。常用命令包括brewinstall安装工具、brewinstall--cask安装图形应用、brewupdate更新及brewdoctor诊断环境。

时间:2026-07-06 16:29
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜