springboot注冊功能中郵箱驗證的實現


我們放假啦,前幾天瘋狂復習,現在又可以再次投入到代碼中啦,這是我的第一篇博客園博客耶嘻嘻,希望大家喜歡!(本人也只是個大二的小白一枚,一同進步和成長叭

廢話不多說,我們要實現的功能是:注冊時對用戶輸入的郵箱進行驗證,包括 ①郵箱存不存在和 ②郵箱是否是用戶的郵箱 兩個驗證

 

我們分為前端和后端來實現:

 

前期准備

 

1. pom.xml文件中引入相關的依賴(發送郵箱用的依賴):

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

 

 

2. 引入相關js和css文件:

① 郵箱驗證要使用到的jquery.cookie.js:(作用后面會講哈)

下載地址:http://plugins.jquery.com/cookie/

下載完后放到相應的文件夾里,譬如我是這樣放的:

 

 

② me.css文件(不引入也可以喲,這只是讓頁面顯示在中間,並不影響功能)

1 .m-container-small {
2     max-width: 60em !important;
3     margin: auto !important;
4 }
5 .m-padded-tb-massive {
6     padding-top: 5em !important;
7     padding-bottom: 5em !important;
8 }

 

 基本的前端(繼續完善的前端在下一篇,敬請期待)

 

1. html代碼:(注意要修改一下js文件的相對路徑,改成你自己的【第76行】)

(引入了css的小伙伴同時要改一下me.css的相對路徑哈【第9行】)

 1 <!DOCTYPE html>
 2 <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport" content="width=device-width,initial-scale=1.0">
 6     <title>博客游客注冊</title>
 7 8     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
 9     <link rel="stylesheet" href="../../static/css/me.css">
10 </head>
11 <body>
12 <br><br><br>
13 <div class="m-container-small m-padded-tb-massive" style="max-width: 30em !important;">
14     <div class="ui container">
15         <div class="ui middle aligned center aligned grid">
16 
17             <div class="column">
18                 <div class="ui negative message" th:unless="${#strings.isEmpty(message)}">
19                     <i class="close icon"></i>
20                     <div class="header">
21                         校驗失敗
22                     </div>
23                     <p th:text="${message}"></p>
24                 </div>
25                 <h2 class="ui teal image header">
26                     <div class="content">
27                         游客注冊
28                     </div>
29                 </h2>
30                 <form class="ui large form" method="post" action="#" th:action="@{/tourist/register}">
31                     <div class="ui segment">
32                         <div class="field">
33                             <div class="ui left icon input">
34                                 <i class="user icon"></i>
35                                 <input type="text" id="username" name="username" placeholder="用戶名"
36                                        onchange="isUsernameUnique(this)">
37                             </div>
38                         </div>
39                         <div class="field">
40                             <div class="ui left icon input">
41                                 <i class="lock icon"></i>
42                                 <input type="password" name="password" placeholder="密碼">
43                             </div>
44                         </div>
45                         <div class="field">
46                             <div class="ui left icon input">
47                                 <i class="mail icon"></i>
48                                 <input type="text" name="email" id="email" placeholder="郵箱">
49                                 <input type="button" id="getcode" class="ui grey label" value="獲取驗證碼">
50                             </div>
51 
52                         </div>
53                         <div class="code field"  style="display:none" >
54                             <div class="ui left icon input">
55                                 <i class="check square outline icon"></i>
56                                 <input type="text" name="identify" id="identify" placeholder="驗證碼">
57                             </div>
58                         </div>
59                         <button class="ui fluid large teal submit button" id="register-btn">注 冊</button>
60                     </div>
61                     <div id="isRepeat"></div>
62                     <div class="ui error mini message"></div>
63 
64                 </form>
65 
66 
67             </div>
68 
69         </div>
70 
71     </div>
72 </div>
73 
74 
75 <script src="https://code.jquery.com/jquery-3.1.1.min.js" crossorigin="anonymous"></script>
76 <script type="text/javascript" src="../../static/js/jquery.cookie.js" ></script>
77 <script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.js"></script>
78 </body>
79 </html>

 

 

2. 界面展示

 

現在我們已經擁有一個靜態頁面啦,接下來的工作是讓它動起來

1. 在用戶點擊“獲取驗證碼”的時候,判斷郵箱位置是否為空,若為空,則不作任何操作

代碼如下:

1   $('#getcode').click(function(){
2 
3             //判斷郵箱位置是否為空
4             var email = $("#email").val();
5             if(email==""){
6                 return;
7             }
8 
9         });

 

2. 不為空的時候我們就要把用戶的郵箱發給后端,讓后端進行郵箱的存在性檢查以及發送

這時候要用到的技術是ajax:

  $.ajax({
                //url路徑
                url: "http://localhost:8080/tourist/sendEmail",
                //data請求數據
                data: {"email": email},
                //dataType json
                type: "post",
                //回調函數
                success: function (data) {
                    //回調函數 data 返回流
                    if (data == "failure") {
                        alert("發送失敗");
                    }
                    else if (data=="false"){
                        alert("目標郵箱不存在,請檢查你的郵箱是否正確");
                    }
                  //  else{

                   // }
                }
            });

 

合並上面兩個代碼,結果如下:

$('#getcode').click(function(){

            //發送驗證碼
            var email = $("#email").val();
            if(email==""){
                return;
            }
            alert("驗證碼已發送,請及時查看你的郵箱");
            $(".code").toggle();
            //ajax實現后台郵箱的發送
            $.ajax({
                //url路徑
                url: "http://localhost:8080/tourist/sendEmail",
                //data請求數據
                data: {"email": email},
                //dataType json
                type: "post",
                //回調函數
                success: function (data) {
                    //回調函數 data 返回流
                    if (data == "failure") {
                        alert("發送失敗");
                    }
                    else if (data=="false"){
                        alert("目標郵箱不存在,請檢查你的郵箱是否正確");
                    }
                  //  else{

                   // }
                }
            });


        });

 

最基本的前端已經完成啦,我們現在來看后端:

 

 后端的實現

 

1. controller的命名與位置:

①名字你可以隨便起,我起的是RegisterController

②位置我是新建了一個web文件夾,然后在web文件夾下新建了一個子文件夾tourist,在這個文件夾中放着我的控制器

(由於這是我博客系統的一部分功能,所以里面有很多很多代碼,我碼掉了,如果大家喜歡我的文章,我就會繼續分享一些實用的有關博客的功能唷)

 

2. html代碼:

(我命名為register.html,並且放在了templates文件里的子文件tourist下

 

//import com.lrm.util.MD5Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.MailSendException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

@Controller
@RequestMapping("/tourist")
public class RegisterController {

    @Autowired
    private UserService userService;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${mail.fromMail.sender}")
    private String sender;// 發送者

    @Autowired
    private JavaMailSender javaMailSender;

    private Map<String, Object> resultMap = new HashMap<>();

    @GetMapping("/register")
    public String register() {
        return "tourist/register";
    }



    @RequestMapping("/sendEmail")
    //轉換json數據  @ResponseBody
    @ResponseBody
    public String sendEmail(String email) {
        SimpleMailMessage message = new SimpleMailMessage();
        String code = VerifyCode(6);    //隨機數生成6位驗證碼
        message.setFrom(sender);
        message.setTo(email);
        message.setSubject("博客系統");// 標題
        message.setText("【博客系統】你的驗證碼為:"+code+",有效時間為5分鍾(若不是本人操作,可忽略該條郵件)");// 內容
        try {
            javaMailSender.send(message);
            logger.info("文本郵件發送成功!");
            saveCode(code);
            return "success";
        }catch (MailSendException e){
            logger.error("目標郵箱不存在");
            return "false";
        } catch (Exception e) {
            logger.error("文本郵件發送異常!", e);
            return "failure";
        }
    }

    private String VerifyCode(int n){
        Random r = new Random();
        StringBuffer sb =new StringBuffer();
        for(int i = 0;i < n;i ++){
            int ran1 = r.nextInt(10);
            sb.append(String.valueOf(ran1));
        }
//        System.out.println(sb);
        return sb.toString();
    }

    //保存驗證碼和時間
    private void saveCode(String code){
        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MINUTE, 5);
        String currentTime = sf.format(c.getTime());// 生成5分鍾后時間,用戶校驗是否過期

        String hash =  MD5Utils.code(code);//生成MD5值
        resultMap.put("hash", hash);
        resultMap.put("tamp", currentTime);
    }
}

 

 

 

 

 思路:先隨機生成一串驗證碼,然后通過郵箱發送給用戶輸入的郵箱號,通過捕獲異常來判斷用戶輸入的郵箱是否存在

 

用到的小技術:里面用到了MD5加密,即生成驗證碼時,將驗證碼和發送時間通過加密技術進行加密,然后保存到Map對象中(用於后面與用戶輸入的驗證碼及時間相比對,來判斷用戶驗證碼輸入是否正確,以及驗證碼是否過期)

所以這里我們還需要引入一下MD5加密工具(或者你可以使用springboot自帶的加密功能,具體的可自行查閱)

 

MD5Utils的代碼如下:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Utils {

    /**
     * MD5加密類
     *
     * @param str 要加密的字符串
     * @return 加密后的字符串
     */
    public static String code(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            byte[] byteDigest = md.digest();
            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < byteDigest.length; offset++) {
                i = byteDigest[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            //32位加密
            return buf.toString();
            // 16位的加密
            //return buf.toString().substring(8, 24);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }

    }


    public static void main(String[] args) {
        System.out.println(code("123"));
    }
}

 

(這個引入之后就可以在上面的controller報錯的地方引入相應的包啦(*^▽^*)【報錯的地方就是因為這個包沒引入】)

 

這樣發送驗證碼的前后端我們基本都寫好啦,是不是躍躍欲試呢,哈哈

放心,你馬上就可以開始運行了,我們還差最后一個工作,就是配置我們的application.properties

##根據自己的情況填寫
##郵箱服務器地址
##QQ smtp.qq.com
##sina smtp.sina.cn
##aliyun smtp.aliyun.com
##163 smtp.163.com
spring.mail.host=smtp.qq.com
##郵箱用戶名
spring.mail.username=362517658@qq.com
##郵箱密碼(注意:QQ郵箱應該使用授權碼)
spring.mail.password=********
##編碼格式
spring.mail.default-encoding=UTF-8

##發送郵件地址
mail.fromMail.sender=362517658@qq.com
##接收郵件地址
mail.fromMail.receiver=362517658@qq.com

 

 

注意!!里面的郵箱密碼,不是你的qq密碼,而是郵箱里的授權碼,不明白的可看下獲取授權碼步驟:

 

① 點擊設置

 

② 選擇“賬戶”

 

③ 下拉到圖中所示位置,選擇前兩個任意一個打開就行(我這里已經打開,沒有打開的小伙伴上面會有“打開”按鈕的選擇),根據它的指引最后可以獲得一串16位的授權碼,這個授權碼就是我們要的

 

 

噠啦啦啦,回到正題:現在讓我們來測試一下吧!

①點擊“獲取驗證碼”,跳出驗證碼框

 

② 輸入一個不存在的郵箱號

(這里的“59秒后可重新獲取”是我們后面要實現的功能,大家這里顯示的還是“獲取驗證碼”哈)

 

③ 填寫正確的郵箱地址

成功收到郵箱啦嘻嘻

 

發送郵箱驗證碼我們已經成功實現,現在我們要驗證一下用戶輸入的驗證碼是否和我們發送的一樣(你就快要完成啦,堅持就是勝利!!!!)

 

這里是點擊“注冊”時,我們進行郵箱驗證碼的判斷

 

前端我們是已經加過表單的跳轉位置了,

 

所以我們現在就來做相應的后端:

 

直接上后端代碼:(加在controller(我們的后端代碼)里)

 @PostMapping("/register")
    public String login(@RequestParam String username, @RequestParam String password, @RequestParam String email,
                        @RequestParam String identify,RedirectAttributes attributes, User user) {
        if (resultMap.size() ==0){
            return "tourist/register";
        }
        //判斷驗證碼是否正確
        String requestHash = resultMap.get("hash").toString();

        String tamp = resultMap.get("tamp").toString();
        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");//當前時間
        Calendar c = Calendar.getInstance();
        String currentTime = sf.format(c.getTime());
        if (tamp.compareTo(currentTime) > 0) {
            String hash =  MD5Utils.code(identify);//生成MD5值
            if (hash.equalsIgnoreCase(requestHash)){
                //校驗成功
                attributes.addFlashAttribute("m", "恭喜!現在,你可以登錄你的用戶名。");
                return "redirect:/tourist";
            }else {
                //驗證碼不正確,校驗失敗
                System.out.println("2");
                attributes.addFlashAttribute("message", "驗證碼輸入不正確");
                return "redirect:/tourist/register";
            }
        } else {
            // 超時
            System.out.println("3");
            attributes.addFlashAttribute("message", "驗證碼已過期");
            return "redirect:/tourist/register";
        }

    }

 

 

思路:判斷此時時間與上次存的驗證碼的生成時間之差是否大於五分鍾,若大於,則提示超時;若沒有大於,再將用戶輸入的驗證碼進行加密,接着判斷用戶輸入的驗證碼與最先保存的驗證碼是否一致(這里也可以通過驗證碼的解密,然后將解密后的驗證碼和用戶輸入的直接比對)

 

為了更方便地看出結果,我們再加個login界面,位置和register.html一樣

 

html代碼:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head >
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>博客用戶登錄</title>
   
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css">
   
</head>
<body>
<br><br><br>

<div class="m-container-small m-padded-tb-massive" style="max-width: 30em !important;">
    <div class="ui success message" th:unless="${#strings.isEmpty(m)}">
        <i class="close icon"></i>
        <div class="header">
            你注冊成功!
        </div>
        <p th:text="${m}">現在,你可以登錄你的用戶名。</p>
    </div>
    <div class="ui container">
        <div class="ui middle aligned center aligned grid">
            <div class="column">
                <h2 class="ui teal image header">
                    <div class="content">
                        用戶登錄
                    </div>
                </h2>

            </div>
        </div>

    </div>
</div>

<script src="https://code.jquery.com/jquery-3.1.1.min.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.js"></script>


    //消息提示關閉初始化
    $('.message .close')
        .on('click', function () {
            $(this)
                .closest('.message')
                .transition('fade');
        });
</script>
</body>
</html>

 

 

現在又到了激動人心的測試環節,大家開始躁起來吧!

(具體演示忽略)

 

 

完善功能:用戶60秒才能重新發送郵箱,這樣可以避免某些壞心眼的孩子一直不斷地發送郵箱(哈哈雖然目的不只是這個),當然每次測試的時候我們也多了個60秒的等待時間

(欲知后事如何,請聽下回分解)

☞ 下篇文章:springboot中郵箱驗證按鈕實現60秒后可重新獲取(防止刷新)以及防重復發送

或者用你們的贊和鼓勵來加快我寫文章的步伐叭

 

參考:Spring Boot發送郵件詳解 https://www.iteye.com/blog/xieke90-2428892

 

轉載請注明出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM