Java項目中發送郵箱驗證碼及有效時長(超詳細)

    最近做一個社區項目,發現很多地方都需要校驗是否爲用戶本人,然後做了個郵箱驗證分享給大家,當然也可以採用手機驗證碼。思想和郵箱驗證碼是類似的,只需要稍作修改。廢話不多說直接上代碼。

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;\">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style=\"font-size:14px;\">&nbsp; <span style=\"font-size:16px;\">&nbsp;&nbsp;您好!您正在進行郵箱驗證,本次請求的驗證碼爲:<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:&quot;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:&quot;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存放,當然大家也可已採用其他方式。以上就是發送郵箱驗證碼全過程了,如有紕漏還請多多指教~

發佈了9 篇原創文章 · 獲贊 7 · 訪問量 4819
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章