使用 Spring Boot + JWT 实现多角色登录认证(附完整流程图)

本文是「EduCore 教务系统实战系列」第 2 篇,介绍我如何使用 Spring Boot + JWT 实现多角色(管理员 / 教师 / 学生)无状态登录认证机制,附带流程图、完整思路与关键代码结构,适合中后台系统开发者参考。


🎯 实现目标

  • ✅ 支持 ADMIN / TEACHER / STUDENT 三种角色登录;
  • ✅ 登录后返回 JWT Token,无需 Session;
  • ✅ 通过前端携带 Token 实现鉴权访问;
  • ✅ Token 中封装用户 ID、角色等核心信息;
  • ✅ 登录认证逻辑通过策略模式解耦;
  • ✅ 权限由 Spring Security 控制,支持细粒度接口权限拦截;

🔐 为什么选择 JWT + Spring Security?

对比项 原始方案(Session) 当前方案(JWT + Security)
状态管理 服务器维护 Session 客户端持有 Token,后端无状态
可扩展性 多端登录困难 可用于移动端、小程序、扫码登录等
灵活性 角色识别困难,易混乱 可在 Token 中封装角色、权限
安全控制 拦截器写死判断 使用 Spring Security 细粒度控制

📌 登录流程图

plaintext 复制代码
[用户登录页面]
        |
        v
   [输入账号/密码 + 角色]
        |
        v
[Controller 登录接口(/login)]
        |
        v
[LoginStrategyFactory 获取对应策略]
        |
        v
[xxxLoginStrategy 登录验证]
        |
        v
[登录成功 → 生成 JWT Token]
        |
        v
[前端保存 Token(localStorage)]
        |
        v
[携带 Authorization: Bearer xxx 请求后端接口]
        |
        v
[JWT 过滤器解析 Token → 构建用户上下文]
        |
        v
[Spring Security 判断权限 → 成功放行]

🧱 技术结构设计

✅ 1. 登录请求格式(包含角色)

json 复制代码
POST /login

{
  "username": "admin001",
  "password": "123456",
  "role": "ADMIN"
}

✅ 2. 后端 Controller 入口

java 复制代码
@PostMapping("/login")
public R login(@RequestBody Account account) {
    LoginStrategy strategy = loginStrategyFactory.getStrategy(account.getRole());
    Account dbAccount = strategy.login(account);
    if (dbAccount == null) return R.error("账号或密码错误");

    String token = jwtUtils.createToken(dbAccount);
    return R.ok().put("token", token).put("user", dbAccount);
}

✅ 3. 策略模式解耦多角色登录

java 复制代码
public interface LoginStrategy {
    Account login(Account account);
}

@Component("ADMIN")
public class AdminLoginStrategy implements LoginStrategy {
    @Autowired private AdminService adminService;
    public Account login(Account account) {
        return adminService.login(account);
    }
}

@Component("TEACHER")
public class TeacherLoginStrategy implements LoginStrategy {
    @Autowired private TeacherService teacherService;
    public Account login(Account account) {
        return teacherService.login(account);
    }
}

// 工厂类
@Component
public class LoginStrategyFactory {
    @Autowired private Map<String, LoginStrategy> strategyMap;
    public LoginStrategy getStrategy(String role) {
        return strategyMap.get(role);
    }
}

💡 这样写的好处是:当角色增加时无需修改核心逻辑,只需新增一个策略实现类即可


✅ 4. JWT Token 工具类(核心方法)

java 复制代码
public String createToken(Account account) {
    return Jwts.builder()
        .setSubject(account.getId().toString())
        .claim("role", account.getRole())
        .signWith(SignatureAlgorithm.HS256, secretKey)
        .setExpiration(expireDate)
        .compact();
}

✅ 5. JWT 过滤器 + Spring Security 认证链路

  • 自定义 JwtAuthenticationFilter 解析请求头中的 Token;
  • 成功解析后,将用户信息封装为 UsernamePasswordAuthenticationToken 放入 SecurityContextHolder
  • 后续的接口请求将被 Spring Security 统一管理是否有权限访问。

🔄 Token 前后端交互说明

步骤 说明
登录成功 后端返回 Token + 用户信息
前端存储 Vue3 使用 localStorage.setItem("token", xxx)
接口调用 Axios 请求头自动携带 Authorization: Bearer xxx
权限判断 后端解析角色权限后放行 or 拒绝

🧠 常见问题解答

❓ 为何要传 role 参数?

因为多个角色可能存在相同账号(如 admin001 可能是老师又是管理员),必须指定登录身份。

❓ Token 中哪些信息需要加密?

用户 ID + 角色是必须的。密码不应放入 Token。可考虑加入签发时间、IP 白名单等增强信息。

❓ Token 过期怎么办?

目前系统使用短时间有效 Token + 刷新机制,可集成 Redis 实现 Token 黑名单。


📦 项目结构片段(后端)

plaintext 复制代码
├── controller
│   └── LoginController.java
├── service
│   ├── AdminService.java
│   ├── TeacherService.java
├── strategy
│   ├── LoginStrategy.java
│   ├── AdminLoginStrategy.java
│   └── TeacherLoginStrategy.java
├── security
│   ├── JwtAuthenticationFilter.java
│   ├── JwtUtils.java

🔚 总结

通过 Spring Boot + JWT + 策略模式,我实现了一个功能完善、结构清晰的多角色登录认证体系:

  • ✅ 无状态、轻量化、安全性强
  • ✅ 支持多角色解耦,灵活扩展
  • ✅ 支持 PC 登录、扫码登录等多终端适配
  • ✅ 权限控制基于 Spring Security 精细化实现

这套机制也为后续的扫码登录、权限控制、动态菜单等功能奠定了基础。


🧭 下一篇预告

📌《如何用 Spring Security 构建无状态权限控制系统(含角色菜单控制)》


🔗 项目地址


🙋‍♂️ 如果你觉得这篇文章有帮助:

  • 点个赞 👍
  • 收藏 ⭐
  • 关注我 👇 持续发布 Spring Boot / Vue3 实战项目内容
相关推荐
musenh1 分钟前
spring学习1
java·学习·spring
专注于大数据技术栈16 分钟前
java学习--Vector
java·学习
sheji341618 分钟前
【开题答辩全过程】以 基于Java的校内美食推荐系统的设计与实现为例,包含答辩的问题和答案
java·开发语言·美食
白典典21 分钟前
解决iTextPDF生成手册时目录页码与实际页码不匹配问题
java·spring·intellij-idea
静心观复24 分钟前
foreach中使用remove踩坑
java
内存不泄露24 分钟前
基于 Spring Boot 的医院预约挂号系统(全端协同)设计与实现
java·vue.js·spring boot·python·flask
Mr -老鬼24 分钟前
Rust 知识图-谱基础部分
开发语言·后端·rust
袁慎建@ThoughtWorks28 分钟前
如何发布自定义 Spring Boot Starter
java·spring boot·后端
IT_陈寒30 分钟前
SpringBoot 3.0实战:10个高效开发技巧让你的启动时间减少50%
前端·人工智能·后端
开开心心_Every36 分钟前
强制打字练习工具:打够百字才可退出
java·游戏·微信·eclipse·pdf·excel·语音识别