首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET MVC 實作驗證碼功能完整範例

     編輯:ASP.NET 基礎

驗證碼是防止機器人惡意提交的基本防線。本文示範 MVC 控制器產生驗證碼圖片、Session 儲存驗證碼、前端顯示與更換、以及驗證邏輯。

驗證碼核心類別

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;

namespace Utility
{
    public class ValidateCode
    {
        /// <summary>產生隨機碼</summary>
        public static string CreateRandomCode(int length)
        {
            const string chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; // 排除易混淆字元
            var random = new Random();
            var code = new char[length];
            for (int i = 0; i < length; i++)
                code[i] = chars[random.Next(chars.Length)];
            return new string(code);
        }

        /// <summary>建立驗證碼圖片並直接輸出至 Response</summary>
        public static void CreateImage(string code)
        {
            int width = code.Length * 22;
            using (var bitmap = new Bitmap(width, 30))
            using (var g = Graphics.FromImage(bitmap))
            {
                g.Clear(Color.AliceBlue);
                g.DrawRectangle(Pens.Black, 0, 0, width - 1, 29);

                // 背景雜訊
                var rand = new Random();
                for (int i = 0; i < 30; i++)
                {
                    g.DrawRectangle(Pens.LightGray, rand.Next(width), rand.Next(30), 1, 1);
                }

                // 字體與顏色陣列
                string[] fonts = { "Arial", "Verdana", "Tahoma" };
                Color[] colors = { Color.Black, Color.DarkBlue, Color.DarkGreen, Color.Maroon };

                // 逐字繪製,隨機旋轉、字體、顏色
                for (int i = 0; i < code.Length; i++)
                {
                    var font = new Font(fonts[rand.Next(fonts.Length)], 16, FontStyle.Bold);
                    var brush = new SolidBrush(colors[rand.Next(colors.Length)]);
                    float angle = rand.Next(-30, 30);

                    g.TranslateTransform(16 + i * 20, 15);
                    g.RotateTransform(angle);
                    g.DrawString(code[i].ToString(), font, brush, 0, 0, StringFormat.GenericTypographic);
                    g.RotateTransform(-angle);
                    g.TranslateTransform(-(16 + i * 20), -15);
                }

                // 輸出 GIF
                HttpContext.Current.Response.ClearContent();
                HttpContext.Current.Response.ContentType = "image/gif";
                using (var ms = new MemoryStream())
                {
                    bitmap.Save(ms, ImageFormat.Gif);
                    HttpContext.Current.Response.BinaryWrite(ms.ToArray());
                }
            }
        }
    }
}

控制器

public class CommonController : Controller
{
    [OutputCache(Duration = 0, NoStore = true)] // 禁止快取
    public ActionResult VCode()
    {
        string code = ValidateCode.CreateRandomCode(4);
        Session["VCode"] = code; // 儲存至 Session
        ValidateCode.CreateImage(code); // 直接輸出圖片
        return new EmptyResult(); // 已在 CreateImage 中寫入 Response
    }

    public JsonResult ValidateCode(string inputCode)
    {
        string sessionCode = Session["VCode"] as string;
        bool valid = !string.IsNullOrEmpty(sessionCode) 
                     && string.Equals(sessionCode, inputCode, StringComparison.OrdinalIgnoreCase);
        return Json(new { success = valid }, JsonRequestBehavior.AllowGet);
    }
}

前端頁面

<img id="vcodeImg" src="/Common/VCode" width="80" height="30" style="vertical-align:middle; cursor:pointer;" title="點擊更換" />
<a href="javascript:;" id="refreshVCode">換一張</a>
<input type="text" id="txtVCode" name="vcode" maxlength="4" />

<script>
    // 點擊圖片或連結更換
    $("#vcodeImg, #refreshVCode").click(function () {
        $("#vcodeImg").attr("src", "/Common/VCode?" + new Date().getTime()); // 加時間戳防快取
    });

    // 表單提交前驗證 (AJAX 範例)
    $("#btnSubmit").click(function () {
        var code = $("#txtVCode").val();
        $.getJSON("/Common/ValidateCode", { inputCode: code }, function (resp) {
            if (resp.success) {
                // 通過,提交表單
                $("form").submit();
            } else {
                alert("驗證碼錯誤");
                $("#vcodeImg").click(); // 自動換碼
            }
        });
    });
</script>

關鍵點與安全建議

  • Session 儲存:單機部署直接用 InProc Session;Web Farm 需使用 StateServer、SQLServer 或 Redis Session Provider。
  • 防快取:[OutputCache(Duration=0, NoStore=true)] + 前端加時間戳查詢字串。
  • 字元集:排除 0/O、1/I/l、8/B 等易混淆字元。
  • 無障礙:提供語音驗證碼選項或 honeypot 隱藏欄位作為替代。
  • 現代替代:考慮 Google reCAPTCHA v3 (無感知)、hCaptcha、Turnstile,安全性更高且使用者體驗更好。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved