最近在试了试使用验证码注册账号和修改密码,这个难度一般,只要按照对应步骤即可。
(在校验验证码时出现小问题,涉及到Redis暂时存储验证码)
一、在此之前需要获得邮箱授权码(我用的是QQ邮箱的)
1、网页版QQ邮箱右上角点击账号与安全
2、进入安全设置,最下面POP3服务需要先绑定手机号
3、点击前往绑定后弹出该页面,要发送对应的短信进行验证
4、绑定后会给你发一个验证码,输入验证码弹出绑定成功页面
5、接下来点击开启服务
6、还要继续发送验证码,可以扫码,也可以选择其他验证方式(也是发短信)
7、短信完成验证后,点击我已发送,弹出授权码窗口
可以先记住授权码,待会需要使用,使用授权码意义是不需要在第三方等应用上用密码登录,只需使用授权码即可,防止泄露密码。
二、回到SpringBoot工程
1、先导入邮箱对应依赖
<!--邮箱授权码,我用的是QQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2、配置resources资源文件下的properties文件(我是用的是yml格式)
spring:
mail:
host: smtp.qq.com
username: XXXX@qq.com #用来发邮件的邮箱
password: XXXX #你的邮箱授权码
default-encoding: UTF-8
其中host后面跟的是收邮件/发邮件的服务器(收pop3/发smtp),可以自行百度
3、发送验证码接口实现类SendCodeServiceImpl ,前端传来参数邮箱param
import com.xuecheng.checkcode.model.CheckCodeResultDto;
import com.xuecheng.checkcode.service.AbstractCheckCodeService;
import com.xuecheng.checkcode.service.SendCodeService;
import org.apache.http.HttpEntity;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import java.io.IOException;
/**
* @description:
* @author: xinTong
* @create: 2024-02-14 12:53
**/
@Service
public class SendCodeServiceImpl implements SendCodeService {
@Autowired
private AbstractCheckCodeService abstractCheckCodeService;
@Value("${spring.mail.username}")
private String sendUser;
@Autowired
private JavaMailSender javaMailSender;
public CheckCodeResultDto send(String param) {
//邮箱验证码
// 1、先生成验证码
// 2、存入Redis
AbstractCheckCodeService.GenerateResult emailCode = abstractCheckCodeService
.generate(null, 4, "EmailCode", 180);
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setFrom(sendUser);
simpleMailMessage.setTo(param);
simpleMailMessage.setSubject("验证码");
simpleMailMessage.setText("Code:" + emailCode.getCode());
javaMailSender.send(simpleMailMessage);
CheckCodeResultDto checkCodeResultDto = new CheckCodeResultDto();
checkCodeResultDto.setKey(emailCode.getKey());
return checkCodeResultDto;
}
}
其中的参数是Form --邮件发送者,Subject--邮件标题,Test--邮件内容,To--邮件收件者
4、存入中间件Redis中
向之前的properties配置类中添加
redis:
host: localhost #你的主机
port: 6379 #端口号
password: redis #你的redis密码
database: 0
lettuce:
pool:
max-active: 20
max-idle: 10
min-idle: 0
timeout: 10000
Redis工具类:
import com.xuecheng.checkcode.service.CheckCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* redis存储验证码
*/
@Component("RedisCheckCodeStore")
public class RedisCheckCodeStore implements CheckCodeService.CheckCodeStore {
@Autowired
RedisTemplate redisTemplate;
@Override
public void set(String key, String value, Integer expire) {
redisTemplate.opsForValue().set(key,value,expire, TimeUnit.SECONDS);
}
@Override
public String get(String key) {
return (String) redisTemplate.opsForValue().get(key);
}
@Override
public void remove(String key) {
redisTemplate.delete(key);
}
}
验证码生成工具类:
import com.xuecheng.checkcode.model.CheckCodeParamsDto;
import com.xuecheng.checkcode.model.CheckCodeResultDto;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
@Slf4j
public abstract class AbstractCheckCodeService implements CheckCodeService {
protected CheckCodeGenerator checkCodeGenerator;
protected KeyGenerator keyGenerator;
protected CheckCodeStore checkCodeStore;
public abstract void setCheckCodeGenerator(CheckCodeGenerator checkCodeGenerator);
public abstract void setKeyGenerator(KeyGenerator keyGenerator);
public abstract void setCheckCodeStore(CheckCodeStore CheckCodeStore);
/**
* @description 生成验证公用方法
* @param checkCodeParamsDto 生成验证码参数
* @param code_length 验证码长度
* @param keyPrefix key的前缀
* @param expire 过期时间
* @return com.xuecheng.checkcode.service.AbstractCheckCodeService.GenerateResult 生成结果
*/
public GenerateResult generate(CheckCodeParamsDto checkCodeParamsDto,Integer code_length,String keyPrefix,Integer expire){
//生成四位验证码
String code = checkCodeGenerator.generate(code_length);
log.debug("生成验证码:{}",code);
//生成一个key
String key = keyGenerator.generate(keyPrefix);
//存储验证码
checkCodeStore.set(key,code,expire);
//返回验证码生成结果
GenerateResult generateResult = new GenerateResult();
generateResult.setKey(key);
generateResult.setCode(code);
return generateResult;
}
@Data
public class GenerateResult{
String key;
String code;
}
public abstract CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto);
public boolean verify(String key, String code){
if (StringUtils.isBlank(key) || StringUtils.isBlank(code)){
return false;
}
String code_l = checkCodeStore.get(key);
if (code_l == null){
return false;
}
boolean result = code_l.equalsIgnoreCase(code);
if(result){
//删除验证码 -- Redis中的
checkCodeStore.remove(key);
}
return result;
}
}
5、验证码接口CheckCodeService
import com.xuecheng.checkcode.model.CheckCodeParamsDto;
import com.xuecheng.checkcode.model.CheckCodeResultDto;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
import java.util.Map;
public interface CheckCodeService {
/**
* @description 生成验证码
* @param checkCodeParamsDto 生成验证码参数
* @return com.xuecheng.checkcode.model.CheckCodeResultDto 验证码结果
*/
CheckCodeResultDto generate(CheckCodeParamsDto checkCodeParamsDto);
/**
* @description 校验验证码
* @param key
* @param code
* @return boolean
*/
public boolean verify(String key, String code);
/**
* @description 验证码生成器
*/
public interface CheckCodeGenerator{
/**
* 验证码生成
* @return 验证码
*/
String generate(int length);
}
/**
* @description key生成器
*/
public interface KeyGenerator{
/**
* key生成
* @return 验证码
*/
String generate(String prefix);
}
/**
* @description 验证码存储
*/
public interface CheckCodeStore{
/**
* @description 向缓存设置key
* @param key key
* @param value value
* @param expire 过期时间,单位秒
* @return void
*/
void set(String key, String value, Integer expire);
String get(String key);
void remove(String key);
}
}
可以试试,有问题可以私聊我,有可能会漏一点代码