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. 3层-CNN卷积神经网络预测MNIST数字

    3层-CNN卷积神经网络预测MNIST数字 本文创建一个简单的三层卷积网络来预测 MNIST 数字.这个深层网络由两个带有 ReLU 和 maxpool 的卷积层以及两个全连接层组成. MNIST 由 ...

  2. 保姆级尚硅谷SpringCloud学习笔记(更新中)

    目录 前言 正文内容 001_课程说明 002_零基础微服务架构理论入门 微服务优缺点[^1] SpringCloud与微服务的关系 SpringCloud技术栈 003_第二季Boot和Cloud版 ...

  3. RF中在测试用例集上设置标签

    1.有时候我们在执行测试用例时只想执行部分测试用例集下面的测试用例,这时可以在相应的测试用例集中设置标签,然后运行时选择标签执行对应的测试用例 语法: *** Settings *** Force T ...

  4. Spring FactoryBean和BeanFactory 区别

    1 BeanFactory 是ioc容器的底层实现接口,是ApplicationContext 顶级接口 spring不允许我们直接操作 BeanFactory  bean工厂,所以为我们提供了App ...

  5. Spring MVC 到 Spring BOOT 的简化之路

    背景 Spring vs Spring MVC vs Spring Boot Spring FrameWork Spring 还能解决什么问题 Spring MVC 为什么需要Spring Boot ...

  6. 数位dp从会打模板到不会打模板

    打了几个数位$dp$,发现自己除了会打模板之外没有任何长进,遇到非模板题依然什么都不会 那么接下来这篇文章将介绍如何打模板(滑稽) 假设我们要处理$l----r$ 采用记忆化搜索的方式,枚举$< ...

  7. 连接过的WiFi改了密码之后再次连接不让输入新密码还是用旧密码一直显示连接失败

    设置---网络和Internet---WLAN----管理已知网络----忘记    根据这个步骤就能忘记密码,重新输入新密码了.

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

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

  9. linux 下安装 docker 环境

    一分钟了解 Docker Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源.Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然 ...

  10. Java并发之ReentrantLock源码解析(三)

    ReentrantLock和BlockingQueue 首先,看到这个标题,不要怀疑自己进错文章,也不要怀疑笔者写错,哈哈.本章笔者会从BlockingQueue(阻塞队列)的角度,看看juc包下的阻 ...