基于 Spring Boot 的登录功能实现详解

发布于:2025-08-12 ⋅ 阅读:(15) ⋅ 点赞:(0)

在 Web 应用开发中,登录功能是保障系统安全的第一道防线。本文将结合实际代码,详细解析一个基于 Spring Boot 框架的登录功能实现,包括验证码生成、用户验证、Token 机制等关键环节。

技术栈概览

本登录功能实现涉及以下核心技术和组件:

  • Spring Boot:后端开发框架
  • MyBatis-Plus:数据库操作增强工具
  • Redis:用于存储验证码和 Token
  • JWT:生成和验证用户令牌
  • Hutool:提供 UUID 生成、加密等工具类
  • 验证码工具:生成图形验证码

核心功能实现

1. 验证码生成与验证

验证码是防止恶意登录的重要手段,实现代码如下:

@RequestMapping("/captcha")
public Result getCaptcha(){
    // 生成验证码图片对象
    Captcha captcha = new SpecCaptcha(130, 38, 4);
    // 将验证码转为大写字符串
    String code = captcha.text().toUpperCase();
    // 生成UUID作为验证码的唯一标识
    String uuid = IdUtil.simpleUUID();
    // 存入redis并设置2分钟过期时间
    redisTemplate.opsForValue().set(uuid, code, 120, TimeUnit.SECONDS);
    
    // 构建返回数据
    Map<String,Object> map = new HashMap<>();
    map.put("uuid", uuid);       // 验证码唯一标识
    map.put("code", code);       // 验证码文本
    map.put("captcha", captcha.toBase64());  // 验证码图片(base64格式)
    
    return Result.ok().put("data", map);
}

验证码实现流程:

  1. 生成指定尺寸的图形验证码
  2. 将验证码文本转为大写并与 UUID 绑定
  3. 存储到 Redis 并设置过期时间
  4. 将 UUID、验证码图片(base64 格式)返回给前端

2. 登录核心逻辑

登录功能是整个流程的核心,负责验证用户身份并生成访问令牌:

@RequestMapping("/login")
public Result login(@RequestBody LoginForm loginForm, HttpSession session){
    // 1. 验证验证码是否存在
    String uuid = loginForm.getUuid();
    String code = (String)redisTemplate.opsForValue().get(uuid);
    if(code == null){
        return Result.ok().put("status","验证码已过期");
    }
    
    // 2. 验证验证码是否正确
    String captcha = loginForm.getCaptcha().toUpperCase();
    if(!code.equals(captcha)){
        return Result.ok().put("status","验证码错误");
    }
    
    // 3. 验证用户名是否存在
    String username = loginForm.getUsername();
    QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("username", username);
    UserEntity user = userService.getOne(queryWrapper);
    if(user == null){
        return Result.ok().put("status","用户名不存在");
    }
    
    // 4. 验证密码是否正确(使用SHA256加密)
    String password = SecureUtil.sha256(loginForm.getPassword());
    if(!password.equals(user.getPassword())){
        return Result.ok().put("status","密码错误");
    }
    
    // 5. 将用户信息存入session
    session.setAttribute("user", user);
    
    // 6. 生成JWT令牌
    String token = jwtUtil.createToken(String.valueOf(user.getUserId()));
    
    // 7. 准备返回数据
    Map<String,Object> map = new HashMap<>();
    map.put("token", token);
    map.put("expire", jwtUtil.getExpire());
    
    return Result.ok().put("data", map);
}

登录流程解析:

  1. 前端提交包含用户名、密码、验证码和 UUID 的登录表单
  2. 后端通过 UUID 从 Redis 获取验证码进行验证
  3. 验证通过后查询数据库检查用户名是否存在
  4. 对输入密码进行 SHA256 加密后与数据库存储的密码比对
  5. 验证成功后,将用户信息存入 session
  6. 生成 JWT 令牌并返回给前端,用于后续请求的身份验证

3. Token 验证机制

为了避免每次请求都需要重新登录,实现了基于 JWT 的 Token 验证机制:

@RequestMapping("/checkToken")
public Result checkToken(HttpServletRequest request){
    String token = request.getHeader("token");
    boolean result = jwtUtil.checkToken(token);
    if (result) return Result.ok().put("status","ok");
    else {
        return Result.ok().put("status", "error");
    }
}

Token 验证流程:

  1. 前端在请求头中携带 Token
  2. 后端从请求头获取 Token 并验证其有效性
  3. 返回验证结果,前端根据结果判断是否需要重新登录

4. 退出登录功能

@RequestMapping("/logout")
public Result logout(HttpSession session) {
    session.invalidate();  // 使当前session失效
    return Result.ok().put("status", "操作成功");
}

退出登录通过使当前 session 失效,清除用户的登录状态。

安全性考虑

  1. 密码加密:使用 SHA256 算法对密码进行加密存储,避免明文存储
  2. 验证码机制:防止机器人自动登录和暴力破解
  3. Token 过期机制:JWT 令牌有有效期,降低被盗用风险
  4. Redis 存储:验证码和 Token 都存储在 Redis 中并设置过期时间,自动清理

总结

本登录功能实现了从验证码生成、用户身份验证到 Token 发放的完整流程,结合了 Redis 和 JWT 技术,既保证了系统安全性,又提升了用户体验。在实际应用中,还可以根据需求进一步增强,如添加登录次数限制、异常登录检测等功能。

通过分层验证(验证码 -> 用户名 -> 密码)的方式,逐步过滤无效请求,既提高了安全性,也能给用户提供更明确的错误提示。


网站公告

今日签到

点亮在社区的每一天
去签到