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