当前位置: 首页 > news >正文

基于若依的邮件登陆功能

一、数据源与邮件配置(application.yml

1. 邮件服务配置(QQ 邮箱为例)

spring:mail:from: XXXXXXXXXXX@qq.com          # 发件人邮箱(需与username一致)host: smtp.qq.com                 # QQ邮箱SMTP服务器地址username: XXXXXXXXXXX@qq.com      # 邮箱账号password: XXXXXXXXXXXXXXXX        # SMTP授权码(非邮箱密码,需在QQ邮箱后台申请)port: 465                         # SSL加密端口(QQ邮箱固定为465或587)properties:mail:smtp:socketFactory:class: javax.net.ssl.SSLSocketFactory  # 使用SSL套接字工厂ssl:trust: smtp.qq.com                      # 信任的SSL主机auth: true                               # 启用认证starttls:enable: true                           # 启用TLS加密required: true                         # 强制TLS
  • 关键配置
    • port: 465 + SSLSocketFactory 确保邮件通过 SSL 加密传输。
    • auth: true 开启用户认证,starttls 增强传输安全性。
    • from 必须与 username 一致,否则 QQ 邮箱会拒绝发送。

配置流程

获取并使用 QQ 邮箱授权码

1. 生成授权码

  • 步骤 1:登录 QQ 邮箱网页版(https://mail.qq.com)。
  • 步骤 2:点击右上角的 设置 → 账户
  • 步骤 3:在 “账户安全” 或 “POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV 服务” 中,找到 生成授权码 选项(可能需要先启用 POP3/IMAP 服务)。
    • 若未启用服务,系统会提示先开启(如 “开启 IMAP/SMTP 服务”),按提示通过短信验证或密保工具完成验证。
  • 步骤 4:验证通过后,系统会生成一个16 位的授权码(例如:abcdefgh12345678),请妥善保存。

2. 使用授权码替代密码

在你的代码或邮件客户端中,将原本输入邮箱密码的位置,替换为刚刚生成的授权码

 二、后端核心代码逻辑

1. 邮件登录控制器(EmailLoginController

@RestController
@RequestMapping("/email")
public class EmailLoginController {@Autowired private EmailUtils emailUtils;@Autowired private SysEmailLoginService sysEmailLoginService;@Autowired private RedisCache redisCache;// 发送邮箱验证码@GetMapping("/sendLoginCode")public AjaxResult sendLoginCode(@RequestParam String to) {String code = generateVerifyCode(); // 生成6位随机数String verifyKey = "email-login-code:" + to;redisCache.setCacheObject(verifyKey, code); // 存入Redis(默认有效期由Redis配置决定)emailUtils.sendSimpleEmail(to, "登录验证码", code); // 发送邮件return AjaxResult.success("验证码发送成功!");}// 邮箱登录接口@PostMapping("/login")public AjaxResult login(@RequestBody MailLoginBody body) {String token = sysEmailLoginService.login(body.getEmail(), body.getCode()); // 验证邮箱+验证码return AjaxResult.success().put(Constants.TOKEN, token); // 返回JWT令牌}private String generateVerifyCode() {return String.valueOf(100000 + new SecureRandom().nextInt(900000)); // 生成100000-999999的随机数}
}

一、整体功能概述

这个控制器提供了两个核心接口:

  1. 发送验证码接口:生成随机验证码,存储到 Redis,并通过邮件发送给用户
  2. 邮箱登录接口:验证用户输入的邮箱和验证码,生成 JWT 令牌

二、核心组件与依赖

@RestController
@RequestMapping("/email")
public class EmailLoginController {@Autowired private EmailUtils emailUtils;       // 邮件发送工具类@Autowired private SysEmailLoginService service; // 邮箱登录业务逻辑@Autowired private RedisCache redisCache;        // Redis缓存操作工具
}
  • EmailUtils:封装邮件发送逻辑(如调用 JavaMailSender)
  • SysEmailLoginService:处理登录核心业务(验证码验证、用户认证)
  • RedisCache:缓存验证码,设置有效期(防重复使用)

三、发送验证码接口

@GetMapping("/sendLoginCode")
public AjaxResult sendLoginCode(@RequestParam String to) {String code = generateVerifyCode(); // 生成6位随机数String verifyKey = "email-login-code:" + to;redisCache.setCacheObject(verifyKey, code); // 存入RedisemailUtils.sendSimpleEmail(to, "登录验证码", code); // 发送邮件return AjaxResult.success("验证码发送成功!");
}
关键点
  1. 验证码生成

    private String generateVerifyCode() {// 生成100000-999999的随机数(6位数字)return String.valueOf(100000 + new SecureRandom().nextInt(900000));
    }
    
     
    • 使用SecureRandom(强随机数生成器)比Random更安全
    • 范围控制确保生成的数字固定为 6 位
  2. Redis 存储

    • Key 格式email-login-code:用户邮箱(避免不同用户冲突)
  3. 邮件发送

    • 调用封装好的工具类发送纯文本邮件
    • 邮件内容直接包含验证码(实际项目建议增加 HTML 模板)

四、邮箱登录接口

@PostMapping("/login")
public AjaxResult login(@RequestBody MailLoginBody body) {String token = service.login(body.getEmail(), body.getCode());return AjaxResult.success().put(Constants.TOKEN, token);
}
关键点
  1. 请求体结构

    public class MailLoginBody {private String email;private String code;// getters/setters
    }
    
  2. 业务逻辑

    // SysEmailLoginService.login() 可能的实现
    public String login(String email, String code) {// 1. 从Redis获取验证码String verifyKey = "email-login-code:" + email;String cachedCode = redisCache.getCacheObject(verifyKey);// 2. 校验验证码if (!code.equals(cachedCode)) {throw new BusinessException("验证码错误");}// 3. 删除已使用的验证码(防复用)redisCache.deleteObject(verifyKey);// 4. 用户存在性校验(从数据库查询)User user = userService.getUserByEmail(email);if (user == null) {// 处理新用户注册逻辑(可选)user = userService.registerByEmail(email);}// 5. 生成JWT令牌return jwtService.generateToken(user.getId());
    }

2. 邮箱登录服务(SysEmailLoginService) 

@Component
public class SysEmailLoginService {@Autowired private RedisCache redisCache;@Autowired private ISysUserService userService;public String login(String email, String code) {validateEmailCaptcha(email, code); // 校验验证码SysUser user = userService.selectUserByEmail(email); // 通过邮箱查询用户if (user == null) throw new UserNotExistsException("邮箱未注册"); // 用户不存在校验// 后续流程:Spring Security认证、生成JWT令牌(与账号密码登录一致)return tokenService.createToken(loginUser); // 生成并返回令牌}private void validateEmailCaptcha(String email, String code) {String verifyKey = "email-login-code:" + email;String cacheCode = redisCache.getCacheObject(verifyKey);if (cacheCode == null) throw new CaptchaExpireException("验证码过期"); // 有效期校验if (!code.equals(cacheCode)) throw new CaptchaException("验证码错误"); // 正确性校验redisCache.deleteObject(verifyKey); // 验证后删除Redis中的验证码,防止重复使用}
}

 实现了基于邮箱验证码的登录服务逻辑,是典型的无密码登录方案。

一、核心功能概述

SysEmailLoginService 负责处理邮箱验证码登录的核心业务逻辑,主要包括:

  1. 验证码校验:从 Redis 获取缓存的验证码并验证
  2. 用户存在性检查:通过邮箱查询用户是否存在
  3. 令牌生成:验证通过后生成 JWT 令牌

二、依赖组件分析

@Component
public class SysEmailLoginService {@Autowired private RedisCache redisCache;       // Redis缓存操作@Autowired private ISysUserService userService; // 用户服务接口@Autowired private TokenService tokenService;   // JWT令牌服务(代码中未显式注入,但方法中使用)
}
  • RedisCache:用于存储和获取验证码(缓存有效期通常设置为 5-10 分钟)
  • ISysUserService:与用户数据库交互,查询用户信息
  • TokenService:生成和管理 JWT 令牌(典型实现如 jjwt 库)

三、登录主流程解析

public String login(String email, String code) {validateEmailCaptcha(email, code); // 校验验证码(核心逻辑)SysUser user = userService.selectUserByEmail(email);if (user == null) throw new UserNotExistsException("邮箱未注册");// 构建登录用户对象(包含用户信息和权限)LoginUser loginUser = new LoginUser(user.getId(), user.getUsername(), ...);// 生成并返回JWT令牌(包含用户ID等信息)return tokenService.createToken(loginUser);
}
关键点
  1. 验证码校验:调用私有方法 validateEmailCaptcha 完成
  2. 用户查询:通过邮箱查询数据库中的用户记录
  3. 用户注册逻辑:当前代码未处理新用户注册(邮箱不存在时直接抛异常)
    • 实际项目中可能需要添加自动注册逻辑(如首次登录自动创建账号)

四、验证码校验逻辑

private void validateEmailCaptcha(String email, String code) {String verifyKey = "email-login-code:" + email;String cacheCode = redisCache.getCacheObject(verifyKey);// 1. 校验验证码是否存在(是否过期)if (cacheCode == null) throw new CaptchaExpireException("验证码过期");// 2. 校验验证码是否正确(忽略大小写)if (!code.equals(cacheCode)) throw new CaptchaException("验证码错误");// 3. 验证通过后立即删除验证码(防止重复使用)redisCache.deleteObject(verifyKey);
}

流程 

用户      前端      后端          Redis       邮件服务器|        |        |             |            || 输入邮箱|        |             |            ||------->|        |             |            ||        |/sendCode|             |            ||        |------->|             |            ||        |        |生成验证码   |            ||        |        |存入Redis    |<-----------||        |        |调用邮件服务 |            ||        |        |----------->|            ||        |<-------|            |            ||        |        |            |            || 输入验证码|        |             |            ||------->|        |             |            ||        |/login  |             |            ||        |------->|             |            ||        |        |从Redis获取  |            ||        |        |验证码       |<-----------||        |        |验证         |            ||        |        |查询用户     |            ||        |        |生成JWT令牌  |            ||        |<-------|            |            ||<-------|        |             |            |

3. 邮件工具类(EmailUtils

@Component
public class EmailUtils {@Resource private MailConfig mailConfig;@Value("${spring.mail.username}") private String from;public void sendSimpleEmail(String to, String subject, String content) {SimpleMailMessage message = new SimpleMailMessage();message.setFrom(from); // 发件人message.setTo(to);     // 收件人message.setSubject(subject); // 主题message.setText(content);     // 内容(纯文本)mailConfig.getMailSender().send(message); // 调用JavaMail发送}
}

 三、前端交互(邮箱登录页面)

1. 页面结构(Vue + Element UI)

<el-tab-pane label="邮箱登录" name="email"><el-form ref="emailForm" :model="emailForm" :rules="emailRules"><el-input v-model="emailForm.email" placeholder="请输入邮箱" /><el-input v-model="emailForm.emailCode" placeholder="请输入验证码" style="width: 63%"><el-button type="primary" :disabled="emailCodeBtnDisabled" @click="getEmailCode">{{ emailCodeBtnText }}</el-button></el-input><el-button @click="handleLogin">登录</el-button></el-form>
</el-tab-pane>
  1. 邮箱输入框:用于输入注册邮箱
  2. 验证码输入框:右侧附带获取验证码按钮
  3. 登录按钮:提交邮箱和验证码进行登录验证

2. 验证码发送逻辑(前端)

methods: {getEmailCode() {this.$refs.emailForm.validateField("email", (error) => {if (!error) { // 邮箱格式正确sendEmailCode({ to: this.emailForm.email }).then(() => {this.$message.success("验证码已发送");this.startCountdown(); // 启动60秒倒计时}).catch(() => {this.$message.error("发送失败,请重试");});}});},startCountdown() {let countdown = 60;this.emailCodeBtnDisabled = true;this.emailCodeBtnText = "60秒后重试";const timer = setInterval(() => {countdown--;if (countdown <= 0) {clearInterval(timer);this.emailCodeBtnDisabled = false;this.emailCodeBtnText = "获取验证码";} else {this.emailCodeBtnText = `${countdown} 秒后重试`;}}, 1000);}
}

3. 登录提交逻辑

handleLogin() {this.$refs.emailForm.validate(valid => {if (valid) {this.$store.dispatch("EmailLogin", { // 调用Vuex中的邮箱登录逻辑email: this.emailForm.email,code: this.emailForm.emailCode}).then(() => {this.$router.push("/index"); // 登录成功跳转首页}).catch(() => {// 处理登录失败(如验证码错误、邮箱未注册)});}});
}
  • 与后端交互
    • 通过$store.dispatch调用后端/email/login接口,传递邮箱和验证码。
    • 成功后存储 JWT 令牌(通过setToken方法),并跳转页面。

 

    相关文章:

  • 关于 smali:3. Smali 与 APK 结构理解
  • 构建智慧校园门户:技术架构与实践指南
  • 银发团扎堆本地游,“微度假”模式如何盘活银发旅游市场?
  • Autodesk Maya 2025.3新特性
  • halcon高斯滤波
  • AI如何颠覆财务预测?——用Python打造自动化智能分析系统
  • JSONP跨域原理全解析
  • vue2使用el-tree实现两棵树间节点的拖拽复制
  • 计算机网络实验课(三)——直接使用数据构造以太网帧,打包并发送|使用SharpPcap库函数构造以太网帧,并发送出去
  • 【Webtrees 手册】第 8章 - 网站管理员指南
  • 在 Unity 中,Start 方法直接设置 RectTransform 的位置,时出现问题,与预计位置不匹配。
  • LightGBM的python实现及参数优化
  • 从十进制到二进制:深入理解定点数与浮点数表示
  • Python学习(2) ----- Python的类型
  • 多模态大语言模型arxiv论文略读(九十五)
  • Python正则表达式:30秒精通文本处理
  • Java中数组(一维/二维)与字符串操作(String/StringBuilder/StringBuffer)详解
  • mysql中的索引怎么用?
  • 高压单端探头,如何实现大比例的衰减?
  • 在thinkphp5.0中。单表使用 model clone 时就会有问题。 需要使用 alias(), 否则会报错。
  • 关于推进网站集约化建设的讲话/私密浏览器免费版
  • 网站建设需要什么人员/商丘seo
  • 哈尔滨网站建设v5star/石家庄seo排名公司
  • 网页游戏排行榜2022前十名最新排名图片/网站推广和优化系统
  • 网站建设是否包含等保/商业策划公司十大公司
  • 玉溪网站建设现状/网页广告调词平台