驗證碼插件 vercode.js

来源:https://www.cnblogs.com/licin/archive/2023/07/22/17573137.html
-Advertisement-
Play Games

第1代圖片驗證碼 - 字母數字型 第2代滑動驗證碼 - 圖片截取型 第3代驗證碼 - 選圖型 vercode.js 結合了上面的情況下新研發的一種驗證碼。 驗證碼類型 驗證碼描述 操作性 安全性 描述 字母數字型圖片驗證碼 這是一種通過後臺隨機碼生成圖片的驗證碼。伺服器會在隨機碼生成時保存隨機碼。 ...


第1代圖片驗證碼 - 字母數字型

 

第2代滑動驗證碼 - 圖片截取型

第3代驗證碼 - 選圖型

 vercode.js 結合了上面的情況下新研發的一種驗證碼。

驗證碼類型 驗證碼描述 操作性 安全性 描述
字母數字型圖片驗證碼

這是一種通過後臺隨機碼生成圖片的驗證碼。伺服器會在隨機碼生成時保存隨機碼。

當進行登錄驗證時,會根據輸入的驗證碼與伺服器保存的驗證碼進行匹配。

★★★ ★★★★

需要輸入

客戶端與服務端聯合驗證,安全性高

滑動驗證碼

這是一種客戶端驗證的驗證碼,相對來說安全性不高,因為隨機碼是客戶端生成的,

驗證也是客戶端完成的,客戶端完成之後再執行的伺服器賬號密碼驗證,對於存在

攻擊性的情況下來說,獲取到伺服器驗證介面後,是完全可以跳過客戶端驗證直接

訪問服務端介面進行賬號和密碼驗證的。

★★★★★ ★★★

只需要滑動

僅客戶端驗證,安全性低

選圖型驗證碼

這是一種通過服務端圖片與字元匹配的關係生成的一種拼圖提供給客戶端,客戶端

點擊拼圖後,會保存拼圖背後的字元,從而拿客戶端的字元與服務端圖片對應字元

進行匹配

★★★ ★★★★★

需要人眼識別和選擇

客戶端與服務端聯合驗證,安全性高

vercode驗證碼

這種是結合了第一種驗證碼,它也是通過服務端賬號生成隨機字元,並保留隨機字元,

如果賬號不匹配的話,是沒辦法獲取到驗證碼的,然後生成字元圖片給客戶端,客戶端

生成鍵盤,用戶通過選擇鍵盤字元。然後在登錄時將賬號密碼以及選擇的字元一併提供

給服務端驗證。

★★★★ ★★★★

直接選擇

客戶端與服務端聯合驗證,安全性高

 

 

 

 

 

 

 

 

 

 

 

 

 

 

vercode.js

var vercode = new Object();
vercode.apiPath = "";
vercode.userId = "";
vercode.generateVerifyImage = function () {
    try {
        var url = vercode.apiPath;
        var userId = $(vercode.userId).val();
        $.ajax({
            url: url,
            type: 'post',
            data: { userId: userId },
            dataType: 'json',
            async: false,
            success: function (res) {
                if (res.code == 0) {
                    document.getElementById('verImage').src = "data:image/jepg;base64," + res.data;
                }
            },
            error: function () {
                console.log('Error occurred while opening the image file.');
            }
        });
    } catch (e) {

    } finally {
        document.getElementById('verset').style.display = 'block';
        document.getElementById('verset').style.top = ($('#vercode').offset().top + $('#vercode').height())+"px";
        document.getElementById('verset').style.left = ($('#vercode').offset().left)+"px";
        document.getElementById('code').innerText = '';
    }
}
vercode.appendVer = function (v) {
    var codeLength = 4;//   驗證碼長度
    if (document.getElementById('code').innerText.length == codeLength) {
        document.getElementById('verset').style.display = 'none';
        return;
    }
    document.getElementById('code').innerText += v.innerText;
};
vercode.Init = function (apiPath, userId) {
    let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    //arr.sort(() => Math.random() - 0.5);    //  如果希望鍵盤順序顯示,註釋改行
    arr.splice(9, 0, 99);
    arr.push(99);

    var template = "";
    for (var i = 0; i < 12; i++) {
        if (i == 9 ) {
            template += '<li onclick="vercode.generateVerifyImage()">重置</li>';
        }
        else if (i == 11) {
            template += '<li onclick="document.getElementById(\'verset\').style.display = \'none\'">確認</li>';
        }
        else {
            template += '<li onclick="vercode.appendVer(this)">' + arr[i] + '</li>';
        }
    }
    $(".verset ul").html(template);
    $("#verImage").click(function () {
        vercode.generateVerifyImage();
    })
    $("#verImage").attr("title", "點擊後刷新驗證碼");
    vercode.apiPath = apiPath;
    vercode.userId = userId;
};

 

vercode.css

.vercode {
    width: 330px;
    margin:10px 0px;
}

    .vercode .code {
        display: inline-block;
        width: 45%;
        margin-right: 5px;
        font-family: 'Arial Unicode MS';
        font: 20px/38px bold;
        line-height: 38px;
        height: 38px;
        text-align: center;
        float: left;
        border-radius: 5px;
        background-color: #f8f4f4;
        text-shadow: 2px 2px 2px #52c574;
    }

            .vercode .verimg {
                display: inline-block;
                width: 45%;
                margin-left: 5px;
                line-height: 38px;
                height: 38px;
                text-align: center;
                cursor: pointer;
            }

                .vercode .verimg img {
                    display: inline-block;
                    width: 100%;
                    height: 38px;
                    vertical-align: middle;
                    line-height: 38px;
                    text-align: center;
                    cursor: pointer;
                }

.verset {
    width: 330px;
    padding: 0px;
    text-align: left;
    height: 100px;
    display: none;
    margin: 10px;
    height: 120px;
    position: fixed;
    top: 0px;
    left: 0px;
    z-index: 9999;
}

        .verset ul {
            width: 76%;
            height: 126px;
            line-height: 28px;
            margin: 0px;
            clear: both;
            padding: 5px 0px;
            padding-left: 5px;
        }

            .verset ul li {
                float: left;
                list-style: none;
                width: 31%;
                background-color: #fff; /*  修改按鈕背景色   */
                text-align: center;
                border: 1px solid #666;
                color: #666; /*  修改按鈕字體色   */
                border-radius: 5px;
                cursor: pointer;
                margin:1px;
            }

  login.html 登錄示例

<li>
                    <em></em>
                    <input type="text" id="userId" tabindex="1" placeholder="請輸入用戶名" class="longcode" />
                    <label id="imgUid" class="error_msg"></label>
                </li>
                <li>
                    <em class="code"></em>
                    <input type="password" id="pwd" placeholder="請輸入密碼" class="longcode on" tabindex="2" />
                    <label id="imgPwd" class="error_msg"></label>
                </li>


                <li>
                    <div class="vercode" id="vercode">
                        <div class="code" id="code"></div>
                        <div class="verimg">
                            <img src="" id="verImage" />
                        </div>
                    </div>

                </li>
...

 <div class="verset" id="verset">
            <ul></ul>
        </div>

  login.html 登錄訪問伺服器javascript方法

<script>
        function syslogin() {
            $.post('/Login/Verify', { userId: $("#userId").val(), pwd: $("#pwd").val(), clientCode: $("#code").text() }, function (res) {
                if (res.code != 0) {
                    document.getElementById('lblMessage').innerText = res.msg;
                    document.getElementById('lblMessage').style.color = "red";
                }
                else {
                    document.getElementById('lblMessage').innerText = res.msg;
                    document.getElementById('lblMessage').style.color = "green";
                    //setTimeout(function () {
                    //    location.href = '/Basic/IcsonFrame_DBC_Table.aspx';
                    //},1000)
                }
            });
        }
       
    </script>

  login.html 初始化javascript方法

vercode.Init方法第一個參數是請求服務端驗證碼圖片的介面地址,第二個參數是登錄該賬號的用戶名元素
<script>
        $(function () {
            vercode.Init('/Login/GenerateVerifyImage', "#userId");
        })
    </script>

  服務端驗證代碼C#

public class LoginController : Controller
    {
        private VryImgGen vryImgGen = new VryImgGen();
        // GET: Home
        public ActionResult Index()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Verify(string userId,string pwd,string clientCode)
        {
            if(clientCode != Session[userId].TryString(""))
            {
                return Json(new { code = -1, msg = "驗證碼錯誤!" });
            }

            return Json(new { code = 0, msg = "驗證成功" });
        }
        [HttpPost]
        public ActionResult GenerateVerifyImage(string userId)
        {
// 校驗用戶賬號是否有效,無效則返回空的圖片 var verifyCode = new Random().Next(1000, 9999).ToString(); var bmp = vryImgGen.CreateImageCode(verifyCode); Session[userId] = verifyCode; MemoryStream ms = new MemoryStream(); bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); byte[] arr = new byte[ms.Length]; ms.Position = 0; ms.Read(arr, 0, (int)ms.Length); ms.Close(); return Json(new { code = 0, data = Convert.ToBase64String(arr),msg="獲取驗證碼成功" }); } }

  生成驗證碼圖片的代碼C#

using System;
using System.Collections.Generic;
using System.Web;
using System.Drawing;
...

/// <summary>
    /// 圖片驗證碼
    /// </summary>
    public class VryImgGen
    {
        #region 生成校驗碼圖片
        /// <summary>
        /// 生成校驗碼圖片
        /// 校驗碼保存在Session["ImgGen"]中
        /// </summary>
        /// <returns>Bitmap</returns>
        public Bitmap CreateImageCode()
        {
            string code = CreateVerifyCode(Length);
            HttpContext.Current.Session["ImgGen"] = code.ToUpper();
            int fSize = FontSize;
            int fWidth = fSize + Padding;
            int imageWidth = (int)(code.Length * fWidth) + 4 + Padding * 2;
            int imageHeight = fSize * 2 + Padding;

            System.Drawing.Bitmap image = new System.Drawing.Bitmap(imageWidth, imageHeight);
            Graphics g = Graphics.FromImage(image);
            g.Clear(BackgroundColor);
            Random rand = new Random();

            //給背景添加隨機生成的燥點
            if (this.Chaos)
            {
                Pen pen = new Pen(ChaosColor, 0);
                int c = Length * 100;

                for (int i = 0; i < c; i++)
                {
                    int x = rand.Next(image.Width);
                    int y = rand.Next(image.Height);

                    g.DrawRectangle(pen, x, y, 1, 1);
                }
            }

            int left = 0, top = 0, top1 = 1, top2 = 1;

            int n1 = (imageHeight - FontSize - Padding * 2);
            int n2 = n1 / 4;
            top1 = n2;
            top2 = n2 * 2;

            Font f;
            Brush b;
            int cindex, findex;

            //隨機字體和顏色的驗證碼字元
            for (int i = 0; i < code.Length; i++)
            {
                cindex = rand.Next(Colors.Length - 1);
                findex = rand.Next(Fonts.Length - 1);

                f = new System.Drawing.Font(Fonts[findex], fSize, System.Drawing.FontStyle.Bold);
                b = new System.Drawing.SolidBrush(Colors[cindex]);

                if (i % 2 == 1)
                {
                    top = top2;
                }
                else
                {
                    top = top1;
                }

                left = i * fWidth;

                g.DrawString(code.Substring(i, 1), f, b, left, top);
            }

            //畫一個邊框 邊框顏色為Color.Gainsboro
            g.DrawRectangle(new Pen(Color.Gainsboro, 0), 0, 0, image.Width - 1, image.Height - 1);
            g.Dispose();

            //產生波形
            image = TwistImage(image, false, 0, 0);

            return image;
        }

        public Bitmap CreateImageCode(string code)
        {
            int fSize = FontSize;
            int fWidth = fSize + Padding;

            int imageWidth = (int)(code.Length * fWidth) + 4 + Padding * 2;
            int imageHeight = fSize * 2 + Padding;

            System.Drawing.Bitmap image = new System.Drawing.Bitmap(imageWidth, imageHeight);

            Graphics g = Graphics.FromImage(image);

            g.Clear(BackgroundColor);

            Random rand = new Random();

            //給背景添加隨機生成的燥點  
            if (this.Chaos)
            {

                Pen pen = new Pen(ChaosColor, 0);
                int c = Length * 10;

                for (int i = 0; i < c; i++)
                {
                    int x = rand.Next(image.Width);
                    int y = rand.Next(image.Height);

                    g.DrawRectangle(pen, x, y, 1, 1);
                }
            }

            int left = 0, top = 0, top1 = 1, top2 = 1;

            int n1 = (imageHeight - FontSize - Padding * 2);
            int n2 = n1 / 4;
            top1 = n2;
            top2 = n2 * 2;

            Font f;
            Brush b;

            int cindex, findex;

            //隨機字體和顏色的驗證碼字元  
            for (int i = 0; i < code.Length; i++)
            {
                cindex = rand.Next(Colors.Length - 1);
                findex = rand.Next(Fonts.Length - 1);

                f = new System.Drawing.Font(Fonts[findex], fSize, System.Drawing.FontStyle.Bold);
                b = new System.Drawing.SolidBrush(Colors[cindex]);

                if (i % 2 == 1)
                {
                    top = top2;
                }
                else
                {
                    top = top1;
                }

                left = i * fWidth;

                g.DrawString(code.Substring(i, 1), f, b, left, top);
            }

            //畫一個邊框 邊框顏色為Color.Gainsboro  
            g.DrawRectangle(new Pen(Color.Gainsboro, 0), 0, 0, image.Width - 1, image.Height - 1);
            g.Dispose();

            //產生波形(Add By 51aspx.com)  
            image = TwistImage(image, true, 3, 2);

            return image;
        }

        #endregion

        #region 屬性

        #region 驗證碼長度
        int length = 4;
        public int Length
        {
            get { return length; }
            set { length = value; }
        }
        #endregion

        #region 驗證碼字體大小(為了顯示扭曲效果,預設40像素,可以自行修改)
        int fontSize = 26;
        public int FontSize
        {
            get { return fontSize; }
            set { fontSize = value; }
        }
        #endregion

        #region 邊框補(預設1像素)
        int padding = 2;
        public int Padding
        {
            get { return padding; }
            set { padding = value; }
        }
        #endregion

        #region 是否輸出燥點(預設不輸出)
        bool chaos = true;
        public bool Chaos
        {
            get { return chaos; }
            set { chaos = value; }
        }
        #endregion

        #region 輸出燥點的顏色(預設灰色)
        Color chaosColor = Color.LightGray;
        public Color ChaosColor
        {
            get { return chaosColor; }
            set { chaosColor = value; }
        }
        #endregion

        #region 自定義背景色(預設白色)
        Color backgroundColor = Color.White;
        public Color BackgroundColor
        {
            get { return backgroundColor; }
            set { backgroundColor = value; }
        }
        #endregion

        #region 自定義隨機顏色數組
        Color[] colors = { Color.Black, Color.Black, Color.Black, Color.Black, Color.Black, Color.Black, Color.Black, Color.Black };
        public Color[] Colors
        {
            get { return colors; }
            set { colors = value; }
        }
        #endregion

        #region 自定義字體數組
        string[] fonts = { "華文中宋", "華文中宋" };
        public string[] Fonts
        {
            get { return fonts; }
            set { fonts = value; }
        }
        #endregion

        #region 自定義隨機碼字元串序列(使用逗號分隔)
        string codeSerial = "2,3,4,5,6,7,8,9,a,b,c,d,e,f,g,h,j,k,m,n,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z";
        public string CodeSerial
        {
            get { return codeSerial; }
            set { codeSerial = value; }
        }
        #endregion
        #endregion

        #region 產生波形濾鏡效果

        private const double PI = 3.1415926535897932384626433832795;
        private const double PI2 = 6.283185307179586476925286766559;

        /// <summary>
        /// 正弦曲線Wave扭曲圖片(Edit By 51aspx.com)
        /// </summary>
        /// <param name="srcBmp">圖片路徑</param>
        /// <param name="bXDir">如果扭曲則選擇為True</param>
        /// <param name="nMultValue">波形的幅度倍數,越大扭曲的程度越高,一般為3</param>
        /// <param name="dPhase">波形的起始相位,取值區間[0-2*PI)</param>
        /// <returns></returns>
        public System.Drawing.Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
        {
            System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);

            // 將點陣圖背景填充為白色
            System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(destBmp);
            graph.FillRectangle(new SolidBrush(System.Drawing.Color.White), 0, 0, destBmp.Width, destBmp.Height);
            graph.Dispose();

            double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;

            for (int i = 0; i < destBmp.Width; i++)
            {
                for (int j = 0; j < destBmp.Height; j++)
                {
                    double dx = 0;
                    dx = bXDir ? (PI2 * (double)j) / dBaseAxisLen : (PI2 * (double)i) / dBaseAxisLen;
                    dx += dPhase;
                    double dy = Math.Sin(dx);

                    // 取得當前點的顏色
                    int nOldX = 0, nOldY = 0;
                    nOldX = bXDir ? i + (int)(dy * dMultValue) : i;
                    nOldY = bXDir ? j : j + (int)(dy * dMultValue);

                    System.Drawing.Color color = srcBmp.GetPixel(i, j);
                    if (nOldX >= 0 && nOldX < destBmp.Width
                     && nOldY >= 0 && nOldY < destBmp.Height)
                    {
                        destBmp.SetPixel(nOldX, nOldY, color);
                    }
                }
            }

            return destBmp;
        }



        #endregion

        #region 生成隨機字元碼
        public string CreateVerifyCode(int codeLen)
        {
            if (codeLen == 0)
            {
                codeLen = Length;
            }

            string[] arr = CodeSerial.Split(',');

            string code = "";

            int randValue = -1;

            Random rand = new Random(unchecked((int)DateTime.Now.Ticks));

            for (int i = 0; i < codeLen; i++)
            {
                randValue = rand.Next(0, arr.Length - 1);

                code += arr[randValue];
            }

            return code;
        }
        public string CreateVerifyCode()
        {
            return CreateVerifyCode(0);
        }
        #endregion
    }

  

  

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • **前言** 小編在油管學習.NET知識,刷到一個外國小哥在用一個類似Idea的IDE開發.NET。出於好奇,小編在某谷搜索Idea支持.NET嗎?結果當然不支持,Idea主要是開發Java的IDE。幸好搜索引擎有個圖片搜索功能,於是拿圖片搜索了這個IDE,原來它的名字叫Rider,是Idea同一家 ...
  • # Unity UGUI的VerticalLayoutGroup(垂直佈局)組件的介紹及使用 ## 1. 什麼是VerticalLayoutGroup組件? VerticalLayoutGroup是Unity UGUI中的一種佈局組件,用於在垂直方向上自動排列子對象。它可以根據子對象的大小和佈局設置 ...
  • ## 引言 彙總一下所有的 .NET IL 指令,以及它們的名稱、操作碼值、堆棧轉換行為和描述。 作為反編譯IL代碼時的查詢字典。 ## IL 指令集列表 以下內容來自[微軟官方文檔](https://learn.microsoft.com/en-us/dotnet/api/system.refle ...
  • ### 一、文件、目錄許可權和所有者 簡介:用戶對一個文件或目錄具有訪問許可權,這些訪問許可權決定了誰能訪問,以及如何範圍這些文件和目錄。通過設置許可權可以限制或允許以下三種用戶訪問: - 文件的用戶所有者(屬主) - 文件的組群所有者(用戶所在組的同組用戶) - 系統中的其他用戶 在linux系統中,每一 ...
  • > ## ESP32連接MQ Sensor實現氣味反應 > > > ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/1961512734a74deb9d455b59cb1ccdab.png#pic_center) > > > | [ESP32+MQTT+MySQL實 ...
  • > 在 MySQL 中,GROUP BY用於將具有指定列中相同值的行分組在一起。這是在處理大量數據時非常有用的功能,允許對數據進行分類和聚合。 # 基本使用 ## 語法 以下是GROUP BY子句的基本語法: """ SELECT col1, col2, ..., aggregate_functio ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 背景 最近聽音樂的時候,看到各種動效,突然好奇這些音頻數據是如何獲取並展示出來的,於是花了幾天功夫去研究相關的內容,這裡只是給大家一些代碼實例,具體要看懂、看明白,還是建議大家大家結合相關API文檔來閱讀這篇文章。 參考資料地址:Web ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...