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 输出一致性;增量开发和充分测试,保证系统稳定可用。

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

相关推荐
围巾哥萧尘4 小时前
从 IDE 插件到 AI 驱动的生态系统:TRAE SOLO 如何定义 AI 编码 3.0 时代的开发新范式🧣
trae
用户4099322502125 小时前
Vue浅响应式如何解决深层响应式的性能问题?适用场景有哪些?
前端·ai编程·trae
龙在天7 小时前
不小心更新了trae,发现...
trae
盏灯8 小时前
薅羊毛🐑🐑🐑Trae限时免费🎁🎁🎁...
trae
天天摸鱼的java工程师9 小时前
大模型能写80%的代码,却写不到95%?我成了“AI代码售后工程师”
trae
Mintopia9 小时前
🧠 可定制化 AIGC:Web 用户个性化模型训练的技术门槛正在塌缩!
前端·人工智能·trae
Mintopia10 小时前
🧭 DeepSeek 与 DeepSleep:算法的觉醒与人的打盹
trae
程序员X小鹿19 小时前
限时免费!字节 TRAE SOLO 正式上线,无需邀请码!新增 TRAE Coder(附实测体验)
ai编程·trae
_大学牲1 天前
从年初DeepSeek的爆火🔥 - 到年底Trae solo 的上线⚙️ :2025 AI 大年,一个普通人的认知指南 ! 🧭
deepseek·mcp·trae