项目优化方案之---实现邮箱用户登录

之前的项目中我写的基于SpringBoot和Vue的全栈项目已经实现了基本的用户接口开发,

不过其代码的功能单一,而且写的也是有不少漏洞(基本就像刚接手的代码*山一样)

那之后的几篇文章都来分享一下如何优化项目(每一章都独立讲方案,不必看之前的)

这里来添加一种登录方法,用邮箱来登录(实际思路跟手机号登录是差不多的,而且都是要借助一些第三方的工具实现)

操作之前先来梳理一下实现流程:

1.用户填写其邮箱(这里我只用QQ邮箱实现)

2.点击发送验证码按钮(ok,此处需要发送请求到后端进行一系列操作Todo)

3.获取到了验证码,填写验证码,并点击登录按钮(这里又要调用一次接口检验验证码是否正确)

总结一下后端要做的接口有哪些:

1.接收qq邮箱并生成验证码发送请求

       (具体实现:1.校验QQ邮箱是否格式正确(这里用SpringValildation即可),2.生成验证码,并将其保存到(??),这里其实有很多种方案可供选择,比如放到session,这里的话我用ThreadUtils操作一下,(后续统一用Redis操作),然后使用第三方工具把验证码发送到对应的QQ邮箱就可以了)

2.接收用户的验证码和其QQ邮箱号,进行二次校验,验证验证码与生成的验证码是否相等,如果相等就可以根据QQ邮箱去查找是否有这个人(这里可以拓展一下,如果没有这个人就可以直接帮他注册),这里没有这个人就返回没有这个用户并让其去注册的消息,如果有这个人就按照正常流程登录即可,(这里我的登录用的是JWT令牌,如果登录成功还要返回令牌给前端)

Ok,开始后端接口开发:

1.定义DTO

先确认一下之前定义的User实体类中要有email属性啊

    @Email@NotEmpty(message = "邮箱不能为空")private String email;

这里在User实体类这里记得要加上email邮箱属性(这里还有两个注释)

我这里用到了SpringValidation进行参数校验,(也就是这两个注解),不知道的同志可以看看之前的文章或者上网搜一下。

OK,这里就可以定义一个接收的实体类了,

由于两个接口一个接收QQ邮箱,一个接收QQ邮箱+验证码,因此这一个DTO也就足够了(如果愿意,也可以用User,不过我这个User定义的属性似乎有点多,感觉会很麻烦)

package org.example.cetidenet.model.dto.user;import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;public class UserEmailDTO {@Email@NotEmpty(message = "邮箱不能为空")private String email;private String code;public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}@Overridepublic String toString() {return "UserEmailDTO{" +"email='" + email + '\'' +", code='" + code + '\'' +'}';}
}

2.开发发送验证码的接口

在Controller类这里我们新定义一个方法

    @PostMapping("/submitEmail")public Result<User> submitEmail(@RequestBody @Validated UserEmailDTO userEmailDTO) {return userService.submitEmail(userEmailDTO);}

这里由于已经使用了@Validated来进行参数校验了,那我们直接返回userService的方法就好,尽量把逻辑处理的函数都放到Service的实现类中。

既然邮箱的格式已经正确了就生成一串随机数字吧

这里就使用RandomUtil生成

String code = RandomUtil.randomNumbers(6);

这样就生成了一个6位的随机数字;

既然万事俱备,那么就该发送验证码了,

3.讲解QQ邮箱发送验证码:
 

这里我使用JavaMail发送验证码,来看看使用方法:
 

步骤1.获取QQ邮箱授权码:

点开QQ邮箱,左上角有设置,点击设置

再点击账号

往下翻,点击开启服务即可

然后通过验证即可获取到授权码,(记得保存好)

步骤2:在后端工程中引入依赖
<dependency><groupId>javax.mail</groupId><artifactId>mail</artifactId><version>1.4</version>
</dependency>
步骤3:按照代码填充:
import java.security.Security;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;public class MailClient {public static void main(String[] args) {try {final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";//配置邮箱信息Properties props = System.getProperties();//邮件服务器props.setProperty("mail.smtp.host", "smtp.qq.com");props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);props.setProperty("mail.smtp.socketFactory.fallback", "false");//邮件服务器端口props.setProperty("mail.smtp.port", "465");props.setProperty("mail.smtp.socketFactory.port", "465");//鉴权信息props.setProperty("mail.smtp.auth", "true");//建立邮件会话Session session = Session.getDefaultInstance(props, new Authenticator() {//身份认证protected PasswordAuthentication getPasswordAuthentication() {//1.账户 授权码return new PasswordAuthentication("xxxxxxx@qq.com", "xxxx");}});//建立邮件对象MimeMessage message = new MimeMessage(session);//设置邮件的发件人message.setFrom(new InternetAddress("xxxxxxx@qq.com"));//2.设置邮件的收件人message.setRecipients(Message.RecipientType.TO, "xxxxxxx@qq.com");//设置邮件的主题message.setSubject("通过javamail发出!!!");//文本部分message.setContent("文本邮件测试", "text/html;charset=UTF-8");message.saveChanges();//发送邮件Transport.send(message);} catch (Exception e) {e.printStackTrace();}}
}

此处将          return new PasswordAuthentication("xxxxxxx@qq.com", "xxxx");

填充为你的账号和授权码,

下面的发件人填写你的邮箱(不要填别人的,不然要报错的)

收件人的邮箱填Controller类处接收到的代码即可;

下面来具体实现一下:

这个邮箱发送代码较长,这边可以将其封装为一个工具类或者函数(我感觉这种要长不长,要短不短的封装成函数比较合适)

那就来展示一下UserServiceImpl的这个方法调用吧;

@Overridepublic Result<User> submitEmail(UserEmailDTO userEmailDTO) {String email = userEmailDTO.getEmail();String code = RandomUtil.randomNumbers(6);sendEmail(email,code);ThreadLocalUtil.set(code);return Result.success();}private static void sendEmail(String email,String code){try {final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";//配置邮箱信息Properties props = System.getProperties();//邮件服务器props.setProperty("mail.smtp.host", "smtp.qq.com");props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);props.setProperty("mail.smtp.socketFactory.fallback", "false");//邮件服务器端口props.setProperty("mail.smtp.port", "465");props.setProperty("mail.smtp.socketFactory.port", "465");//鉴权信息props.setProperty("mail.smtp.auth", "true");//建立邮件会话Session session = Session.getDefaultInstance(props, new Authenticator() {//身份认证protected PasswordAuthentication getPasswordAuthentication() {//1.账户 授权码return new PasswordAuthentication("1147683258@qq.com", "bsfyppqvhrqqecgj");}});//建立邮件对象MimeMessage message = new MimeMessage(session);//设置邮件的发件人message.setFrom(new InternetAddress("1147683258@qq.com"));//2.设置邮件的收件人message.setRecipients(Message.RecipientType.TO, email);//设置邮件的主题message.setSubject("来自Cetide网的信息");//文本部分message.setContent("收到您的登录请求发送验证码"+code, "text/html;charset=UTF-8");message.saveChanges();//发送邮件Transport.send(message);} catch (Exception e) {e.printStackTrace();}}

Ok,那么这个接口也就开发的差不多了,这里来验证一下吧,启动SpringBoot项目并打开Swagger试试

输入一个QQ小号的地址即可发送出验证码

那么,这也就发送成功了。(这里我测试的时候,感觉请求发出过程好慢,可以看看有没有更快速一些的QQ邮箱调用)

后续的登录就比较简单了,这里添加一个登录接口

这边也就不细致讲解了,直接上代码,大家观看吧

    @PostMapping("/email/submit")public Result login(@RequestBody @Validated UserEmailDTO userEmailDTO){// 实现登录功能return userService.emailLogin(userEmailDTO);}
    @Overridepublic Result emailLogin(UserEmailDTO userEmailDTO) {String email = userEmailDTO.getEmail();String userCode = userEmailDTO.getCode();String code = ThreadLocalUtil.get();if(!code.equals(userCode)){return Result.error("验证码错误");}//现在说明这个验证码正确User user = userMapper.findByEmail(email);if(user == null){return Result.error("该邮箱未注册用户,请先注册");}//存在该用户Map<String, Object> claims = new HashMap<>();claims.put("id", user.getId());claims.put("username", user.getUserName());String token = JwtUtil.genToken(claims);//存在且密码正确return Result.success(token);}
    @Select("select * from user where  email = #{email}")User findByEmail(String email);

此处代码也就差不多能够实现根据QQ邮箱登录的功能了;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/21897.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JMeter性能测试实现与分析分享

JMeter是由著名开源软件巨头Apache组织开发的纯Java的压力测试工具&#xff0c;它即能测试动态服务&#xff08;WebService&#xff09;&#xff0c;也能测试静态资源&#xff0c;包括Servlet服务、CGI脚本等&#xff0c;还能测试动态语言服务&#xff08;PHP、Java、ASP.NET等…

JVM学习-监控工具(二)

jmap&#xff1a;导出内存映像文件&内存使用情况 基本情况 jmap(JVM Memory Map)&#xff1a;一方法获取dump文件(堆转储快照文件&#xff0c;二进制文件)&#xff0c;还可以获取目标Java进程的内存相关信息&#xff0c;包括Java堆各区域的使用情况、堆中对象的统计信息、…

MyBatis学习(二)--MyBatis获取参数值的两种方式

1、搭建新的module:mybatis_parameter MyBatis获取参数值的两种方式&#xff1a;${}和#{} ${}的本质就是字符串拼接&#xff0c;采用sql拼接&#xff0c;无法防止sql注入 #{}的本质就是占位符赋值 &#xff0c;采用预编译 防止sql注入 不同参数使用案例 2、单个字面量类型…

OpenHarmony嵌套类对象属性变化:@Observed装饰器和@ObjectLink装饰器

上文所述的装饰器仅能观察到第一层的变化&#xff0c;但是在实际应用开发中&#xff0c;应用会根据开发需要&#xff0c;封装自己的数据模型。对于多层嵌套的情况&#xff0c;比如二维数组&#xff0c;或者数组项class&#xff0c;或者class的属性是class&#xff0c;他们的第二…

实时瞳孔分割算法-RITnet论文复现

源代码在这里RITnet-Github 这个模型比较小众&#xff0c;我们实验室使用了官方提供的模型进行瞳孔中心位置提取&#xff0c;以实现视线追踪&#xff0c;效果很好 一、数据集准备 RITnet也是那一届openEDS数据集挑战赛的冠军模型&#xff0c;openEDS数据集可以从Kaggle上下载&a…

数据结构--关键路径

事件v1-表示整个工程开始&#xff08;源点&#xff1a;入度为0的顶点&#xff09; 事件v9-表示整个工程结束&#xff08;汇点&#xff1a;出度为0的顶点&#xff09; 关键路径&#xff1a;路径长度最长的路径 求解关键路径问题&#xff08;AOE网&#xff09; 定义四个描述量 …

网络网络层之(6)ICMPv4协议

网络网络层之(6)ICMPv4协议 Author: Once Day Date: 2024年6月2日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 通信网络技术_Once-Day的博客-CS…

大模型备案项目补贴政策一览【保持更新】

大模型项目、AI类项目、大模型备案通过后等一篮子财政补贴政策 上海市 加快创新体系构建 1. 提升自主创新水平&#xff1a;对引领大模型发展或取得颠覆性突破的项目&#xff0c;最高给予1000万元补贴支持。 2. 加强算力资源保障&#xff1a;实施算力伙伴计划&#xff0c;对…

力扣174题动态规划:地下城游戏(含模拟面试)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业…

Java进阶学习笔记36——算法

什么是算法&#xff1f; 解决某个实际问题的过程和方法。 1&#xff09;导航&#xff1b; 2&#xff09;滴滴打车&#xff1b; 3&#xff09;抖音&#xff1b; 不同的算法&#xff0c;效率高、性能好&#xff01; 在Java中&#xff0c;代码已经帮我们写好了&#xff0c;但为…

离散点云拟合三维平面参数推导(基于最小二乘)

1、背景介绍 实际中&#xff0c;很多人工构造物是由平面结构构造而成&#xff0c;如下图所示&#xff0c;为一典型的由多个平面组成的人工构筑物。因此&#xff0c;根据离散点拟合成平面&#xff0c;获取拟合平面方程&#xff0c;是点云数据处理中非常常见的数据处理操作。 2、…

鸿蒙Ability Kit(程序框架服务)【ExtensionAbility组件】

ExtensionAbility组件 ExtensionAbility组件是基于特定场景&#xff08;例如服务卡片、输入法等&#xff09;提供的应用组件&#xff0c;以便满足更多的使用场景。 每一个具体场景对应一个[ExtensionAbilityType]&#xff0c;开发者只能使用&#xff08;包括实现和访问&#…

WPS的excel表格设置了编辑权限,要怎么取消?

在日常生活和工作中&#xff0c;我们经常会使用WPS Office办公软件来处理各种文档&#xff0c;其中WPS Excel表格是我们进行数据处理和分析的重要工具。为了保护表格中的数据不被随意修改&#xff0c;我们有时会设置编辑权限。然而&#xff0c;随着时间的推移或需求的变更&…

基于FPGA的SystemVerilog练习

文章目录 一、认识SystemVerilogSystemVerilog的语言特性SystemVerilog的应用领域SystemVerilog的优势SystemVerilog的未来发展方向 二、流水灯代码流水灯部分testbench仿真文件 三、用systemVerilog实现超声波测距计时器测距部分led部分数码管部分采样部分顶层文件引脚绑定效果…

dpdk uio整体分析及网卡加载

参考:https://zhuanlan.zhihu.com/p/477600165 一、Linux内核知识点 1. __attribute__ constructor/destructor (1)若函数被设定为constructor属性,则该函数会在 main()函数执行之前被自动的执行。 (2)若函数被设定为destructor属性,则该函数会在main()函数执…

开发和渗透偷懒利器utools

目录 1.前言 1.1 工具简介 1.2 核心特性 1.3 使用场景 1.4 安装与使用 1.4.1 下载&#xff1a; 1.4.2 安装&#xff1a; 1.4.3 配置&#xff1a; 1.4.4 插件市场&#xff1a; 2.懒狗插件介绍 基本介绍 2.1 数据模拟 2.2 随机生成虚假数据 2.3 API市场 2.4 Hoppscot…

【十二】图解mybatis日志模块之设计模式

图解mybatis日志模块之设计模式 概述 最近经常在思考研发工程师初、中、高级工程师以及系统架构师各个级别的工程师有什么区别&#xff0c;随着年龄增加我们的技术级别也在提升&#xff0c;但是很多人到了高级别反而更加忧虑&#xff0c;因为it行业35岁年龄是个坎这是行业里的共…

一文读懂数据库中的DB、DBMS、DBS、DBAS

目前数据库的应用非常广泛,几乎各行各业都在直接或间接地与数据库打交道,例如网上购物、银行业务、铁路购票和酒店住宿等。在实际应用中,数据库、数据库管理系统、数据库系统和数据库应用系统经常被统称为数据库,而实质上这4个概念是不一样的,它们具有不同的定义和含义。下…

暴力数据结构之排序大杂烩

1. 冒泡排序&#xff1a;O(N^2) 逻辑解析&#xff1a; 冒泡排序并没有什么实际意义&#xff0c;但是有教学意义&#xff0c;相信大部分小白在学习的初期第一个接触的排序就是冒泡排序。那么接下来我们了解一下他的底层逻辑&#xff1a; 冒泡排序顾名思义就是将最大&#xff08…

idea项目maven下载依赖报错

报错&#xff1a; 1、Failure to find bad.robot:simple-excel:jar:1.0 in https://maven.aliyun.com/repository/public was cached in the local repository, resolution will not be reattempted until the update interval of aliyunmaven has elapsed or updates are forc…