大家肯定遇到过很多下面的场景,当你在某个网站、某个APP注册信息的时候,为了验证身份,需要填写你的邮箱地址,之后邮箱可能会收到验证码,也可能会收到一个里面有激活链接的邮件,叫你点击链接进行激活。

就像下面这样:

这两种方式是登录注册时对邮件任务的经典应用场景。

那么今天就继续上次整合登录的讲解,人脸识别和三方登录,往期的文章已经介绍了,有兴趣的回头再去看看。

邮件任务

SpringBoot已经为我们整合了对发送邮件的支持,也就是说我们可以使用代码,很方便的给指定的邮箱发送任意内容的邮件。

整合步骤

引入邮件任务依赖

<!--引入邮件任务依赖-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>

在SpringBoot的配置文件中配置邮件信息(以QQ邮箱为例)

spring: mail:username: 373675032@qq.compassword: ****************host: smtp.qq.comport: 465properties:mail:smtp:auth: truestarttls:enable: truerequired: truesocketFactory:port: 465class: javax.net.ssl.SSLSocketFactoryfallback: falsevalid: 5title: "用户验证"template: "您的动态验证码为:<strong style='color: red'>%s</strong>,%d分钟内有效,若非本人操作,请勿泄露。"
  • username:发送方邮箱,也就是你的邮箱地址
  • password:SMTP服务密码,并不是你的QQ密码

spring.mail.password通过下面方法获得

封装邮件服务类

/*** @author XUEW* @apiNote 邮件服务*/
@Service
public class EmailService {@Autowiredprivate JavaMailSenderImpl mailSender;/*** 发送方邮箱*/@Value("${spring.mail.username}")private String email;/*** 有效时长*/@Value("${spring.mail.valid}")private Integer valid;/*** 内容模版*/@Value("${spring.mail.template}")private String template;/*** 标题*/@Value("${spring.mail.title}")private String title;/*** 发送邮件验证码* @param targetEmail 目标邮箱* @return 验证码*/public String sendEmailCode(String targetEmail) {// 生成随机验证码String verifyCode = RandomUtil.randomNumbers(6);MimeMessage mimeMessage = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);try {helper.setSubject(title);helper.setText(String.format(template, verifyCode, valid), true);helper.setFrom(email);helper.setTo(targetEmail);} catch (MessagingException e) {e.printStackTrace();}mailSender.send(mimeMessage);return verifyCode;}/*** 发送邮箱* @param targetEmail 目标邮箱* @param content 发送内容*/public void sendEmail(String targetEmail, String title, String content) {MimeMessage mimeMessage = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(mimeMessage);try {helper.setSubject(title);helper.setText(content, true);helper.setFrom(email);helper.setTo(targetEmail);} catch (MessagingException e) {e.printStackTrace();}mailSender.send(mimeMessage);}
}

邮件验证码的实现思路

操作步骤大家肯定都知道,输入完邮箱地址点击获取验证码后,按钮变成了disable状态,并且开始倒计时一分钟。

如此同时向后端发送异步请求,调用刚才写的邮件服务向输入的邮箱发送验证码。

/*** 发送邮箱验证码*/
@PostMapping("/sendEmailCode")
@ResponseBody
public ResponseResult sendEmailCode(String email, Map<String,Object> map, HttpSession session) {if (StrUtil.isEmpty(email)) {return ResponseResult.failure(500, "邮箱不能为空");}// 发送验证码String verifyCode = emailService.sendEmailCode(email);map.put("email", email);map.put("code", verifyCode);map.put("time", new Date());session.setAttribute("EMAIL_CODE" + email, map);return ResponseResult.success();
}

发送完成后,将验证码与邮箱缓存,这里可以使用session或者redis。

用户收到验证码后,填写后点击登录,后端服务开始进行一些列的校验工作,比如:缓存中是否存在此邮箱?验证码是否正确?验证码是否过期?诸如此类的操作。校验没问题,那么就可以进行入库保存等操作了。

/*** 验证码登录*/
@GetMapping("/loginEmail")
public String loginSms(String email, String code, HttpSession session) {Map<String,Object> codeData = (Map<String, Object>) session.getAttribute("EMAIL_CODE" + email);if (codeData == null) {throw new RuntimeException("登录失败:尚未发送验证码");}String sentCode = (String) codeData.get("code");Calendar calendar = Calendar.getInstance();calendar.setTime((Date) codeData.get("time"));calendar.add(Calendar.MINUTE, 5);if (System.currentTimeMillis() > calendar.getTime().getTime()) {session.removeAttribute("EMAIL_CODE" + email);throw new RuntimeException("登录失败:验证码已经超时");}if (!sentCode.equals(code)) {throw new RuntimeException("登录失败:验证码错误");}// 校验全部通过,执行入库等业务操作// ...return "redirect:/success";
}

邮件激活链接实现思路

那么激活链接是如何实现的呢?首先既然叫激活,那么说明用户的信息肯定是已经存入数据库了,只不过用户的状态是尚未激活,所以无法正常使用系统。那么点击激活链接,其实主要目的就是把用户的状态修改为正常,大家首先要明白这一点。

当用户注册完成后,默认状态为【未激活】,在入库之后,后端就需要给注册邮箱发送激活链接,那么激活链接如何设计呢?我给大家提供两个思路:

思路一

生成一串随机字符串叫做密钥,因为用户信息已经存库,所以用户ID我们也是可以获取到,之后将密钥和用户id缓存,同样可以使用session或者redis。

之后将密钥和用户id拼接成URL的参数,像下面这样:

http://localhost:8080/activate?uid=1&key=asjkdjflksdajflasdfjdlsfj
/*** 发送邮箱激活链接*/
@PostMapping("/sendEmailActivateUrl")
@ResponseBody
public ResponseResult sendEmailActivateUrl(Integer uid, HttpSession session) {// 前提条件:发送之前已经保存用户到数据库User user = userService.get(uid);String serverUrl = "http://localhost:8080";String key = RandomUtil.randomString(10);String content = String.format("点击此链接进行激活: <a href=\"%s/activate?uid=%d&key=%s\">点我激活</a>", serverUrl, uid, key);// 发送邮件emailService.sendEmail(user.getEmail(), "激活链接", content);// 存入缓存session.setAttribute("ACTIVATE" + uid, key);return ResponseResult.success();
}

注意在激活链接中访问的是activate请求,路径传参数输入get方式,所以后端服务需要在controller中编写此服务用于激活用户。

/*** 用户激活* @param uid 用户ID* @param key 密钥* @return*/
@GetMapping("/activate")
public String activate(Integer uid, String key, HttpSession session) {User user = userService.get(uid);// 开始一系列校验if (Assert.isEmpty(user) ) {throw new RuntimeException("激活失败:尚未注册的用户");}if (user.getStatus() == 1) {throw new RuntimeException("激活失败:用户已完成激活");}// 获取激活信息String activateKey = (String) session.getAttribute("ACTIVATE" + uid);if (Assert.isEmpty(activateKey)) {throw new RuntimeException("激活失败:尚未发送激活邮件");}if (!activateKey.equals(key)) {throw new RuntimeException("激活失败:密钥匹配失败");}// 校验通过,更新用户状态// ...return "redirect:/success";
}

发送邮件的内容就可以是下面这样:

点击此链接进行激活: <a href="http://localhost:8080/activate?uid=1&key=asjkdjflksdajflasdfjdlsfj">点我激活</a>

收到的邮件如下:

思路二

和上面的区别主要在激活链接这块的设计,上面的可以实现,但是安全性和时效性上并不是很灵活和安全,所以我更推荐大家使用JWT Token的方式去作为激活链接的加密参数。

Token里面可以用来存放一些数据,并且可以很方便的设置Token的过期时间,这样我们在做校验的时候也会方便很多了。

所谓的JWT Token,也还是一串字符串,但是是混乱的,像下面这样:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImNpbmNvIiwicm9sZSI6ImFkbWluIiwic3ViIjoiYWRtaW4tdGVzdCIsImV4cCI6MTY0MjE0MDUyMCwianRpIjoiNDc0ZWRhNjUtYzI0Ny00OTg1LTgwNGEtMjM5NjliZjFhNDRhIn0.cRDXDjBmCMfgLCxNPINh_KBeKDPG-VNSA2LY95ySsmc

项目开源:https://github.com/373675032/login-system

简单实用的邮件任务 ,让验证码、激活链接来丰富你的登录注册相关推荐

  1. sql 拼接int类型的字段_一套简单实用的SQL脚本(下篇)

    点击上方SQL数据库开发,关注获取SQL视频教程 SQL专栏 SQL数据库基础知识汇总 SQL数据库高级知识汇总 之前已经分享了一部分内容<一套简单实用的SQL脚本(上篇)>接上一章我们继 ...

  2. 一款简单实用的桌面电子邮件客户端

    为大家分享一款Gmail 客户端,Mia for Gmail for mac运行在菜单栏,支持添加多个Gmail帐户,你可以快速搜索.阅读和撰写电子邮件,当你收到电子邮件时,Mia for Gmail ...

  3. html表格制作旅游网页,简单实用的网页表格特效_html

    在我们制作主页的过程中,用到表格的地方非常多,灵活运用表格技巧可以为我们的网页增色不少,这里我就详细介绍几中特效表格的制作方法. 一.彩色虚线表格 .tab1 { border-top-width: ...

  4. 发邮件(通过发邮件 激活用户/激活链接)

    POP3/SMTP服务 (如何使用 Foxmail 等软件收发邮件?) 已关闭 |  开启 IMAP/SMTP服务 (什么是 IMAP,它又是如何设置?) 已关闭 |  开启 Exchange服务 ( ...

  5. PS入门教程:简单实用的PS快捷键教程2

    上篇内容从工具箱.文件操作.图层混合.选择功能.视图操作五方面入手分类总结了常用的PS快捷键教程.这篇内容小编再将从编辑操作.图像调整.加点按.取消操作这五方面为大家加码日常都可用到的PS快捷键教程. ...

  6. django自带邮件模块实现用户注册激活邮件发送

    最近在看慕课网的利用Django搭建教学网站的视频,其中碰到了给注册用户发送激活邮件的问题.期间也遇到了一些小问题,在此记录一下. 实现邮件发送流程 利用django.core.mail模块下的sen ...

  7. windows 7重装系统(简单实用)

    记录一个简单实用的windows系统重装的简易操作,也是为了下次自己使用方便.因为公司电脑是32位,而现在的主流是64以及某些软件要求使用64位,所以需要重新安装一下系统. 1 https://msd ...

  8. XP系统优化简单实用技法收藏

    XP系统优化简单实用技法收藏 1.关闭计算机时自动结束任务: 在关机的时候,有时会弹出讨厌的对话框,提醒某个程序仍在运行,是否结束任务.其实完全梢酝ü坏愕阈薷娜肳indows自动结束这些仍在运行的程 ...

  9. 一个简单实用的,基于EF的三层架构

    到底什么样的框架才是好框架呢?或许不同人有不同的看法.我个人觉一个好的框架,最重要的要是简单实用,能快速适开发,可维护性高(不会出现复制黏贴的代码),并能快速响应各种业务场景的变化的框架,同时性能不会 ...

最新文章

  1. Linux 线程属性的使用
  2. 快速完全删除node_modules
  3. 在控制台中实现“单词竞猜”游戏 C# 猜词游戏
  4. Mr.J-- 简单生日页面制作
  5. SQL SERVER2008 存储过程、表、视图、函数的权限
  6. Linux Shell编程 - 正则表达式
  7. 如何批量生成UPC-E条码
  8. CAN 通信协议(希望大家多多指点)
  9. python动态心形代码-python心形代码
  10. RTT移植STM32之创建进程
  11. 使用 RuPengGame游戏引擎包 建立游戏窗体 如鹏游戏引擎包下载地址 Thread Runnable 卖票实例...
  12. win7密码破解之“替换法”
  13. registry登录认证
  14. java 抓取搜狗微信_搜狗微信公众号文章抓取
  15. CentOs虚拟机硬盘扩容
  16. 2011年国内手机市场如何推演?
  17. Spring更简单的存储对象------不使用XML而使用注解
  18. 使用以太坊和 Metamask 再也不需要输入密码
  19. cnpm安装 指定版本_vue npm install安装某个指定版本的方法
  20. 江苏省计算机二级Python备考经验(2020年10月考试)

热门文章

  1. 【linux】基础IO
  2. JavaScript简餐——函数尾调用优化
  3. 【运维能力提升计划-3】Java多线程详解
  4. 4g内存只识别2.5g的解决办法
  5. 150℃下使用的无铅焊锡:为车载基板开辟新路(一)
  6. 2022年了,你在用哪些Mac软件?
  7. 尤肖虎,中国3G、4G掌门人
  8. 利用条件函数判断计算机这课成绩及格情况,如何用Excel表格中的if函数来判断成绩及格不及格...
  9. StratifiedKFold 和 KFold 的比较
  10. 大数据揭秘:怎样才是高效率的工作?