一、前端发起请求

前端通过调用 /login 接口,将用户名、密码、验证码等信息以 JSON 格式发送到后端。

二、后端业务处理

后端入口控制器处理

请求首先由 SysLoginController 的 login 方法处理。该方法负责验证参数合法性,并调用认证服务。

1.验证码校验流程

  • 客户端请求验证码接口获取验证码图片及UUID
  • 后端生成验证码并存储到Redis,Key为UUID,Value为验证码值
  • 用户提交登录请求时携带验证码和UUID
  • 后端根据UUID从Redis获取存储的验证码进行比对
  • 验证失败则返回错误信息,成功则进入下一步

SysloginController.java:

SysLoginService.java

调用 ValidateCodeService 验证输入的验证码是否匹配:

具体实现验证用户输入的验证码是否正确:

关键逻辑:

  • 检查用户输入的验证码是否与服务器生成的一致。
  • 若验证码不存在(过期或已删除),拒绝登录。
  • 校验成功后立即删除Redis中的验证码,防止重复使用。

2.用户名密码校验流程

  • 从请求中提取用户名和密码参数
  • 查询数据库验证用户名是否存在
  • 对用户输入的密码进行加密处理(MD5 + Salt)
  • 比对数据库中的加密密码与处理后的输入密码
  • 校验失败返回账号或密码错误,成功则进入Token生成阶段

Ctrl+鼠标左键点击login自动跳转到相关代码SysLoginService.java进一步分析:

通过 AuthenticationManager 进行用户名密码认证:

异常处理:

认证成功后的操作:

记录登录日志:调用 SysLoginInfoService 插入登录日志

关键逻辑:

  • 登录失败时异步记录日志(用户名、失败原因)。
  • 根据失败类型抛出不同异常,供前端展示提示

3.Token生成与返回流程

  • 使用JWT工具类生成Token,包含用户ID、账号等信息
  • 设置Token过期时间(如7200秒)
  • 将Token及相关用户信息存入Redis,Key为login_tokens:用户ID
  • 清除验证码Redis缓存防止重复使用
  • 返回Token给前端,前端存储至本地并用于后续请求鉴权

生成认证令牌:认证成功后返回 UsernamePasswordAuthenticationToken

TokenService

三、关键代码类

  • LoginController: 处理登录请求入口
  • SysLoginService: 核心登录逻辑实现
  • TokenService: JWT token生成/验证
  • AuthenticationConfig: Spring Security配置类
  • RedisCache: 验证码和Token存储

1. LoginController

  • 作为REST接口层,接收前端登录请求(如/login
  • 参数校验:验证用户名、密码、验证码格式
  • 调用SysLoginService处理业务逻辑
  • 返回标准化响应(如Result封装Token或错误码)
// 示例代码片段(非完整实现)
@PostMapping("/login")
public AjaxResult login(@RequestBody LoginBody loginBody) {
    // 验证码校验
    captchaService.validate(loginBody.getCode(), loginBody.getUuid());
    // 密码解密
    String password = PasswordUtils.decryptPassword(loginBody.getPassword());
    // 用户认证
    Authentication authentication = authenticationManager.authenticate(
        new UsernamePasswordAuthenticationToken(loginBody.getUsername(), password));
    // 生成Token
    LoginUser loginUser = (LoginUser) authentication.getPrincipal();
    String token = tokenService.createToken(loginUser);
    return AjaxResult.success().put("token", token);
}
 

2. SysLoginService

  • 核心业务逻辑:验证码校验、用户凭证验证
  • 调用AuthenticationManager进行Spring Security认证
  • 通过TokenService生成JWT令牌
  • 记录登录日志、处理并发登录限制等

典型流程:

  1. 检查Redis中验证码匹配性
  2. 执行authenticationManager.authenticate()
  3. 调用tokenService.createToken()生成令牌
if (!passwordEncoder.matches(password, storedPassword)) {
    throw new ServiceException("用户密码错误");
}
 

3. TokenService

JWT token管理核心类,主要功能包括:

  • 生成Token:使用Jwts.builder()设置claims、过期时间、签名密钥
  • 解析Token:验证签名有效性及过期时间
  • 刷新Token:当接近过期时生成新token
  • 黑名单管理:登出时加入黑名单
String token = Jwts.builder()
    .setSubject(loginUser.getUsername())
    .setExpiration(new Date(System.currentTimeMillis() + expireTime))
    .signWith(SignatureAlgorithm.HS512, secret)
    .compact();
 

4. AuthenticationConfig

  • 继承WebSecurityConfigurerAdapter配置安全策略
  • 定义密码编码器(如BCryptPasswordEncoder)
  • 配置放行路径(如登录接口、静态资源)
  • 注入自定义的UserDetailsService
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/login").permitAll()
        .anyRequest().authenticated()
        .and().addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    return http.build();
}
 

5. RedisCache

验证码和Token的存储管理,主要操作:

  • 验证码存储:redisTemplate.opsForValue().set(captchaKey, code, timeout)
  • Token黑名单:使用Hash结构存储失效token
  • 用户信息缓存:登录用户信息序列化存储
  • 分布式会话同步:跨服务共享认证状态

缓存操作示例:

public void setCacheObject(String key, Object value, Integer timeout) {
    redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}
 

关键逻辑:

  • Token包含用户身份信息并设置有效期。
  • Token在Redis中存储,支持快速验证和续期。
  • 验证码缓存清除确保一次性使用。

四、Ruoyi Vue 登录功能后端代码调用具体流程时序图

1.客户端请求验证码:用户在客户端发起请求,获取验证码。
2.后端生成并存储验证码:后端生成验证码,并将其存储到 Redis 缓存中。
3.客户端提交登录信息:用户输入用户名、密码和验证码,提交登录请求。
4.后端校验验证码:后端从 Redis 中获取验证码并进行校验。
5.校验用户名密码:若验证码正确,后端查询数据库验证用户名和密码是否匹配。
6.生成 JWT Token:验证通过后,生成 JWT 认证令牌。
7.存储用户信息:将用户信息存入 Redis(用于后续快速访问)。
8.清除验证码缓存:为安全起见,清除已使用的验证码缓存。
9.返回 Token 给客户端:后端将 JWT Token 返回给客户端,客户端接收并本地存储。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐