最近做一個社區項目,發現很多地方都需要校驗是否爲用戶本人,然後做了個郵箱驗證分享給大家,當然也可以採用手機驗證碼。思想和郵箱驗證碼是類似的,只需要稍作修改。廢話不多說直接上代碼。
1.導入郵箱依賴
我這裏是基於spring boot下的maven項目,導入pom依賴。用的是springboot2.2.2版本。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2.有關application.yaml配置
#郵件發送
spring:
mail:
username:XXXX@qq.com
#郵箱授權碼,百度一下很簡單
password: 授權碼
host: smtp.qq.com
default-encoding: utf-8
#開啓加密驗證
properties:
mail:
smtp:
ssl:
enable: ture
3.創建一個工具類生成驗證碼
/**
* @Description TODO:郵箱驗證碼,採用SecureRandom真隨機數
* @Author 鬱郁201
* @Date 2020-01-20 17:03
* @Version 1.0
*/
public class VerCodeGenerateUtil {
//郵箱字符串提取,去除了容易混淆的幾個字符比如0,o~
private static final String SYMBOLS = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
private static final Random RANDOM = new SecureRandom();
/**
* 生成4位隨機驗證碼
* @return 返回4位驗證碼
*/
public static String getVerCode() {
char[] nonceChars = new char[4];
for (int index = 0; index < nonceChars.length; ++index) {
nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
}
return new String(nonceChars);
}
}
4.發送郵件驗證碼
創建ScheduledExecutorService線程池(該線程池,將計時和多線程結合一起,perfect),以便於多用戶獲取驗證碼放入session並計時。ReslutTypeDto爲返回前端的數據類型,VisitorStatusEmun爲枚舉類型,存放多種結果操作,下面附有註釋,可自行替換。
//創建線程池對象
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
//這個是我用戶Service實現類可以自行替換
@Autowired
UserServiceImpl userServiceImpl;
//這個是郵件類,必須要導入哦
@Autowired
JavaMailSenderImpl mailSender;
@GetMapping("/reg/sendEmail")
@ResponseBody
public ReslutTypeDto sendEmail(String email,HttpServletRequest request){
HttpSession session = request.getSession();
//驗證碼
String verCode = VerCodeGenerateUtil.getVerCode();
//發送時間 --這裏自己寫了一個時間類,格式轉換,用於郵件發送
String time = DateUtils.date2String(new Date(), "yyyy-MM-dd hh:mm:ss");
Map<String,String> map = new HashMap<>();
map.put("code",verCode);
map.put("email",email);
//驗證碼和郵箱,一起放入session中
session.setAttribute("verCode",map);
Map<String,String> codeMap = (Map<String,String>) session.getAttribute("verCode");
//創建計時線程池,到時間自動移除驗證碼
try {
scheduledExecutorService.schedule(new Thread(()->{
if(email.equals(codeMap.get("email"))){
session.removeAttribute("verCode");
}
}), 5*60, TimeUnit.SECONDS);
} catch (Exception e) {
e.printStackTrace();
}
//一下爲發送郵件部分
MimeMessage mimeMessage = null;
MimeMessageHelper helper = null;
try {
//發送複雜的郵件
mimeMessage = mailSender.createMimeMessage();
//組裝
helper= new MimeMessageHelper(mimeMessage, true);
//郵件標題
helper.setSubject("【Share社區】 註冊賬號驗證碼");
//因爲設置了郵件格式所以html標籤有點多,後面的ture爲支持識別html標籤
//想要不一樣的郵件格式,百度搜索一個html編譯器,自我定製。
helper.setText("<h3>\n" +
"\t<span style=\"font-size:16px;\">親愛的用戶:</span> \n" +
"</h3>\n" +
"<p>\n" +
"\t<span style=\"font-size:14px;\"> </span><span style=\"font-size:14px;\"> <span style=\"font-size:16px;\"> 您好!您正在進行郵箱驗證,本次請求的驗證碼爲:<span style=\"font-size:24px;color:#FFE500;\"> "+verCode+"</span>,本驗證碼5分鐘內有效,請在5分鐘內完成驗證。(請勿泄露此驗證碼)如非本人操作,請忽略該郵件。(這是一封自動發送的郵件,請不要直接回復)</span></span>\n" +
"</p>\n" +
"<p style=\"text-align:right;\">\n" +
"\t<span style=\"background-color:#FFFFFF;font-size:16px;color:#000000;\"><span style=\"color:#000000;font-size:16px;background-color:#FFFFFF;\"><span class=\"token string\" style=\"font-family:"font-size:16px;color:#000000;line-height:normal !important;background-color:#FFFFFF;\">Share社區</span></span></span> \n" +
"</p>\n" +
"<p style=\"text-align:right;\">\n" +
"\t<span style=\"background-color:#FFFFFF;font-size:14px;\"><span style=\"color:#FF9900;font-size:18px;\"><span class=\"token string\" style=\"font-family:"font-size:16px;color:#000000;line-height:normal !important;\"><span style=\"font-size:16px;color:#000000;background-color:#FFFFFF;\">"+time+"</span><span style=\"font-size:18px;color:#000000;background-color:#FFFFFF;\"></span></span></span></span> \n" +
"</p>",true);
//收件人
helper.setTo(email);
//發送方
helper.setFrom(我的郵箱);
try {
//發送郵件
mailSender.send(mimeMessage);
} catch (MailException e) {
//郵箱是無效的,或者發送失敗
return new ReslutTypeDto(VisitorStatusEmun.Email_Invalid);
}
} catch (MessagingException e) {
//發送失敗--服務器繁忙
return new ReslutTypeDto(VisitorStatusEmun.Server_Busy);
}
//發送驗證碼成功
return new ReslutTypeDto(VisitorStatusEmun.Send_Email_Captcha_OK);
}
5.接收並使用郵件驗證碼
最後一步註冊時使用驗證碼,獲取了前端三個參數,郵箱(username),密碼,驗證碼(vercode)。
//這裏我採用的是email作爲username
@PostMapping("/reg")
@ResponseBody
public ReslutTypeDto reg(String username,
String password,
String verCode,
HttpServletRequest httpServletRequest){
HttpSession session = httpServletRequest.getSession();
Map<String,String> codeMap = (Map<String,String>)session.getAttribute("verCode");
String code = null;
String email = null;
try {
code = codeMap.get("code");
email = codeMap.get("email");
} catch (Exception e) {
//驗證碼過期,或未找到 ---驗證碼無效
return new ReslutTypeDto(VisitorStatusEmun.Email_Captcha_Invalid);
}
//驗證碼判斷
if (!verCode.toUpperCase().equals(code) || !username.equals(email)) {
return new ReslutTypeDto(VisitorStatusEmun.Email_Captcha_Fail);
}
//驗證碼使用完後session刪除
session.removeAttribute("verCode");
User user = userServiceImpl.findUserByName(username);
//用戶名是否可用
if (user!=null){
//返回,該用戶)(username)已被註冊過
return new ReslutTypeDto(VisitorStatusEmun.Account_Registered);
}
//數據庫插入數據
Integer integer = userServiceImpl.addUser(username, password);
//是否插入數據成功
if (integer==null||!integer.equals(1)){
//返回註冊失敗
return new ReslutTypeDto(VisitorStatusEmun.Register_Fail);
}
//返回註冊成功
return new ReslutTypeDto(VisitorStatusEmun.Register_OK);
}
6.效果展示
7.思想總結
驗證碼運用在項目中的還是挺簡單的(需要全套源碼評論區留郵箱哦),主要掌握核心思想,就是驗證碼的存放,移除。我這採用的session存放,當然大家也可已採用其他方式。以上就是發送郵箱驗證碼全過程了,如有紕漏還請多多指教~