[C#] 第一次自己作 Captcha(驗證碼) 就上手(3)

2013-03-14

 

上一篇 [C#] 第一次自己作 Captcha(驗證碼) 就上手(2)

實作出來 Captcha 圖片..

有朋友過來問我說要怎麼做,我就繼續把這系列寫完..

首先,我會將認證是否符合產生出來的字放在server 端檢查..

透過Postback 驗證

畫面:

2012-08-24_214620

中間我圖片是做成base64 避免生出大量檔案..

接下來都寫在註解裡:

private string CurrentCaptcha
{
    //存放在Session 中
    get { return Session["CAPTCHA"].ToString(); }
    set { Session["CAPTCHA"] = value; }
}
 
protected void Page_Load(object sender, EventArgs e)
{
    //如果只是postback 就不更新
    if (!IsPostBack)
    {
        //取一個新的GUID 然後取MD5 因為GUID只有到F 並取四碼
        CurrentCaptcha = FormsAuthentication.HashPasswordForStoringInConfigFile(Guid.NewGuid().ToString(), "MD5").Substring(0, 4);
        Helper helper = new Helper();
        var result = helper.GetCaptcha(CurrentCaptcha, "Verdana", Server.MapPath("bk.jpg"), 95, 65, 22, 2);
        Image1.Src = "data:image/" + GetImageFormat(result) + ";base64," + ImageToBase64(result);
    }
}
 
 
/// <summary>
/// 更新按下時 充新換Key
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnRefresh_Click(object sender, EventArgs e)
{
 
    ////取一個新的GUID 然後取MD5 因為GUID只有到F 並取四碼
    CurrentCaptcha = FormsAuthentication.HashPasswordForStoringInConfigFile(Guid.NewGuid().ToString(), "MD5").Substring(0, 4);
    Helper helper = new Helper();
    var result = helper.GetCaptcha(CurrentCaptcha, "Verdana", Server.MapPath("bk.jpg"), 95, 65, 22, 2);
    Image1.Src = "data:image/" + GetImageFormat(result) + ";base64," + ImageToBase64(result);
 
}
 
/// <summary>
/// 自動判斷圖片格式
/// </summary>
/// <param name="img"></param>
/// <returns></returns>
public static System.Drawing.Imaging.ImageFormat GetImageFormat(Image img)
{
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Jpeg))
        return System.Drawing.Imaging.ImageFormat.Jpeg;
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Bmp))
        return System.Drawing.Imaging.ImageFormat.Bmp;
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png))
        return System.Drawing.Imaging.ImageFormat.Png;
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Emf))
        return System.Drawing.Imaging.ImageFormat.Emf;
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Exif))
        return System.Drawing.Imaging.ImageFormat.Exif;
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Gif))
        return System.Drawing.Imaging.ImageFormat.Gif;
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Icon))
        return System.Drawing.Imaging.ImageFormat.Icon;
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.MemoryBmp))
        return System.Drawing.Imaging.ImageFormat.MemoryBmp;
    if (img.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Tiff))
        return System.Drawing.Imaging.ImageFormat.Tiff;
    return System.Drawing.Imaging.ImageFormat.Wmf;
}
 
 
/// <summary>
/// 將 Image 物件轉 Base64
/// Convert image to base64
/// </summary>
/// <param name="image"></param>
/// <returns></returns>
public string ImageToBase64(Bitmap image)
{
 
    MemoryStream ms = new MemoryStream();
 
 
    // 將圖片轉成 byte[]
    // Comvert image to byte[]
    image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
    byte[] imageBytes = ms.ToArray();
 
    // 將 byte[] 轉 base64
    // byte to base64
    string base64String = Convert.ToBase64String(imageBytes);
    return base64String;
 
}
 
/// <summary>
/// 按下確認後認證
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void btnCheck_Click(object sender, EventArgs e)
{
    //印出來是否正確
    lblResult.Text = (CurrentCaptcha.ToUpper() == txtCaptcha.Text.Trim().ToUpper()).ToString() + CurrentCaptcha;
}


 



透過 AJAX



首先,我會先建立一個 Captcha的 .aspx 或是 .ashx 專門產圖



實作方式可以參考 : [ASP.net] 用Response作Image 輸出,並可控制權限



CaptchaCreator.aspx:





using System;
using System.Drawing.Imaging;
using System.IO;
using System.Web.Security;
using RippleCaptcha;
 
namespace TestRippleCaptcha
{
    public partial class CaptchaCreator : System.Web.UI.Page
    {
        private string CurrentCaptcha
        {
            get { return Session["CAPTCHA"].ToString(); }
            set { Session["CAPTCHA"] = value; }
        }
 
 
        protected void Page_Load(object sender, EventArgs e)
        {
 
            
            
            CurrentCaptcha = FormsAuthentication.HashPasswordForStoringInConfigFile(Guid.NewGuid().ToString(), "MD5").Substring(0, 4);
            Helper helper=new Helper();
 
            var result = helper.GetCaptcha(CurrentCaptcha, "Verdana", Server.MapPath("bk.jpg"), 95, 65, 22, 7);
 
            //設定 ContentType 為 jpg圖片
            // Set the ContentType to jpg picture.
            Response.ContentType = "image/jpeg";
            //注意這邊要用writefile 其中帶入圖片路徑
            byte[] data = null;
 
            using (MemoryStream oMemoryStream = new MemoryStream())
            {
 
                //儲存圖片到 MemoryStream 物件,並且指定儲存影像之格式
                //Save image to MemoryStream  and set it to jpeg format.
                result.Save(oMemoryStream, ImageFormat.Jpeg);
                //設定資料流位置
                //Set stream position start from zero
                oMemoryStream.Position = 0;
                //設定 buffer 長度
                //Set buffer length
                data = new byte[oMemoryStream.Length];
                //將資料寫入 buffer
                //Wrire data to buffer
                oMemoryStream.Read(data, 0, Convert.ToInt32(oMemoryStream.Length));
                //將所有緩衝區的資料寫入資料流
                //Flush memory.
                oMemoryStream.Flush();
 
            }
            //將buffer 中的stream全部送出
            Response.BinaryWrite(data);
            Response.Flush();
 
        }
    }
}


實作端:



HTML :





<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestAjax.aspx.cs" Inherits="TestRippleCaptcha.TestAjax" %>
 
<!DOCTYPE html>
 
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="http://code.jquery.com/jquery-1.8.0.min.js" type="text/javascript"></script>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <img src="CaptchaCreator.aspx" id="imgCaptcha" />
            <asp:TextBox ID="txtCaptcha" runat="server"></asp:TextBox>
            <input type="button" id="input_Refresh" value="Refresh" />
            <br />
 
            <asp:Button ID="btnCheck" runat="server" Text="Check" OnClick="btnCheck_Click" />
            <br />
            <asp:Label ID="lblResult" runat="server" Text=""></asp:Label>
 
            <script type="text/javascript">
 
 
                $('#input_Refresh').click(function () {
                    $('#imgCaptcha').attr('src', 'CaptchaCreator.aspx?' + RandomNumber(1, 9999));
                });
 
 
                function RandomNumber(min, max) {
                    return Math.floor(Math.random() * (max - min + 1) + min);
                }
            </script>
        </div>
    </form>
</body>
</html>


 


 


驗證依然在 Server 端..


 




using System;
 
namespace TestRippleCaptcha
{
    public partial class TestAjax : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
 
        }
        protected void btnCheck_Click(object sender, EventArgs e)
        {
            lblResult.Text = (Session["CAPTCHA"].ToString().ToUpper() == txtCaptcha.Text.Trim().ToUpper()).ToString();
        }
    }
}


完整程式碼放在 Github :  https://github.com/donma/RippleCaptcha



下載後直接可以跑..


當麻許的超技八 2014 | Donma Hsu Design.