当你多次登陆不成功的时候,他会弹出这么一个窗口:
我们的验证码出来了,这就证明了咱们的验证码确实能有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试进行破解。所以当我们要输入验证码的时候,我们要想到这些,就不必心烦了,程序员想的不是不周到,是想让大家的数据更加安全,也为我们的秘密泄露加上了很好的保护套。
至于春运买火车票的,我看见很多人抱怨说输入验证码导致自己没买到票,这么说吧,要是不输入验证码,那更买不到了,至于人家的铁道部网站做的怎么样,咱们先不讨论。
相信很多人跟我一样,有过这样的背景,其实挺好,没有这样的疑惑,我们就没有进步的动力,就难以跟上时代的步伐。我写这篇博客就是想给大家解开这个迷惑,到底这是怎么做到的呢?
我在想,为什么验证码那么神奇呢?为什么验证码能区分用户是计算机和人呢?他是怎么做到的呢?原因很简单,我们来看看内部的代码运行情况:
我们做一个登陆页面,来看看验证码的背后是怎么工作的:
- <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Login_blog.aspx.cs" Inherits="WebApplication1.Login_blog" %>
- <!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 runat="server">
- <title>登陆验证码测试</title>
- <link href="css/Login_blog.css" rel="stylesheet" type="text/css" />
- <script language="javascript" type="text/javascript">
- function changeCode() {
- var imgNode = document.getElementById("vimg");
- imgNode.src = "../handler/WaterMark.ashx?t=" + (new Date()).valueOf(); // 这里加个时间的参数是为了防止浏览器缓存的问题
- }
- </script>
- </head>
- <body>
- <form id="form1" runat="server">
- <div>
- <h3>
- 登录验证码测试
- </h3>
- <div id="Login_blog">
- <p>
- 用户名:
- <asp:TextBox ID="txtUserName" runat="server" CssClass="textbox"></asp:TextBox>
- <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="请输入用户名"
- Text="*" ControlToValidate="txtUserName"></asp:RequiredFieldValidator>
- </p>
- <p>
- 密码:
- <asp:TextBox ID="txtPassword" runat="server" TextMode="Password" CssClass="textbox"></asp:TextBox>
- <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="请输入密码!"
- Text="*" ControlToValidate="txtPassword"></asp:RequiredFieldValidator>
- </p>
- <p>
- 验证码:<img src="../handler/WaterMark.ashx" id="vimg" alt="" οnclick="changeCode()" />
- <asp:TextBox ID="txtCode" runat="server" CssClass="txtCode"></asp:TextBox>
- <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="请输入验证码!"
- Text="*" ControlToValidate="txtCode"></asp:RequiredFieldValidator>
- </p>
- <p>
- <asp:Button ID="btnLogin" runat="server" Text="登录" OnClick="btnLogin_Click" />
- </p>
- <asp:ValidationSummary ID="ValidationSummary1" runat="server" ShowMessageBox="true"
- ShowSummary="false" />
- </div>
- </div>
- </form>
- </body>
- </html>
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.UI;
- using System.Web.UI.WebControls;
- using BLL;
- using System.Web.Security;
- namespace WebApplication1
- {
- public partial class Login_blog : System.Web.UI.Page
- {
- protected void Page_Load(object sender, EventArgs e)
- {
- }
- //登录按钮
- protected void btnLogin_Click(object sender, EventArgs e)
- {
- //判断验证码是否输入正确
- string code = txtCode.Text.Trim();
- string rightCode = Session["Code"].ToString();
- if (code!=rightCode)
- {
- Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('验证码输入错误!');</script>");
- return;
- }
- string name = txtUserName.Text.Trim();
- string pwd = txtPassword.Text.Trim();
- bool b = LoginManager.Login(name, pwd);
- if (b)
- {
- //登录成功
- Session["admin"] = name;
- Response.Redirect("http://blog.csdn.net/yi_zz");
- }
- else
- {
- //登录失败
- Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('登陆失败,用户名或者密码错误!');</script>");
- }
- }
- }
- }
- /*
- *登陆验证码测试
- */
- *
- {
- margin :0;
- padding :0;
- }
- body
- {
- font-size :14px;
- }
- #loginfrm #login p
- {
- padding-bottom :10px;
- }
- .textbox
- {
- width :150px;
- }
- .txtCode
- {
- width :73px;
- }
- /*
- * 创建人:宗毅
- * 创建时间:2012年8月11日19:38:27
- * 说明:登陆的业务逻辑类
- * 版权所有:
- */
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace BLL
- {
- public class LoginManager
- {
- #region 用户登陆是否成功
- /// <summary>
- /// 用户登陆是否成功
- /// </summary>
- /// <param name="name">用户名</param>
- /// <param name="pwd">密码</param>
- /// <returns></returns>
- public static bool Login(string name, string pwd)
- {
- bool flag = false;
- if ("zongyi" == name && "czy" == pwd)
- {
- flag = true;
- }
- return flag;
- }
- #endregion
- }
- }
最后看看验证码这部分的代码:
- /*
- * 验证码
- */
- using System;
- using System.Web;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Web.SessionState;
- public class WaterMark : IHttpHandler, IRequiresSessionState // 要使用session必须实现该接口,记得要导入System.Web.SessionState命名空间
- {
- public void ProcessRequest(HttpContext context)
- {
- string checkCode = GenCode(5); // 产生5位随机字符
- context.Session["Code"] = checkCode; //将字符串保存到Session中,以便需要时进行验证
- System.Drawing.Bitmap image = new System.Drawing.Bitmap(70, 22);
- Graphics g = Graphics.FromImage(image);
- try
- {
- //生成随机生成器
- Random random = new Random();
- //清空图片背景色
- g.Clear(Color.White);
- // 画图片的背景噪音线
- int i;
- for (i = 0; i < 25; 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.Silver), x1, y1, x2, y2);
- }
- Font font = new System.Drawing.Font("Arial", 12, (System.Drawing.FontStyle.Bold));
- System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2F, true);
- g.DrawString(checkCode, font, brush, 2, 2);
- //画图片的前景噪音点
- g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);
- System.IO.MemoryStream ms = new System.IO.MemoryStream();
- image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
- context.Response.ClearContent();
- context.Response.ContentType = "image/Gif";
- context.Response.BinaryWrite(ms.ToArray());
- }
- finally
- {
- g.Dispose();
- image.Dispose();
- }
- }
- /// <summary>
- /// 产生随机字符串
- /// </summary>
- /// <param name="num">随机出几个字符</param>
- /// <returns>随机出的字符串</returns>
- private string GenCode(int num)
- {
- string str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- char[] chastr = str.ToCharArray();
- string code = "";
- Random rd = new Random();
- int i;
- for (i = 0; i < num; i++)
- {
- //code += source[rd.Next(0, source.Length)];
- code += str.Substring(rd.Next(0, str.Length), 1);
- }
- return code;
- }
- public bool IsReusable
- {
- get
- {
- return false;
- }
- }
- }
这个登录验证码的窗体已经算完成了,我们看的出来验证码其实就是通过一张图片,来区分用户和计算机,就能达到很好的防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试;所以为了咱们的网络安全,这个验证码确实发挥了很大的作用。