TRAE 实战:Spring Boot JWT 认证授权系统全流程开发

TRAE 实战:Spring Boot JWT 认证授权系统全流程开发

本文作者:天天摸鱼的 java 工程师

🎯 先看效果图

这篇文章不搞虚的,全程实战 ------ 从 PRD 转技术文档,到接口设计、代码生成、测试验证,再到实际运行效果,一步步带你看 AI 如何帮我们省下 80% 的重复工作,让认证授权开发从 "耗时活" 变成 "轻松活"。不管是新项目搭建权限体系,还是旧项目安全改造,跟着走就能直接复用!

1. 系统登录页面

访问系统入口首先进入登录界面,支持输入测试账号(如admin/admin123)发起认证请求:

2. 管理员仪表盘

登录成功后自动跳转至个人仪表盘,展示当前用户角色(如ROLE_ADMIN),并支持测试不同权限的 API 接口(如图中 "测试受保护接口" 仅管理员可正常访问):

🚀 第一步:AI 开发四步法

这个需求抓得很准,直击前后端分离项目的核心安全痛点!核心结论:借助 TRAE 辅助开发,基于 Spring Boot+JWT+Spring Security 可快速落地一套完整的认证授权系统,支持自定义权限注解和细粒度访问控制,项目到手即跑、可直接复用。

AI 辅助认证授权开发的完整流程清晰高效:

  1. 需求分析与技术文档转换:将产品安全需求转化为结构化技术文档,明确认证方式、权限粒度和验收标准
  2. 接口设计与数据建模:定义 RESTful API 协议、用户权限数据模型,兼顾安全性和扩展性
  3. 代码生成与业务逻辑实现:AI 生成基础配置、工具类和 CRUD 代码,人工聚焦 JWT 核心逻辑、权限注解和安全校验
  4. 测试验证与文档同步:生成单元测试和集成测试用例,自动同步接口文档和配置说明

🎯 第二步:核心思路

人机合理分工是高效落地的关键:

我们负责:

  • 架构决策:确定认证方案(JWT 无状态)、权限模型(RBAC 基础)、技术栈组合(Spring Boot+Spring Security+JPA+H2)
  • 核心逻辑实现:自定义权限注解、JWT Token 生成 / 解析 / 刷新机制、AOP 权限切面、安全过滤器链配置
  • 代码 review:把控加密算法安全性、权限校验逻辑严谨性、代码规范一致性,规避安全漏洞

TRAE 负责:

  • 重复劳动:生成 Spring Security 配置类、JWT 工具类、数据库实体 / Repository、控制器基础代码
  • 文档同步:自动更新接口文档、项目结构说明、测试数据清单,保持文档与代码同步
  • 测试用例:生成单元测试(工具类、切面逻辑)和集成测试(接口全流程)代码,覆盖核心场景

📋 第三步:完整工作流

以开发一套通用的 Spring Boot JWT 认证授权系统为例,全程落地可跑:

第四步:需求文档二次加工(关键步骤)

原始 PRD 通常是这样的:"做一套前后端分离的认证授权系统,支持用户注册登录、角色权限控制,接口需要 Token 验证,不同角色能访问不同接口,还要有自定义权限注解"

使用标准化提示词让 TRAE 转换为技术文档,提示词如下:

markdown 复制代码
这是原始需求文档@auth需求.md,请帮我转换为开发可执行的技术文档,按以下格式:
1. 核心实体和关系
2. 主要功能点
3. 认证权限流转规则
4. 接口协议设计
5. 验收标准
原始需求:[粘贴 PRD 内容]

转换结果示例:

JWT 认证授权系统技术需求 v1.0
  1. 核心实体
  • 用户 (User):系统访问主体,包含用户名、密码、角色等核心信息
  • 角色 (Role):权限集合载体,关联用户与具体权限(ADMIN/USER 基础角色)
  • Token:认证凭证,包含用户 ID、角色信息、过期时间等核心字段
  • 权限 (Permission):接口 / 功能访问许可,支持通过注解细粒度控制
  1. 主要功能点
  • 用户注册:新用户提交账号密码,系统加密存储并分配默认角色
  • 用户登录:验证账号密码,生成 Access Token(短期有效)和 Refresh Token(长期有效)
  • 接口认证:所有受保护接口需携带有效 Token,否则拒绝访问
  • 权限控制:基于角色和自定义注解,限制接口访问权限
  • Token 管理:支持 Token 刷新、失效处理,保障系统安全性
  1. 认证权限流转规则未登录状态 → 注册 / 登录 → 生成双 Token → 携带 Token 访问接口 → 过滤器验证 Token 有效性 → AOP 验证权限 → 允许访问 / 返回错误
  2. 验收标准
  • Given 用户名密码正确,When 用户发起登录请求,Then 返回 Access Token 和 Refresh Token,状态码 200
  • Given Token 有效且用户拥有接口权限,When 携带 Token 访问受保护接口,Then 正常返回接口数据
  • Given Token 过期或无效,When 访问受保护接口,Then 返回 401 未授权错误
  • Given Token 有效但用户无接口权限,When 访问受保护接口,Then 返回 403 权限不足错误

第五步:固定提示词与配置

每次与 TRAE 交互时携带固定提示词,确保输出内容一致性:

markdown 复制代码
xxxxxx(具体开发需求)
此外,请务必遵守以下要求:
1. 技术栈版本锁定:Spring Boot 2.7.x、Spring Security 5.7.x、JJWT 0.11.x、JPA 2.6.x、H2 2.2.x
2. 代码遵循 Alibaba Java 开发手册,类名、方法名、变量名符合命名规范,添加中文注释
3. 统一响应格式:所有接口返回 Result 结构体(code: 状态码, msg: 提示信息, data: 响应数据)
4. 密码加密使用 BCryptPasswordEncoder,禁止明文存储
5. 自定义权限注解命名为 @RequiresPermission,支持通过 AOP 切面实现权限校验
6. H2 数据库配置支持控制台访问,数据自动初始化
7. 生成代码包含完整包路径、依赖配置(pom.xml),可直接复制运行
8. 异常统一处理:覆盖 Token 过期、无效、无权限等核心场景,返回友好提示

.TRAE/rules/project_rules.md 配置文件(控制 AI 自动生成文档):

markdown 复制代码
## 基础规约
- 项目编码 UTF-8,Java 版本 8+,Maven 3.6+
- 核心依赖:Spring Boot Starter Web、Spring Boot Starter Security、Spring Boot Starter Data JPA、JJWT、H2 Database、Spring Boot Starter AOP
- 数据库:H2 内存数据库,DDL 自动执行,DML 初始化测试数据
- 安全规范:Token 过期时间(Access Token 30 分钟,Refresh Token 7 天),禁止硬编码密钥

## 自动文档生成
每次完成代码修改后,在 docs/summaries/YYYY-MM-DD/ 目录下生成总结文档,包含:
1. 本次修改的功能点
2. 涉及的文件列表
3. 核心逻辑说明(含关键配置)
4. API 变更记录(新增/修改/删除)
文档命名:HH-MM-SS_auth_summary.md

## 代码质量要求
- 工具类采用单例模式或静态方法,避免重复创建对象
- 所有接口请求参数添加校验注解(@NotNull、@NotBlank 等)
- 安全相关代码(Token 生成、权限校验)必须添加详细注释
- 异常处理通过全局异常处理器统一捕获,禁止分散捕获

第六步:RESTful 接口设计

使用提示词指导 AI 生成 RESTful 接口,提示词如下:

markdown 复制代码
请参考 JWT 认证授权系统技术需求 v1.0,设计完整的 RESTful API 接口,要求:
1. 接口路径符合 RESTful 规范,区分公共接口和受保护接口
2. 包含注册、登录、刷新 Token、查询当前用户信息、测试权限接口等核心功能
3. 定义请求/响应 DTO 实体,添加字段注释和校验注解
4. 标注每个接口的访问权限(公开/需登录/需特定角色/需特定权限)

生成的核心接口示例:

less 复制代码
// 公共接口(无需认证)
@RequestMapping("/api/auth")
public interface AuthController {
    // 用户注册
    @PostMapping("/register")
    Result<UserLoginDTO> register(@RequestBody @Valid UserRegisterDTO registerDTO);
    
    // 用户登录
    @PostMapping("/login")
    Result<UserLoginDTO> login(@RequestBody @Valid UserLoginRequest request);
    
    // 刷新 Token
    @PostMapping("/refresh-token")
    Result<UserLoginDTO> refreshToken(@RequestParam String refreshToken);
}

// 受保护接口(需登录/权限)
@RequestMapping("/api/users")
public interface UserController {
    // 查询当前登录用户信息(需登录)
    @GetMapping("/me")
    Result<UserVO> getCurrentUser();
    
    // 管理员查询所有用户(需 ADMIN 角色)
    @GetMapping("/all")
    @PreAuthorize("hasRole('ADMIN')")
    Result<List<UserVO>> getAllUsers();
    
    // 测试自定义权限(需 user:test 权限)
    @GetMapping("/test-perm")
    @RequiresPermission("user:test")
    Result<String> testPermission();
}

// 请求/响应实体示例
@Data
@Validated
public class UserRegisterDTO {
    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 20, message = "用户名长度需在 3-20 字符之间")
    private String username;
    
    @NotBlank(message = "密码不能为空")
    @Size(min = 6, max = 20, message = "密码长度需在 6-20 字符之间")
    private String password;
    
    @NotBlank(message = "昵称不能为空")
    private String nickname;
}

@Data
public class UserLoginDTO {
    private String accessToken;
    private String refreshToken;
    private Long expiresIn; // Access Token 过期时间(秒)
    private UserVO userInfo;
}

@Data
public class Result<T> {
    private int code;
    private String msg;
    private T data;

    // 成功响应
    public static <T> Result<T> success(T data) {
        return new Result<>(200, "操作成功", data);
    }

    // 错误响应
    public static <T> Result<T> error(int code, String msg) {
        return new Result<>(code, msg, null);
    }
}

第七步:数据库设计

使用提示词生成数据库表结构,提示词如下:

markdown 复制代码
请根据 JWT 认证授权系统技术需求 v1.0,创建 H2 数据库表结构,要求:
1. 包含用户表(存储账号、密码、昵称等)、角色表(基础角色)、用户角色关联表
2. 字段类型合理,添加注释说明,包含审计字段(创建时间、更新时间)
3. 主键使用自增 ID 或 UUID,添加合适索引优化查询
4. 生成初始化测试数据 SQL(管理员和普通用户各 1 个)
5. 支持 H2 数据库语法,可通过 JPA 自动执行

生成的表结构与初始化 SQL 示例:

sql 复制代码
-- 用户表
CREATE TABLE `sys_user` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '用户ID',
  `username` VARCHAR(50) NOT NULL UNIQUE COMMENT '登录用户名',
  `password` VARCHAR(100) NOT NULL COMMENT '加密密码',
  `nickname` VARCHAR(50) NOT NULL COMMENT '用户昵称',
  `status` TINYINT DEFAULT 1 COMMENT '状态:1-正常,0-禁用',
  `create_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
);

-- 角色表
CREATE TABLE `sys_role` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '角色ID',
  `role_code` VARCHAR(50) NOT NULL UNIQUE COMMENT '角色编码(如ADMIN/USER)',
  `role_name` VARCHAR(50) NOT NULL COMMENT '角色名称'
);

-- 用户角色关联表
CREATE TABLE `sys_user_role` (
  `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '关联ID',
  `user_id` BIGINT NOT NULL COMMENT '用户ID',
  `role_id` BIGINT NOT NULL COMMENT '角色ID',
  FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`),
  FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`id`),
  UNIQUE KEY `idx_user_role` (`user_id`, `role_id`)
);

-- 初始化角色数据
INSERT INTO `sys_role` (`role_code`, `role_name`) VALUES ('ADMIN', '管理员'), ('USER', '普通用户');

-- 初始化用户数据(密码:admin123 / user123,已通过 BCrypt 加密)
INSERT INTO `sys_user` (`username`, `password`, `nickname`) 
VALUES ('admin', '$2a$10$E8Z5sN9y6G6z6X7a8B9c0D1e2F3g4H5i6J7k8L9m0N1o2P3q4R5', '系统管理员'),
       ('user', '$2a$10$A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4Y', '普通用户');

-- 关联用户与角色
INSERT INTO `sys_user_role` (`user_id`, `role_id`) 
VALUES ((SELECT `id` FROM `sys_user` WHERE `username`='admin'), (SELECT `id` FROM `sys_role` WHERE `role_code`='ADMIN')),
       ((SELECT `id` FROM `sys_user` WHERE `username`='user'), (SELECT `id` FROM `sys_role` WHERE `role_code`='USER'));

-- 索引优化
CREATE INDEX `idx_sys_user_username` ON `sys_user` (`username`);
CREATE INDEX `idx_sys_user_role_user_id` ON `sys_user_role` (`user_id`);

第八步:代码分层设计

严格按照 Spring Boot 项目标准分层组织代码,明确各目录职责,提示词如下:

diff 复制代码
请按照以下分层架构组织代码,每个目录职责明确,核心代码放在对应目录下:
- config:配置类(Spring Security 配置、CORS 配置、AOP 配置、数据库配置)
- controller:控制器(处理 HTTP 请求,映射接口路径)
- service:服务层(实现核心业务逻辑,协调数据访问)
- repository:数据访问层(JPA 接口,操作数据库)
- entity:数据库实体(与表结构对应,包含 JPA 注解)
- dto:入参/出参实体(请求DTO、响应DTO、视图VO)
- util:工具类(JWT 工具类、响应结果工具类)
- component:自定义组件(JWT 认证过滤器、权限切面、全局异常处理器)
- annotation:自定义注解(权限注解 @RequiresPermission)
- exception:自定义异常(Token 过期异常、无权限异常等)

生成的项目目录结构:

arduino 复制代码
src/main/java/com/example/auth/
├── AuthApplication.java                // 项目启动类
├── config/                             // 配置层
│   ├── WebSecurityConfig.java          // Spring Security 核心配置
│   ├── CorsConfig.java                 // 跨域配置
│   ├── AopConfig.java                  // AOP 配置
│   └── DatabaseConfig.java             // 数据库配置
├── controller/                         // 控制器层
│   ├── AuthController.java             // 认证接口(注册/登录/刷新Token)
│   ├── UserController.java             // 用户接口(查询信息/测试权限)
│   └── PublicController.java           // 公共接口(健康检查/欢迎页)
├── service/                            // 服务层
│   ├── UserService.java                // 用户业务逻辑
│   └── UserDetailsServiceImpl.java     // Spring Security 用户详情服务
├── repository/                         // 数据访问层
│   └── UserRepository.java             // 用户数据操作接口
├── entity/                             // 数据库实体
│   ├── User.java                       // 用户实体
│   ├── Role.java                       // 角色实体
│   └── UserRole.java                   // 用户角色关联实体
├── dto/                                // 入参出参实体
│   ├── request/UserLoginRequest.java   // 登录请求DTO
│   ├── request/UserRegisterDTO.java    // 注册请求DTO
│   └── response/UserLoginDTO.java      // 登录响应DTO
│   └── response/UserVO.java            // 用户视图VO
├── util/                               // 工具类
│   ├── JwtUtils.java                   // JWT 生成/解析/验证工具
│   └── ResultUtils.java                // 响应结果工具
├── component/                          // 自定义组件
│   ├── JwtAuthenticationFilter.java    // JWT 认证过滤器
│   ├── JwtAuthorizationFilter.java     // JWT 授权过滤器
│   ├── PermissionAspect.java           // 权限注解切面
│   └── GlobalExceptionHandler.java     // 全局异常处理器
├── annotation/                         // 自定义注解
│   └── RequiresPermission.java         // 权限注解
└── exception/                          // 自定义异常
    ├── TokenExpiredException.java      // Token 过期异常
    ├── InvalidTokenException.java      // 无效 Token 异常
    └── NoPermissionException.java      // 无权限异常

核心代码示例(JWT 工具类):

typescript 复制代码
@Component
public class JwtUtils {
    @Value("${jwt.secret}")
    private String secret; // JWT 密钥(配置在 application.yml)
    
    @Value("${jwt.access-token-expire}")
    private long accessTokenExpire; // Access Token 过期时间(秒)
    
    @Value("${jwt.refresh-token-expire}")
    private long refreshTokenExpire; // Refresh Token 过期时间(秒)
    
    /**
     * 生成 Access Token
     * @param userId 用户ID
     * @param roles 角色列表
     * @return Access Token
     */
    public String generateAccessToken(Long userId, List<String> roles) {
        return generateToken(userId, roles, accessTokenExpire);
    }
    
    /**
     * 生成 Refresh Token
     * @param userId 用户ID
     * @param roles 角色列表
     * @return Refresh Token
     */
    public String generateRefreshToken(Long userId, List<String> roles) {
        return generateToken(userId, roles, refreshTokenExpire);
    }
    
    /**
     * 生成 Token 核心方法
     */
    private String generateToken(Long userId, List<String> roles, long expireTime) {
        Date now = new Date();
        Date expireDate = new Date(now.getTime() + expireTime * 1000);
        
        // 构建 JWT Token
        return Jwts.builder()
                .setSubject(String.valueOf(userId)) // 存储用户ID
                .claim("roles", roles) // 存储角色信息
                .setIssuedAt(now) // 签发时间
                .setExpiration(expireDate) // 过期时间
                .signWith(SignatureAlgorithm.HS256, secret) // 加密算法(开发环境)
                .compact();
    }
    
    /**
     * 从 Token 中解析用户ID
     */
    public Long getUserIdFromToken(String token) {
        Claims claims = parseClaims(token);
        return Long.parseLong(claims.getSubject());
    }
    
    /**
     * 从 Token 中解析角色列表
     */
    public List<String> getRolesFromToken(String token) {
        Claims claims = parseClaims(token);
        return claims.get("roles", List.class);
    }
    
    /**
     * 验证 Token 有效性
     */
    public boolean validateToken(String token) {
        try {
            parseClaims(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 解析 Token 中的 Claims
     */
    private Claims parseClaims(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }
}

第九步:增量开发实现

分三轮实现,每轮产出可独立运行的版本,降低调试难度:

第一轮:最小可用版本(核心认证功能)

目标:实现用户注册、登录、Token 生成与验证,跑通基础流程提示词:"请实现认证授权系统的最小可用版本,包含用户注册(加密存储密码)、登录(生成 Access Token 和 Refresh Token)、JWT 工具类、Spring Security 基础配置、公共接口和受保护接口区分,确保能正常注册登录并访问受保护接口"

核心产出:

  • JwtUtils.java:JWT 生成 / 解析 / 验证工具类
  • AuthController.java:注册 / 登录接口
  • WebSecurityConfig.java:Spring Security 基础配置(放行公共接口、配置密码加密方式)
  • JwtAuthenticationFilter.java:JWT 认证过滤器(拦截请求、验证 Token)
第二轮:完善权限控制(注解 + 角色校验)

目标:实现基于角色的访问控制和自定义权限注解提示词:"请完善权限控制功能,实现 @PreAuthorize 角色校验(支持 hasRole ('ADMIN'))、自定义 @RequiresPermission 注解及 AOP 切面校验、用户角色关联查询,确保不同角色只能访问对应权限的接口"

核心产出:

  • RequiresPermission.java:自定义权限注解
  • PermissionAspect.java:权限注解 AOP 切面
  • UserDetailsServiceImpl.java:加载用户角色信息,适配 Spring Security
  • UserController.java:添加角色校验和权限注解校验的测试接口
第三轮:补充功能与优化(异常 + 跨域 + 测试数据)

目标:完善全局异常处理、跨域配置、初始化测试数据,优化用户体验提示词:"请添加全局异常处理器(处理 Token 过期、无效、无权限等异常)、跨域配置(支持前后端分离项目访问)、H2 数据库初始化测试数据、Token 刷新功能,确保系统稳定可用,前端可直接集成"

核心产出:

  • GlobalExceptionHandler.java:全局异常处理器
  • CorsConfig.java:跨域配置
  • DatabaseConfig.java:H2 数据库配置(支持控制台访问)
  • 数据库初始化 SQL:自动插入测试用户和角色数据

第十步:测试用例编写

生成测试用例覆盖核心场景,确保系统功能正常,提示词如下:

markdown 复制代码
请编写单元测试和集成测试,覆盖以下核心场景:
1. JWT 工具类:Token 生成、解析、验证、过期测试
2. 认证接口:注册成功、登录成功(生成双 Token)、刷新 Token 成功
3. 权限控制:角色校验(ADMIN 可访问、USER 不可访问)、自定义权限注解校验
4. 异常场景:无效 Token、过期 Token、无权限访问、参数校验失败
要求测试用例有明确断言,使用 JUnit 5 + MockMvc 实现

单元测试示例(JwtUtils 测试):

ini 复制代码
@SpringBootTest
public class JwtUtilsTest {

    @Autowired
    private JwtUtils jwtUtils;

    @Test
    public void testGenerateAndValidateToken() {
        // 准备测试数据
        Long userId = 1L;
        List<String> roles = Arrays.asList("ADMIN");
        
        // 生成 Token
        String accessToken = jwtUtils.generateAccessToken(userId, roles);
        String refreshToken = jwtUtils.generateRefreshToken(userId, roles);
        
        // 验证 Token 有效性
        Assertions.assertTrue(jwtUtils.validateToken(accessToken));
        Assertions.assertTrue(jwtUtils.validateToken(refreshToken));
        
        // 验证解析结果
        Assertions.assertEquals(userId, jwtUtils.getUserIdFromToken(accessToken));
        Assertions.assertEquals(roles, jwtUtils.getRolesFromToken(accessToken));
    }

    @Test
    public void testExpiredToken() throws InterruptedException {
        // 生成过期 Token(设置过期时间 1 秒)
        Long userId = 1L;
        List<String> roles = Arrays.asList("USER");
        String accessToken = jwtUtils.generateAccessToken(userId, roles);
        
        // 休眠 2 秒,等待 Token 过期
        Thread.sleep(2000);
        
        // 验证过期 Token 无效
        Assertions.assertFalse(jwtUtils.validateToken(accessToken));
    }
}

集成测试示例(接口全流程):

less 复制代码
@SpringBootTest
@AutoConfigureMockMvc
public class AuthIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    private String accessToken;
    private String refreshToken;

    // 登录获取 Token(测试前置操作)
    @BeforeEach
    public void login() throws Exception {
        UserLoginRequest loginRequest = new UserLoginRequest();
        loginRequest.setUsername("admin");
        loginRequest.setPassword("admin123");

        // 发起登录请求
        String response = mockMvc.perform(post("/api/auth/login")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(loginRequest)))
                .andExpect(status().isOk())
                .andReturn()
                .getResponse()
                .getContentAsString();

        // 解析响应,获取 Token
        UserLoginDTO loginDTO = objectMapper.readValue(response, UserLoginDTO.class);
        accessToken = loginDTO.getAccessToken();
        refreshToken = loginDTO.getRefreshToken();
    }

    // 测试访问需 ADMIN 角色的接口(成功)
    @Test
    public void testAdminRoleInterface() throws Exception {
        mockMvc.perform(get("/api/users/all")
                        .header("Authorization", "Bearer " + accessToken)
                        .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value(200));
    }

    // 测试刷新 Token(成功)
    @Test
    public void testRefreshToken() throws Exception {
        mockMvc.perform(post("/api/auth/refresh-token")
                        .param("refreshToken", refreshToken)
                        .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.data.accessToken").exists());
    }

    // 测试无权限访问接口(失败,返回 403)
    @Test
    public void testNoPermissionInterface() throws Exception {
        // 使用普通用户登录获取 Token
        UserLoginRequest userLoginRequest = new UserLoginRequest();
        userLoginRequest.setUsername("user");
        userLoginRequest.setPassword("user123");
        String userResponse = mockMvc.perform(post("/api/auth/login")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(userLoginRequest)))
                .andReturn()
                .getResponse()
                .getContentAsString();
        UserLoginDTO userLoginDTO = objectMapper.readValue(userResponse, UserLoginDTO.class);

        // 普通用户访问 ADMIN 接口
        mockMvc.perform(get("/api/users/all")
                        .header("Authorization", "Bearer " + userLoginDTO.getAccessToken())
                        .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isForbidden()) // 403 无权限
                .andExpect(jsonPath("$.code").value(403));
    }
}

做得好的地方

  • 标准化提示词明确了技术栈版本和代码规范,AI 生成的代码无需大幅修改即可集成
  • 增量开发模式让每个版本都能独立运行,便于定位问题,降低调试成本
  • 自定义权限注解 + AOP 切面的设计,让权限控制更灵活,可直接复用在其他项目
  • AI 自动生成测试用例和项目文档,大幅减少重复工作量,提升开发效率

踩过的坑

  • 初期提示词未明确 Spring Security 版本,导致 AI 生成的配置类与 Spring Boot 2.7.x 不兼容,后续需锁定版本号
  • 忘记启用 @EnableGlobalMethodSecurity (prePostEnabled = true) 注解,导致 @PreAuthorize 角色校验失效,需在 Security 配置类补充
  • 跨域配置未允许 Authorization 请求头,导致前端携带 Token 时出现跨域错误,需在 CorsConfig 中添加 allowedHeaders = "*"
  • JWT 密钥硬编码存在安全风险,后续改为从配置文件注入,生产环境计划替换为 RSA 非对称加密

给大家的建议

  • 技术栈选择要兼顾稳定性和易用性,Spring Boot 2.7.x + Spring Security 5.7.x 是成熟组合,文档丰富、问题易排查
  • 权限设计要循序渐进,先实现基础的角色校验,再扩展自定义权限注解,避免一开始过度设计
  • AI 生成的安全相关代码(如 Token 生成、密码加密)必须人工 review,确保无安全漏洞
  • 提前规划 Token 策略,包括过期时间、刷新机制和异常处理,避免后期重构影响系统稳定性

💎 最大的收益:释放更多时间做有价值的事

用 TRAE 辅助开发这套认证授权系统,最直观的收益不是开发速度的提升,而是从重复劳动中解放出来,专注于核心设计。

以前开发类似系统,光是编写 Spring Security 配置、JWT 工具类、数据库实体、CRUD 代码和测试用例,就要花费 4-6 天时间。现在这些重复性工作 AI 半小时内就能搞定,我可以把省下来的时间用在:

  • 架构优化:思考权限模型的扩展性(如支持数据权限、多租户权限)、系统性能(如 Token 缓存、接口限流)
  • 安全加固:研究更安全的加密算法、Token 存储方案(如 HttpOnly Cookie)、防 CSRF/XXS 攻击策略
  • 易用性提升:优化接口设计、统一响应格式、完善异常提示,让前端集成更简单
  • 代码质量把控:花更多时间做 code review,优化代码可读性和可维护性

AI 接管了 "体力活",让我们能专注 "脑力活",开发出的系统不仅落地快,安全性和可扩展性也更强。

🛠️ 工具推荐

  • CodeGeeX(IDEA 插件):专为 Java 开发优化,支持代码生成、注释添加和错误修复,与 Spring 生态兼容性好
  • Postman:接口测试工具,支持 Token 自动携带和批量测试,方便验证认证授权流程
  • Draw.io:免费开源的流程图工具,支持导入导出,快速绘制架构图和流程逻辑图
  • Lombok(IDEA 插件):简化 Java 代码,减少 getter/setter/ 构造函数等样板代码
  • H2 Console:内置数据库控制台,方便调试数据,支持 SQL 执行和数据查看

🚀 总结

这套基于 Spring Boot+JWT+Spring Security 的认证授权系统,通过 TRAE 辅助开发实现了 "落地就能跑" 的目标,支持用户注册登录、Token 管理、角色校验和自定义权限注解,可直接复用在前后端分离项目中。

核心要点是:明确人机分工,让 AI 处理重复工作,人把控架构和安全核心;标准化流程和提示词,确保 AI 输出一致性;增量开发和充分测试,保证系统稳定可用。

无论是新项目搭建认证授权体系,还是旧项目安全改造,这套方案都能大幅降低开发成本、提升开发效率,同时保障系统的安全性和可扩展性。

相关推荐
sinat_267611911 小时前
Trae AI 进行 Android 从0 到 1的一键开发
kotlin·android studio·trae
阆遤1 天前
利用TRAE对nanobot进行安全分析并优化
python·安全·ai·trae·nanobot
Molesidy1 天前
【VSCode】VSCode或者Trae的扩展文件夹以及用户设置文件夹的路径更改到指定位置
ide·编辑器·trae
yosh'joy!!1 天前
下载Trae使用
ai·trae
豆包MarsCode2 天前
只需一个指令,让 OpenClaw 安排 TRAE 干活
trae
sugar15692 天前
Trae快速构建自己项目的docker镜像
docker·容器·trae
sugar15692 天前
Trae 添加项目规则,快速完成crmeb项目本地开发环境搭建
docker·容器·trae
欧简墨3 天前
kotlin Android Extensions插件迁移到viewbinding总结
android·trae
arbboter3 天前
【AI编程】约束即设计:AI时代的人机边界重构
ai编程·ai工作流·人机协作·trae·声明式执行·流程编排
进击的雷神5 天前
Trae AI IDE 完全指南:从入门到精通
大数据·ide·人工智能·trae