Spring Boot邮箱链接注册验证

简单介绍

注册流程

【1】前端提交注册信息

【2】后端接受数据

【3】后端生成一个UUID做为token,将token作为redis的key值,用户数据作为redis的value值,并设置key的时长

【4】后端根据用户信息中的邮箱地址信息,检验用户是否已经注册,如果没有,生成注册链接发送到用户邮箱,如果已经注册,提示用户该邮箱地址已被注册

【5】用户点击邮件中的注册链接

【6】后端判断redis中token是否过期,没有将用户信息保存到数据库,提示用户注册成功

项目源码:https://gitee.com/residual-temperature/email-link-demo.git

邮箱效果图

实现过程

1、pom文件要加入的jar包

 	   <!-- 邮件相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency> <!-- redis相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、application.yml文件中要加入的配置

spring:
redis:
host: # redis地址
port: 6379 # redis端口号(默认6379)
password: # redis密码
mail:
host: smtp.qq.com # 邮箱协议
username: 地址 # 发送的邮箱地址
password: 授权码 # 邮箱的授权码

3、定义实体类


@Repository
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private long id;
private String account;
private String password;
private String username; }

注意

此处没有get(),set()方法是因为导入了lombok包

4、redis的config配置

对象的保存需要序列化,所以需要自定义RedisTemplete


@Configuration
public class RedisConfig {
//编写自己的配置类
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
//为了开发方便一般使用<String,Object>
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
//JSON序列化的配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//String的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer); //hash采用String的序列方式
template.setHashKeySerializer(stringRedisSerializer); //value序列化采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer); //hash的Value序列化采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}

5、验证链接生成和邮箱发送的工具类CodeUtils的配置

@Component
public class CodeUtils { @Resource
JavaMailSender mailSender; @Resource
RedisTemplate<String, User> redisTemplate; // 生成链接,并给接收的邮箱发送邮件
public boolean sendCode(User user){
MimeMessage message = mailSender.createMimeMessage();
try{
MimeMessageHelper messageHelper = new MimeMessageHelper(message);
String token = UUID.randomUUID().toString(); // 生成UUID
redisTemplate.opsForValue().set(token,user);
redisTemplate.expire(token,300, TimeUnit.SECONDS);
messageHelper.setFrom("发送方的邮箱地址"); //发送方的邮箱地址,而不是接收方的邮箱地址
messageHelper.setTo(user.getAddress()); // 接收方的邮箱地址
messageHelper.setSubject("注册"); // 邮箱标题
String html = "<html>\n" +
"<body>\n" +
"<p>请点击下方链接注册</p>\n" +
"<a href=\"http://localhost:8081/lookCode/"+token+"\">http://localhost:8081/lookCode/"+token+"</a>" +
"</body>\n" +
"</html>";
messageHelper.setText(html,true); // 邮箱内容
mailSender.send(message); // 发送邮箱
System.out.println("发送成功");
return true;
}catch (Exception e){
System.out.println("发送失败");
return false;
}
} // 判断token是否过期
public boolean eqToken(String token){
return redisTemplate.hasKey(token);
} // 根据token查询用户的信息
public User findUser(String token){
return redisTemplate.opsForValue().get(token);
} }

6、UserMapper的配置

@Mapper
@Repository
public interface UserMapper { // 添加用户 注解开发sql语句
@Insert("insert into user(account,password,username) values (#{account},#{password},#{username})")
public int addUser(User user); }

7、UserService的配置

public interface UserService {

    // 添加用户
public boolean adduser(User user); // 根据用户注册信息进行注册链接的的生成和发送
public boolean sendCode(User user); // 用户点击注册链接判断token是否过期
public boolean eqToken(String token); }

8、UserService的实现类UserServiceImpl的配置

@Service
public class UserServiceImpl implements UserService { @Resource
UserMapper userMapper; @Resource
CodeUtils codeUtils; /**
* 添加注册的用户信息
* @param user 注册的用户信息
* @return 是否添加成功
*/
@Override
public boolean adduser(User user) {
return userMapper.addUser(user) > 0;
} /**
* 生成链接和发送链接
* @param address 接收的邮箱地址
* @param user 注册的用户信息
*/
@Override
public boolean sendCode(User user) {
if ( codeUtils.sendCode(user)) // 调用验证链接生成工具类中的生成链接和发送邮件函数
return true;
else
return false;
} /**
* 判断token是否过期
* @param token 用户注册所接收的token
* @return 注册成功与否
*/
@Override
public boolean eqToken(String token) {
boolean flag = codeUtils.eqToken(token); if (flag){
User user = codeUtils.findUser(token);
adduser(user);
return true;
}else {
return false;
}
}
}

9、UserController的配置

@RestController
public class UserController { @Resource
UserService userService; // 根据用户注册信息进行注册链接的的生成和发送
@PostMapping("/sendCode")
public Map<String,String> sendCode(@RequestBody User user){
boolean flag = userService.sendCode(user);
Map<String,String> map = new HashMap<>();
if (flag){
map.put("msg","邮件发送成功,请前往您的邮箱进行注册验证");
return map;
}else {
map.put("msg","邮件发送失败");
return map;
}
} // 判断是否注册成功
@GetMapping("/lookCode/{token}")
public Map<String,String> lookCode(@PathVariable("token")String token){
boolean flag = userService.eqToken(token);
Map<String,String> map = new HashMap<>();
if (flag){
map.put("msg","注册成功");
/* 后续的操作 ... ...*/
return map;
}else {
map.put("msg","注册码过期,请重新注册");
return map;
}
}
}

因为没有写前端页面,所以就用postman和页面来演示

postman测试

传入user对象

返回结果

邮箱链接

点击注册链接之后

注册成功之后数据库前后对比

注册成功之前



注册成功之后

总结

可能会遇到的问题

【1】有些内部网络不支持发送邮箱,如果保证代码没错,可以换个网络试试

【2】如果是在本地测试,连接的是本地redis,记得开启本地的redis

Spring Boot邮箱链接注册验证的更多相关文章

  1. 将Spring Boot应用程序注册成为系统服务

    文章目录 前期准备 打包成可执行jar包 注册成为liunx服务 System V Init Systemd Upstart 在Windows中安装 Windows Service Wrapper J ...

  2. Java实现发送邮箱验证码/注册验证链接

    本文以163邮箱为例 1.准备(邮箱账号,邮箱必须设置POP3/SMTP/IMAP,设置步骤如下:) >>步骤:1 开启授权码服务 >>步骤:2 手机获取验证码 >> ...

  3. Spring Boot学习——表单验证

    我觉得表单验证主要是用来防范小白搞乱网站和一些低级的黑客技术.Spring Boot可以使用注解 @Valid 进行表单验证.下面是一个例子. 例子说明:数据库增加一条Student记录,要求学生年龄 ...

  4. spring boot 使用hibernate validator 验证service

    不在controller中验证,而是在service中验证. spring boot 默认使用的就是hibernate validator,存在于pom的spring-boot-starter-web ...

  5. 20190219备份 java spring boot 学习链接(日/英)

    Building web applications with Spring Boot and Kotlin https://www.slideshare.net/masuda220/spring-82 ...

  6. Spring Boot 5 SpringSecurity身份验证

    对于没有访问权限的用户需要转到登录表单页面.要实现访问控制的方法多种多样,可以通过Aop.拦截器实现,也可以通过框架实现(如:Apache Shiro.Spring Security). pom.xm ...

  7. Spring boot中注册Servlet

    Spring boot中注册Servlet 如何在spring boot项目中注册Servlet呢? 如何在spring boot项目中注册Servlet呢? 由于没有web.xml,无法直接在xml ...

  8. 玩转spring boot——AOP与表单验证

    AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...

  9. 第5章 Spring Boot 功能

    Spring Boot 功能 本节将会介绍Spring Boot的一些细节. 在这里,您可以了解您将要使用和自定义的主要功能. 如果还没有准备好,您可能需要阅读第二部分“入门指南”和第三部分“使用 S ...

随机推荐

  1. SOLOv 2:实例分割(动态、更快、更强)

    SOLOv 2:实例分割(动态.更快.更强) SOLOv2:  Dynamic, Faster and Stronger 论文链接: https://arxiv.org/pdf/2003.10152. ...

  2. 大尺寸卫星图像目标检测:yoloT

    大尺寸卫星图像目标检测:yoloT 1. 前言 YOLT论文全称「You Only Look Twice: Rapid Multi-Scale Object Detection In Satellit ...

  3. GPU上创建目标检测Pipeline管道

    GPU上创建目标检测Pipeline管道 Creating an Object Detection Pipeline for GPUs 今年3月早些时候,展示了retinanet示例,这是一个开源示例 ...

  4. 【VBA】列号与字母(列名)的相互转换 (自定义函数)

    1. '列号转字母(列名) Function Num2Name(ByVal ColumnNum As Long) As String On Error Resume Next Num2Name = & ...

  5. Flink从Kafka取数WordCount后TableApi写入ES

    一.背景说明 需求为从Kafka消费对应主题数据,通过TableApi对数据进行WordCount后,基于DDL写法将数据写入ES. 二.代码部分 说明:代码中关于Kafka及ES的连接部分可以抽象到 ...

  6. ESCMScript(1)let和const

    1.let命令 基本语法 ES6 新增了let命令,用来声明变量.它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. { let a = 1 var b = 2 console ...

  7. JAVA实现按列表中元素的时间字段排序

    JAVA代码实现按列表中元素的时间字段排序 导语: 工作中遇到一个问题,调用第三方接口返回的数据没有按时间倒序排列,测试说要加,然后在网上找到一个解决办法,这里记录一下 需求: 如下图列表,按生日进行 ...

  8. vue 快速入门 系列 —— vue loader 上

    其他章节请看: vue 快速入门 系列 vue loader 上 通过前面"webpack 系列"的学习,我们知道如何用 webpack 实现一个不成熟的脚手架,比如提供开发环境和 ...

  9. IP地址与子网的划分

    一.IP地址 1.IP地址的定义 (1).IP地址有32位二进制数组成,一般用点分十进制来表示 (2).IP地址由两部分组成 网络部分(NETWORK) 主机部分(HOST) 2.IP地址的分类 IP ...

  10. 【NLP学习其三】在学习什么是嵌入之前,你应该了解什么是词语表征

    在了解什么是嵌入(embeddings)之前,我们需要先搞清楚一个词语在NLP中是如何被表示的 注:本次不涉及任何具体算法,只是单纯对概念的理解 词汇表征 One-Hot 词汇的表示方法有很多,最有名 ...