一、项目整体技术栈核心框架SpringBoot 3.3.5 Spring Security 6持久层MyBatis-Plus 3.5.7 MySQL8鉴权JWTjava-jwt 4.3.0 Redis实现登出 Token 黑名单失效工具Lombok、FastJson2、BCrypt 密码加密构建工具MavenJava17架构模式标准 MVC 三层架构 过滤器前置鉴权 前后端分离无状态登录不使用 Session二、主要功能模块SecurityConfiguration整套安全规则核心核心过滤链SecurityFilterChain配置项逐条解释authorizeHttpRequests接口放行规则/api/auth/**全部放行登录、登出接口不需要 TokenanyRequest().authenticated()其余所有接口必须携带有效 Token 登录后访问formLogin表单登录配置登录提交地址POST /api/auth/loginsuccessHandler(this::onAuthenticationSuccess)登录成功处理器生成 Token 返回前端failureHandler(this::onAuthenticationFailure)登录失败处理器返回 401 错误logout登出配置登出接口地址/api/auth/logoutlogoutSuccessHandler(this::onLogoutSuccess)登出处理器Token 加入 Redis 黑名单失效exceptionHandling全局鉴权异常处理authenticationEntryPoint未登录 / Token 失效返回 401accessDeniedHandler登录但权限不足返回 403csrf(AbstractHttpConfigurer::disable)关闭 CSRF 防护前后端分离 JWT 无 session 不需要sessionCreationPolicy.STATELESS无状态完全放弃 Session靠 Token 鉴权addFilterBefore(jwtAuthorizeFilter, UsernamePasswordAuthenticationFilter.class)请求进入时优先执行 JWT 过滤器提前解析 Token 写入登录上下文5 个核心处理器方法onAuthenticationSuccess登录成功 查询完整账号 → 调用 JwtUtils 生成 Token → 封装 AuthorizeVO → RestBean 包装 JSON 返回前端onAuthenticationFailure登录失败 统一返回RestBean.unauthorized(异常信息)401 未授权onLogoutSuccess退出登录 获取请求头 Token → JwtUtils.invalidateJwt 将 Token 存入 Redis 黑名单 → 返回登出成功onUnauthorized未登录 / Token 过期 接口无有效 Token 时触发返回 401onAccessDeny权限不足 用户已登录但角色无访问接口权限返回 403三、流程 1用户登录完整执行链路前端 POST /api/auth/login总流程文字流程图前端提交 username 明文密码 → Security 过滤链接收请求 → 自动调用 AccountService.loadUserByUsername → 查询数据库账号 → Security 密码比对 → 成功 / 失败分支分步详细执行前端发起 POST 请求http://localhost:端口/api/auth/login表单携带 username、password请求进入 Security 过滤链匹配 formLogin 登录处理地址跳过 JwtAuthorizeFilter放行接口无需鉴权Security 框架自动执行认证逻辑调用AccountService.loadUserByUsername(前端username)3.1loadUserByUsername内部调用findAccountByNameOrEmail(text)3.2 MyBatis-Plus 生成 SQLselect * from db_account where username? or email?底层调用 AccountMapper 查询数据库 3.3 数据库返回 Account 实体无匹配数据直接抛出UsernameNotFoundException3.4 封装 Security 内置 User 对象包含用户名、加密密码、角色Security 自动注入BCryptPasswordEncoder比对前端明文密码与数据库加密密码分支 A密码错误 / 账号不存在进入onAuthenticationFailure失败处理器构造RestBean.unauthorized(用户名或密码错误)调用asJsonString()转为 JSON 写入 Response 返回前端登录流程结束分支 B账号存在且密码匹配成功进入onAuthenticationSuccess登录成功处理器从认证凭证获取用户名再次调用service.findAccountByNameOrEmail(user.getUsername())获取完整 Account 实体id、role调用JwtUtils.createJwt(user, account.getId(), account.getUsername())生成 JWT 令牌实例化 AuthorizeVO填充 username、role、token、expire 过期时间外层包装RestBean.success(vo)转 JSON 字符串返回前端前端接收 JSON提取 token 存入浏览器 localStorage后续所有接口请求头携带Authorization: Bearer 令牌四、流程 2携带 Token 访问普通业务接口如 GET /api/test/hello完整执行链路前端请求头携带Authorization: Bearer xxx→ JwtAuthorizeFilter 优先拦截 → JwtUtils 校验 Token → 合法写入 Security 上下文 → 放行到 Controller前端发起 GET 请求GET /api/test/helloHeader 携带 Token请求进入 Security 过滤链先执行 JwtAuthorizeFilter 过滤器过滤器执行doFilterInternal3.1 读取 Header 中的 Authorization 字符串 3.2 调用utils.resolveJwt(authorization)校验 Token剥离 Bearer 前缀校验签名密钥一致性判断 Token 是否过期查询 Redis 黑名单判断是否已执行退出登录失效 3.3 校验通过返回 DecodedJWT 对象utils.toUser(jwt)解析 Token 内用户名、角色权限构造UsernamePasswordAuthenticationToken认证对象存入SecurityContextHolder.getContext()全局登录上下文将用户 ID 存入 request 域 3.4 校验失败返回 null不写入登录上下文直接放行到 Security 权限校验Security 匹配规则anyRequest().authenticated()检测无登录认证信息触发onUnauthorized处理器返回 401 未登录 JSONToken 合法场景Security 检测到已存在登录认证放行至 TestControllerController 执行 test () 方法返回字符串Hello World给前端五、流程 3退出登录完整执行链路POST /api/auth/logout执行流程图前端携带有效 Token 请求 logout 接口 → Security 登出拦截 → JwtUtils.invalidateJwt 将 Token 存入 Redis 黑名单 → 返回登出成功前端发起请求POST /api/auth/logoutHeader 携带有效 Token接口路径属于/api/auth/**放行路径进入 Security logout 配置逻辑触发onLogoutSuccess登出成功处理器读取请求头Authorization完整 Token 字符串调用utils.invalidateJwt(authorization)5.1convertToken剥离 Bearer 前缀获取纯净 token 5.2 校验 Token 签名合法性解析 Token 内部唯一 UUIDJWTId 5.3 计算 Token 剩余有效时间调用deleteToken(uuid, 过期时间)5.4 Redis 存入 Keyjwt:blacklist:UUID过期时长 Token 剩余有效期过期自动清除缓存Redis 存入成功返回RestBean.success()无数据成功 JSONRedis 存入失败Token 已拉黑返回RestBean.failure(400,退出登录失败)前端收到响应后清除本地 localStorage 中的 token跳转登录页登出黑名单核心作用用户退出登录后原有 Token 即便未过期也直接失效下次携带该 Token 访问接口时JwtUtils.resolveJwt检测 Redis 黑名单存在直接判定 Token 非法返回 401。六、全模块调用依赖汇总表1. 登录流程调用链前端接口 → SecurityConfiguration.formLogin → AccountService.loadUserByUsername → AccountServiceImpl.findAccountByNameOrEmail → AccountMapper.selectOne → MySQL db_account 表 密码校验Security 内置 BCryptPasswordEncoderWebConfiguration 注册 生成 TokenonAuthenticationSuccess → JwtUtils.createJwt → AuthorizeVO → RestBean 返回 JSON2. 全局鉴权调用链任意带 Token 请求 → JwtAuthorizeFilter → JwtUtils.resolveJwt → Redis 黑名单查询 Token 验签 → SecurityContextHolder 写入登录信息 → Controller 业务接口3. 退出登录调用链前端 logout 接口 → SecurityConfiguration.logout → onLogoutSuccess → JwtUtils.invalidateJwt → JwtUtils.deleteToken → StringRedisTemplate 写入 Redis 黑名单 → RestBean 返回结果