随机校验码的生成和使用

随机校验码的生成和使用

在一些网页以及窗口应用程序中,经常会碰到一些随机校验码的使用问题。其作用是可以增强系统的安全性,防止恶意注册,恶意使用等。校验码大致会有以下几种形式:全部是英文字符,如数字,大小写字符混合,汉字,随机的一些简单数学试题等。

其图案显示的内容可以随机更改,现对其实现原理做一点简单说明,以供大家交流学习。

具体代码可以在http://download.csdn.net/source/2862637下载

第一步,是随机图片的生成。

需要在窗口上添加一个PictureBox的控件,用来显示将来生成的随机图片。然后就在后台代码中自定义一个Image,然后定义一个画笔,在刚刚生成的图片上进行绘制图形,如增加一些噪声点,干扰线等。当然,还需要将我们随机生成的一些字符信息写到图片上,以便能够显示。

具体的代码如下:

private void CreateCheckCodeImage(string checkCode)

        {

            if (checkCode == null || checkCode.Trim() == String.Empty)

                return;

            Bitmap image = new Bitmap((int)Math.Ceiling((checkCode.Length * 20.5)), 22);

            Graphics g = Graphics.FromImage(image);

 

            try

            {

                Random random = new Random();

                g.FillRectangle(Brushes.White, 0, 0, image.Width, image.Height);           

            

            for (int i = 0; i < 2; i++)

            {

                int x1 = random.Next(image.Width);

                int x2 = random.Next(image.Width);

                int y1 = random.Next(image.Height);

                int y2 = random.Next(image.Height);

                g.DrawLine(new Pen(Color.Black), x1, y1, x2, y2);

            }

            Font font = new System.Drawing.Font("微软雅黑", 12, (System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic));

            //使用系统画刷,在一个新矩形里画图

            

            System.Drawing.Drawing2D.LinearGradientBrush  brush = new LinearGradientBrush(

                new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed,

                0, true);

 

 

            g.DrawString(checkCode, font, brush , 2, 2);

            

            for (int i = 0; i < 100; i++)

            {

                int x = random.Next(image.Width);

                int y = random.Next(image.Height);

                //生成随机的图形噪音点

                image.SetPixel(x, y, Color.FromArgb(random.Next()));

            }

//将生成的图片绑定到窗口的PictureBox控件上,进行显示

            this.picCheck.Width = image.Width;

            this.picCheck.Height = image.Height;

            this.picCheck.BackgroundImage = image;

            }

            finally

            {

                g.Dispose();

            }

        }

以上代码是生成图片,显示的是得到的随机内容,这里的图片设置较为简单,如果愿意,可以加上其他的效果,如扭曲变化,翻转,倒影等,在此不做具体阐述。

第二步是,如何得到随机的文字内容?

我们会使用getCheckCode()函数来生成随机内容,在这个函数里,调用了三个不同的函数,以便分别能够生成字符,汉字,以及随机数学试题。具体代码如下:

private string getCheckCode()

        {

            Random random = new Random();

            //根据随机生成的caseNum,来确定所使用的图案内容

            int caseNum = random.Next() % 3;

            checkCode = string.Empty;

            switch (caseNum)

            {

                case 0:

                    //普通校验码

                    getEnglishCode();

                    break;

                case 1:

                    //汉字校验码

                        getChineseCode();

                    break;

                case 2:

                    //随机测试题校验码

                    getNumCode();

                    break;                

            }

            return checkCode;

        }     

首先通过一个随机数,来确定使用哪种校验码。

下面是三种不同校验码的生成。

①普通校验码

private string getEnglishCode()

        {           

            Random random = new Random();

            int number;

            char code;

            for (int i = 0; i < 4; i++)

            {

                number = random.Next();

//如果是偶数,生成一个随机数字

                if (number % 2 == 0)

                    code = (char)('0' + (char)(number % 10)); 

                else//如果为奇数,生成一个随机字符

                    code = (char)('A' + (char)(number % 26)); 

 

                //将该字符存储到验证码中

                checkCode += code.ToString();

            }

            return checkCode;

     }

②,汉字校验码

private string getChineseCode()

        {

            Random random = new Random();

            int strlength = 4;

            //定义一个字符串数组储存汉字编码的组成元素 

            string[] r = new String[16] { "0""1""2""3""4""5""6""7""8""9""a""b""c""d""e""f" };

 

            //定义一个object数组用来 

            object[] bytes = new object[strlength];

            /**/

     /*每循环一次产生一个含两个元素的十六进制字节数组,并将其放入bject数组中 

         每个汉字有四个区位码组成 

         区位码第1位和区位码第2位作为字节数组第一个元素 

         区位码第3位和区位码第4位作为字节数组第二个元素 

        */

            for (int i = 0; i < strlength; i++)

            {

                //区位码第1 

                int r1 = random.Next(11, 14);

                string str_r1 = r[r1].Trim();

                //区位码第2 

               random = new Random(r1 * unchecked((int)DateTime.Now.Ticks) + i);

//更换随机数发生器的种子避免产生重复值 

                int r2;

                if (r1 == 13)

                    r2 = random.Next(0, 7);

                else

                    r2 = random.Next(0, 16);

                string str_r2 = r[r2].Trim();

                //区位码第3 

                random = new Random(r2 * unchecked((int)DateTime.Now.Ticks) + i);

                int r3 = random.Next(10, 16);

                string str_r3 = r[r3].Trim();

                //区位码第4 

                random = new Random(r3 * unchecked((int)DateTime.Now.Ticks) + i);

                int r4;

                if (r3 == 10)

                {

                    r4 = random.Next(1, 16);

                }

                else if (r3 == 15)

                {

                    r4 = random.Next(0, 15);

                }

                else

                {

                    r4 = random.Next(0, 16);

                }

                string str_r4 = r[r4].Trim();

                //定义两个字节变量存储产生的随机汉字区位码 

                byte byte1 = Convert.ToByte(str_r1 + str_r2, 16);

                byte byte2 = Convert.ToByte(str_r3 + str_r4, 16);

                //将两个字节变量存储在字节数组中 

                byte[] str_r = new byte[] { byte1, byte2 };

                //将产生的一个汉字的字节数组放入object数组中 

                bytes.SetValue(str_r, i);

            }

            Encoding gb = Encoding.GetEncoding("gb2312");

            //根据汉字编码的字节数组解码出中文汉字 

            for (int m = 0; m < strlength; m++)

                checkCode += gb.GetString((byte[])Convert.ChangeType(bytes[m], typeof(byte[])));

            return checkCode;

   }  

③,随机数学试题生成

private string getNumCode()

        {

            flag = true;

            result = 0;

            Random rand = new Random();

            int op = rand.Next() % 4;

            int a = rand.Next() % 10;

            int b = rand.Next() % 10;

            

            switch (op)

            {

                case 0:

                    {

                        result  = a + b;

                        checkCode = a + "+" + b + " =";

                    }

                    break;

                case 1:

                    {

                        result = a - b;

                        checkCode = a + "-" + b + " =";

                    }

                    break;

                case 2:

                    {

                        result = a * b;

                        checkCode = a + "*" + b + " =";

                    }

                    break;

            }

            return checkCode;

        }

第三步,是如何将用户输入的校验信息与图片显示的信息进行比较匹配。

当点击Logon按钮的时候,会发生如下的事件:

private void btnLogin_Click(object sender, EventArgs e)

        {

            if(flag)

                checkCode = result.ToString();

            if (txtUserName.Text == "Admin" && txtPwd.Text == "admin" && txtCheck.Text == checkCode)

            {

                MessageBox.Show("Welcome " + txtUserName.Text + " and your password is " + txtPwd.Text + " and you checkCode is " + checkCode,

                    "登陆成功",MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            else

                MessageBox.Show("你的用户名或者密码,或者验证码错误","温馨提示",

                    MessageBoxButtons.OK, MessageBoxIcon.Information);

        }

在程序中,使用了一个全局变量checkCode,用来接收随机生成的校验信息,然后与用户输入的验证码进行比较,据此来判断是否正确输入。

如果是随机的数学试题,(flag = true,则将试题的结果传递给checkCode,用来跟用户输入的计算结果进行比较判断。

其他的比如刷新,重新获取操作较为简单,在此不做阐述,具体可以参考代码。

以上就是一个利于随机校验图片的实现,当然,我们可以将其编译成为一个dll控件,这样在其他的程序中都可以直接调用,使用起来也较为方便。

 

以上就是对随机校验码实现的一点简单说明,不免显得有些啰嗦,但第一次写技术性的文字,不知该如何下手,希望大家多多交流,共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值