首页  ·  知识 ·  云计算
实现数字、字母、中文混淆验证
moozi  http://www.cnblogs.com/moozi/  综合  编辑:dezai  图片来源:网络
请先看动网验证码的截图: 系

请先看动网验证码的截图:

 

 

系统自动生成中文、数字、字母的混合字符串,并且自动设置有效的验证码值。上图中的有效验证码值为“mejjh”,而图片全文为“mej的jh”,这样就可以有效地防止被机器识别出验证码了。

    我把动网里的验证码代码剥离出来,并作了一些修改。

    在动网源代码中,它生成的验证码参数设置是读取Request.QueryString值的,这里我们不再使用这种方式设置验证码,改用xml文件保存设置。

XML配置


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
   
 


 

再把xml文件的配置信息映射到一个类上:

XML配置类
/**////


/// 验证码配置文件
///

public class ValidateCodeConfig
{
    属性#region 属性
    private Color bgcolor;
    /**////
    /// 背景色
    ///

    public Color BgColor
    {
        get { return bgcolor; }
        set { bgcolor = value; }
    }
    private bool bold;
    /**////
    /// 是否粗体
    ///

    public bool Bold
    {
        get { return bold; }
        set { bold = value; }
    }
    private Color forecolor;
    /**////
    /// 颜色
    ///

    public Color ForeColor
    {
        get { return forecolor; }
        set { forecolor = value; }
    }
    private string fontFamily;
    /**////
    /// 字体
    ///

    public string FontFamily
    {
        get { return fontFamily; }
        set { fontFamily = value; }
    }
    private int fontSize;
    /**////
    /// 字体大小
    ///

    public int FontSize
    {
        get { return fontSize; }
        set { fontSize = value; }
    }
    private int height;
    /**////
    /// 高度
    ///

    public int Height
    {
        get { return height; }
        set
        {
            if (300 < value)
                height = 300;
            else
                height = value;
        }
    }
    private int impurity;
    /**////
    /// 杂质
    ///

    public int Impurity
    {
        get { return impurity; }
        set
        {
            if (30 < value)
                impurity = 30;
            else
                impurity = value;
        }
    }
    private bool italic;
    /**////
    /// 斜体
    ///

    public bool Italic
    {
        get { return italic; }
        set { italic = value; }
    }
    private int width;
    /**////
    /// 宽度
    ///

    public int Width
    {
        get { return width; }
        set
        {
            if (300 < value)
                width = 300;
            else
                width = value;
        }
    }
    private char[] codetext;
    /**////
    /// 验证码字符
    ///

    public char[] CodeText
    {
        get { return codetext; }
        set { codetext = value; }
    }
    private int number;
    /**////
    /// 验证码字数
    ///

    public int Number
    {
        get { return number; }
        set { number = value; }
    }
    #endregion

    /**////


    /// 构造函数
    ///

    public ValidateCodeConfig()
    {
        LoadXMLOnInit();
    }

    /**////


    /// 加载config.xml配置
    ///

    private void LoadXMLOnInit()
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(HttpContext.Current.Server.MapPath("~/ValidateCode/config.xml"));
        this.bgcolor = Color.FromName(doc.GetElementsByTagName("bgcolor").Item(0).Attributes["value"].Value);
        this.bold = Boolean.Parse(doc.GetElementsByTagName("bold").Item(0).Attributes["value"].Value);
        this.codetext = doc.GetElementsByTagName("codetext").Item(0).InnerText.ToCharArray();
        this.fontFamily = doc.GetElementsByTagName("fontfamily").Item(0).Attributes["value"].Value;
        this.fontSize = int.Parse(doc.GetElementsByTagName("fontsize").Item(0).Attributes["value"].Value);
        this.forecolor = Color.FromName(doc.GetElementsByTagName("forecolor").Item(0).Attributes["value"].Value);
        this.height = int.Parse(doc.GetElementsByTagName("height").Item(0).Attributes["value"].Value);
        this.impurity = int.Parse(doc.GetElementsByTagName("impurity").Item(0).Attributes["value"].Value);
        this.italic = Boolean.Parse(doc.GetElementsByTagName("italic").Item(0).Attributes["value"].Value);
        this.width = int.Parse(doc.GetElementsByTagName("width").Item(0).Attributes["value"].Value);
        this.number = int.Parse(doc.GetElementsByTagName("number").Item(0).Attributes["value"].Value);
    }
}
 

在绘图方法中调用这个类,并为其设置缓存依赖:

为配置文件设置缓存依赖
/**////


/// 为配置文件设置缓存依赖
///

private void LoadConfig()
{
    if (HttpRuntime.Cache["ValidateCodeConfig"] == null)
    {
        config = new ValidateCodeConfig();
        CacheDependency dep = new CacheDependency(HttpContext.Current.Server.MapPath("~/ValidateCode/config.xml"));
        HttpRuntime.Cache.Insert("ValidateCodeConfig", config, dep, DateTime.MaxValue,
            TimeSpan.Zero);
    }
    else
    {
        config = (ValidateCodeConfig)HttpRuntime.Cache["ValidateCodeConfig"];
    }
}
 

之后,我们就可以开始写生成验证码的主要方法了:

验证码主要方法
/**////


/// 验证码字体样式
///

///
private FontStyle GetFontStyle()
{
    if (config.Bold && config.Italic)
    {
        return (FontStyle.Italic | FontStyle.Bold);
    }
    if (config.Bold)
    {
        return FontStyle.Bold;
    }
    if (config.Italic)
    {
        return FontStyle.Italic;
    }
    return FontStyle.Regular;
}

private Bitmap GetneralCodeImage()
{
    bool flag3;
    Random random = new Random();
    Bitmap image = new Bitmap(config.Width, config.Height);
    Graphics graphics = Graphics.FromImage(image);
    graphics.Clear(config.BgColor);
    int length = Directory.GetFiles(Server.MapPath("~/ValidateCode/"), "*.gif").Length;
    int backgroundfile = random.Next(1, length);

    Brush brush = new TextureBrush(new Bitmap(Server.MapPath("~/ValidateCode/" + backgroundfile.ToString() + ".gif")));
    Rectangle rect = new Rectangle(0, 0, config.Width, config.Height);
    graphics.FillRectangle(brush, rect);
    string[] strColorArray = new string[]
{
"#666666", "#003300", "#009900", "#330000", "#333300",
"#336600", "#660000", "#663300", "#666600", "#FF99FF",
"#FF33FF", "#CCCCFF", "#CC66FF", "#CC00FF", "#9999FF",
"#9933FF", "#9900FF", "#FF00FF", "#996633", "#CC3333",
"#FF3333", "#6633FF", "#0033FF", "#336666", "#CC9900",
"#6633CC", "#66FF66", "#009999", "#99CC00", "#615379",
"#E6649E", "#B5B495", "#73CEA7"
};
    bool istop = random.Next(0, 2) == 0;
    Pen pen = new Pen(ColorTranslator.FromHtml(strColorArray[random.Next(0, strColorArray.Length)]), 2f);
    pen.DashStyle = DashStyle.Solid;
    Point[] randomPointGroup = this.GetRandomPointGroup(istop);
    for (int i = 0; i < randomPointGroup.Length; i += 2)
    {
        graphics.DrawLine(pen, randomPointGroup[i], randomPointGroup[i + 1]);
    }
    string input = "";
    for (int j = 0; j < config.Number; j++)
    {
        input += config.CodeText[random.Next(config.CodeText.Length)].ToString();
    }
    string[] strArray2 = new string[config.Number + 1];
    int index = 0;
Label_0313:
    while (index != config.Number)
    {
        string str2 = strColorArray[random.Next(0, strColorArray.Length)];
        strArray2[index] = str2;
        index++;
        for (int n = 0; n < strArray2.Length; n++)
        {
            if (strArray2[n] == str2)
            {
                goto Label_0313;
            }
            if (n == (strArray2.Length - 1))
            {
                strArray2[index] = str2;
                index++;
            }
        }
    }
    char[] chArray2 = input.ToCharArray();
    int num8 = random.Next(0, config.Number - 1);
    string str3 = strArray2[num8];
    int num9 = random.Next(0, config.Number - 2) + 1;
    num9 = (num9 == 1) ? 2 : num9;
    int[] numArray = new int[num9];
    numArray[0] = num8;
    for (int k = 1; k < num9; k++)
    {
        int num11 = random.Next(0, config.Number - 1);
        bool flag2 = false;
        for (int num12 = 0; num12 < k; num12++)
        {
            if (numArray[num12] == num11)
            {
                flag2 = true;
                break;
            }
        }
        if (!flag2)
        {
            numArray[k] = num11;
        }
        else
        {
            k--;
        }
    }
    do
    {
        string str4 = strColorArray[random.Next(0, strColorArray.Length)];
        flag3 = false;
        for (int num13 = 0; num13 < strArray2.Length; num13++)
        {
            if (str4 == strArray2[num13])
            {
                flag3 = true;
                break;
            }
        }
    }
    while (flag3);
    string strRegexString = "";
    string strRegexValidateType = "";

    int intValidateType = random.Next(0, 3);

    bool flag4 = false;
    while (!flag4)
    {
        Match matchChinese;
        Match matchLetter;
        Match matchNumber;
        switch (intValidateType)
        {
            case 0:
                if (!Regex.IsMatch(input, @"[\u4e00-\u9fa5]+"))
                {
                    goto Label_RandomCodeType;
                }
                flag4 = true;
                strRegexValidateType = "中文字体";
                matchChinese = Regex.Match(input, @"[\u4e00-\u9fa5]+", RegexOptions.Multiline | RegexOptions.IgnoreCase);
                goto Label_ChineseRegexResult;

            case 1:
                if (!Regex.IsMatch(input, "[a-zA-Z]+"))
                {
                    goto Label_RandomCodeType;
                }
                flag4 = true;
                strRegexValidateType = "英文字母";
                matchLetter = Regex.Match(input, "[a-zA-Z]+", RegexOptions.Multiline | RegexOptions.IgnoreCase);
                goto Label_LetterRegexResult;

            case 2:
                if (!Regex.IsMatch(input, "[0-9]+"))
                {
                    goto Label_RandomCodeType;
                }
                flag4 = true;
                strRegexValidateType = "数字";
                matchNumber = Regex.Match(input, "[0-9]+", RegexOptions.Multiline | RegexOptions.IgnoreCase);
                goto Label_NumberRegexResult;

            case 3:
                if (Regex.IsMatch(input, @"[^\u4e00-\u9fa5|a-zA-Z|0-9]"))
                {
                    flag4 = true;
                    strRegexValidateType = "特殊字符";
                    strRegexString = new Regex(@"[\u4e00-\u9fa5|a-zA-Z|0-9]+").Replace(input, "");
                }
                goto Label_RandomCodeType;

            default:
                goto Label_RandomCodeType;
        }
    Label_ChineseRegexSuccess:
        strRegexString = strRegexString + matchChinese.Value;
        matchChinese = matchChinese.NextMatch();
    Label_ChineseRegexResult:
        if (matchChinese.Success)
        {
            goto Label_ChineseRegexSuccess;
        }
        goto Label_RandomCodeType;
    Label_LetterRegexSuccess:
        strRegexString = strRegexString + matchLetter.Value;
        matchLetter = matchLetter.NextMatch();
    Label_LetterRegexResult:
        if (matchLetter.Success)
        {
            goto Label_LetterRegexSuccess;
        }
        goto Label_RandomCodeType;
    Label_NumberRegexSuccess:
        strRegexString = strRegexString + matchNumber.Value;
        matchNumber = matchNumber.NextMatch();
    Label_NumberRegexResult:
        if (matchNumber.Success)
        {
            goto Label_NumberRegexSuccess;
        }

    Label_RandomCodeType:
        if (!flag4)
        {
            intValidateType = random.Next(0, 3);
        }
    }
    int num16 = 0;
    for (int m = 0; m < chArray2.Length; m++)
    {
        int num21;
        int num18 = config.FontSize;
        int num19 = (m == 0) ? 10 : 25;
        num16 += num19;
        int num20 = num16;
        if (istop)
        {
            num21 = random.Next(15, config.Height - 35);
        }
        else
        {
            num21 = random.Next(0, config.Height - 45);
        }
        bool flag5 = false;
        if ((((('.' != chArray2[m]) && ('_' != chArray2[m])) && (('*' != chArray2[m]) && ('`' != chArray2[m]))) && ((('~' != chArray2[m]) && ('.' != chArray2[m])) && ((',' != chArray2[m]) && ('\'' != chArray2[m])))) && ((('-' != chArray2[m]) && ('|' != chArray2[m])) && ('\\' != chArray2[m])))
        {
            char ch1 = chArray2[m];
        }
        graphics.DrawString(chArray2[m].ToString(), new Font(config.FontFamily, flag5 ? ((float)(num18 + 30)) : ((float)num18), flag5 ? FontStyle.Bold : this.GetFontStyle()), new SolidBrush(ColorTranslator.FromHtml(strArray2[m])), (float)num20, (float)num21);
    }

    graphics.DrawString("输入图中出现的", new Font("Verdana", 10f, FontStyle.Regular), new SolidBrush(ColorTranslator.FromHtml("#008000")), (2 == intValidateType) ? ((float)18) : ((float)4), istop ? ((float)2) : ((float)(config.Height - 16)));
    graphics.DrawString(strRegexValidateType, new Font("Verdana", 10f, FontStyle.Bold), new SolidBrush(ColorTranslator.FromHtml("#FF0000")), (2 == intValidateType) ? ((float)126) : ((float)110), istop ? ((float)2) : ((float)(config.Height - 16)));

    graphics.Dispose();
    Response.Cookies.Add(new HttpCookie("ValidateCode", strRegexString.ToLower()));
    return image;
}

/**////


/// 杂质
///

///
///
private Point[] GetRandomPointGroup(bool istop)
{
    Point[] pointArray = new Point[config.Impurity * 2];
    for (int i = 0; i < pointArray.Length; i++)
    {
        int num2 = new Random().Next(10000000, 99999999);
        int x = new Random((num2 / (i + 2)) * (i + 1)).Next(0, config.Width);
        int y = new Random((num2 / (x + 2)) * (x + 1)).Next(istop ? 16 : 0, istop ? config.Height : (config.Height - 16));
        pointArray[i] = new Point(x, y);
    }
    return pointArray;
}
 

最后,在Page_Load中调用上面的方法:

private void Page_Load(object sender, EventArgs e)
{
    this.LoadConfig();
    base.Response.ContentType = "image/gif";
    this.GetneralCodeImage().Save(base.Response.OutputStream, ImageFormat.Gif);
}

效果

 

本文作者:moozi 来源:http://www.cnblogs.com/moozi/
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读