空心字体验证码

时间:2022-05-09 06:12:15
<%@ WebHandler Language="C#" Class="Handler" %>


using System;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Web.SessionState;
using System.Drawing.Text;
using System.Drawing.Drawing2D;


public class Handler : IHttpHandler, IRequiresSessionState
{


    static PrivateFontCollection pfc = null;
    public void ProcessRequest(HttpContext context)
    {
        string checkCode = context.Request.QueryString["ValidateCode"];
        if (checkCode == null)
            checkCode = "0 0 0 0";
        context.Session["GetCode"] = checkCode;
        int iwidth = 108;//(int)(checkCode.Length * 11.5);
        System.Drawing.Bitmap image = new System.Drawing.Bitmap(iwidth, 45);
        Graphics g = Graphics.FromImage(image);
        Random random = new Random(System.DateTime.Now.Millisecond);
        
        


        
        //Font f = new System.Drawing.Font("Arial", 16, System.Drawing.FontStyle.Regular);


        //Brush b = new System.Drawing.SolidBrush(Color.Black);
        Brush b = new System.Drawing.SolidBrush(Color.FromArgb(4683611));
        //g.FillRectangle(new System.Drawing.SolidBrush(Color.Blue),0,0,image.Width, image.Height);
        //Color color = Color.FromArgb(16775149);
        g.Clear(Color.FromArgb(237, 247, 255));
        using (StringFormat format = new StringFormat())
        {
            
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;
            format.FormatFlags = StringFormatFlags.NoWrap;
            Matrix matrix = new Matrix();
            float offsetx = -35, offsety = 0;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            for (int i = 0; i < checkCode.Length; i++)
            {
                int fsize = random.Next(24,28);
                Font f = CreateFont(context.Server.MapPath("tt0767m_.TTF"), fsize, FontStyle.Bold, GraphicsUnit.Point, 0);
                SizeF size = g.MeasureString(checkCode[i].ToString(), f);

                matrix.RotateAt(random.Next(-15, 10), new PointF(offsetx+size.Width/2, offsety+size.Height/2));
                g.Transform = matrix;



                g.DrawString(
                             checkCode[i].ToString(),
                             f,
                             Brushes.Green,
                             new RectangleF(
                             offsetx,
                             offsety,
                             image.Width,
                             image.Height),
                            format);                
                //g.DrawString(checkCode, f, b, 3, 3);
                offsetx += size.Width*3/5;
                offsety += -0;
                g.RotateTransform(0); 
                matrix.Reset();
                f.Dispose();
            }
        }


        Pen blackPen = new Pen(Color.Black, 0);
        //Random rand = new Random();
        //for (int i = 0; i < 5; i++)
        //{
        //    int y = rand.Next(image.Height);
        //    g.DrawLine(blackPen, 0, y, image.Width, y);
        //}
        //System.Random rand = new Random();
        //int num = image.Width * image.Height * 30 / 300;
        //for (int iCount = 0; iCount < num; iCount++)
        //{
        //    int x = rand.Next(image.Width);
        //    int y = rand.Next(image.Height);
        //    int r = rand.Next(255);
        //    int h = rand.Next(255);
        //    int k = rand.Next(255);
        //    Color c = Color.FromArgb(r, h, k);
        //    image.SetPixel(x, y, c);
        //}
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        context.Response.ClearContent();
        context.Response.ContentType = "image/Jpeg";
        context.Response.BinaryWrite(ms.ToArray());
        g.Dispose();
        image.Dispose();
    }
    protected void DrawChar(char[] randChar, Graphics g, Bitmap bmp, Font _font)
    {
        Random random = new Random(6);
        //绘制字符
        for (int i = 0; i < randChar.Length; i++)
        {
            //获取显示的单个文字所占空间
            SizeF size = g.MeasureString(randChar[i].ToString(), _font);


            Point p = new Point(i * (int)(bmp.Width * 0.9) / randChar.Length + random.Next(-3, 3), 2 + random.Next(-2, 2));
            System.Drawing.Drawing2D.Matrix transform = new System.Drawing.Drawing2D.Matrix();
            //沿着单个文字的中心旋转 旋转一个随机的角度 0~30度
            transform.RotateAt(random.Next(0, 30), new PointF(p.X + size.Width / 2, p.Y + size.Height / 2));
            //更改矩阵
            g.Transform = transform;
            g.DrawString(randChar[i].ToString(), _font, new SolidBrush(Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256))), p);
            //矩阵还原
            g.RotateTransform(0);
        }
    }
    public static Font CreateFont(string fontFile, float fontSize, FontStyle fontStyle, GraphicsUnit graphicsUnit, byte gdiCharSet)

    {

        /*PrivateFontCollection 类允许应用程序安装现有字体的私有版本,而无需替换该字体的系统版本。例如,除系统使用的 Arial 字体外,GDI+ 还可以创建 Arial 字体的私有版本。PrivateFontCollection 还可以用于安装操作系统中不存在的字体。这种临时的字体安装不会影响系统安装的字体集合。若要查看已安装的字体集合,请使用 InstalledFontCollection 类。*/

        pfc = new PrivateFontCollection();
        pfc.AddFontFile(fontFile);
        return new Font(pfc.Families[0], fontSize, fontStyle, graphicsUnit, gdiCharSet);
    }
    private string CreateRandomCode(int codeCount)
    {
        string allChar = "0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,W,X,Y,Z";
        //string allChar = "0,1,2,3,4,5,6,7,8,9";
        string[] allCharArray = allChar.Split(',');
        string randomCode = "";
        int temp = -1;


        Random rand = new Random();
        for (int i = 0; i < codeCount; i++)
        {
            if (temp != -1)
            {
                rand = new Random(i * temp * ((int)DateTime.Now.Ticks));
            }
            int t = rand.Next(allChar.Length);
            if (temp == t)
            {
                return CreateRandomCode(codeCount);
            }
            temp = t;
            randomCode += allCharArray[t] + " ";
        }
        return randomCode;
    }
    public bool IsReusable
    {
        get
        {
            return true;
        }
    }


}

前端测试代码:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>CAPTCHA Example</title>
    <script type="text/javascript" language="javascript" src="/Scripts/jquery-1.4.1.min.js"></script>


    <style type="text/css">
body {
font-size:12px;
font-family:Verdana, Arial, Helvetica, sans-serif;
}
</style>


    <script language="javascript" type="text/javascript">
//var allChar = ['0','1','2','3','4','5','6','7','8','9'];
var allChar = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","W","X","Y","Z"];
//var allChar = new Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","W","X","Y","Z");


//var allChar = new Array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','W','X','Y','Z');
function TestCaptcha()
{
    var formcode = document.getElementById("captchacode");
    var sessioncode = document.getElementById("validatecode");


    if(formcode.value.toLowerCase() == sessioncode.value.toLowerCase())
       return true;
    else
    {
        $("#msg").css("display","inline");
        $("#msg").html("验证码错误");
        RefreshImage("img1");
return false;
    }
}
function fRandomBy(under, over){
        switch(arguments.length){
            case 1: return parseInt(Math.random()*under+1);
            case 2: return parseInt(Math.random()*(over-under+1) + under); 
            default: return 0;
        }
}
function CreateCode2()
{
    var i, ret, hvalue,tmp, num, result;
    ret="";
    hvalue=""

//随机生成3个或4个验证码
    result=parseInt(Math.random()*10) % 2;    
    if(result == 1)
    {
        num=3;
    }
    else
    {
        num = 4;
    }
    for(i=0;i<num;i++)
    {
        tmp=fRandomBy(allChar.length-1);
        hvalue= hvalue+allChar[tmp];
        ret = ret + allChar[tmp];
    }
    var formcode = document.getElementById("validatecode");
    formcode.value= hvalue;
    return ret;
}


function CreateCode(num)
{
    var i, ret, hvalue,tmp;
    ret="";
    hvalue=""
    for(i=0;i<num;i++)
    {
        tmp=fRandomBy(9);
        hvalue= hvalue+tmp;
        ret = ret + tmp+ " ";
    }
    var formcode = document.getElementById("validatecode");
    formcode.value= hvalue;
    return ret;
}
function RefreshImage(valImageId) {
var objImage = document.images[valImageId];
if (objImage == undefined) {
return;
}
    var code = CreateCode2();


objImage.src = objImage.src.split('?')[0] + '?ValidateCode=' + code;
}
$(document).ready(function(){
var objImage = document.images["img1"];
if(objImage == undefined)
{
return;
}
var code = CreateCode2();
objImage.src = objImage.src.split('?')[0] + '?ValidateCode=' + code;
});
    </script>


</head>
<body>
    <form id="form1" name="form1" method="post" action="default.aspx" onsubmit="return TestCaptcha();" >
        <table width="400" border="1" align="center">
            <tr>
                <td colspan="2" align="center">
                    <strong>CAPTCHA Example</strong></td>
            </tr>
            <tr>
                <td id="msg" colspan="2" align="right" style=" background-color:#fff2f2;height:20px ">
                </td>
            </tr>
            <tr>
                <td width="261">
                    CAPTCHA Image
                    <input name="abc" type="text" id="abc" /></td>
                <td width="223">
                    <!--<img alt="" id="imgCaptcha" src="Handler.ashx" /><a href="javascript:void(0)" onclick="RefreshImage('imgCaptcha')">Change Image</a><br />-->
                    <img alt="" id="img1" src="Handler2.ashx?ValidateCode=1234" /><a href="javascript:void(0)"
                        onclick="RefreshImage('img1')">Change Image</a><br />
                </td>
            </tr>
            <tr>
                <td>
                    Write the characters in the image above</td>
                <td>
                    <input name="captchacode" type="text" id="captchacode" size="10" /></td>
            </tr>
            <tr>
                <td>&nbsp;
                    </td>
              <td>
                    <input type="submit" name="btnTest" id="btnTest" value="Test Input" />
                    </td>
            </tr>
        </table>
        <input type="hidden" id="validatecode" />
    </form>
</body>
</html>