我恍如隔世,忽然从梦中惊醒,是小编想的太少,小编总是为自己的方便着想,没有想到程序员的难处,当然程序员是想让大家方便,但是没有事事那么完美无瑕,所以为了大家方便的同时,程序员遇到更大的一个难题就是安全,而验证码是一种区分用户是计算机和人的全自动程序,可以防止,恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上是用验证码是现在很多网站通行的方式(比如招商银行的网上个人银行,百度社区),程序员利用比较简易的方式实现了这个功能。到现在也许有很多的用户反映到登陆输入验证码太麻烦了,所以看到有一些网站是第一次登陆不需要输入验证码,然后你输入用户名或者密码不对的时候,就是登陆不成功的时候,验证码才出来,毕竟那是电脑,没有人脑那么灵活,所以程序员就让给电脑一个灵感,但登陆不成功的时候,为了安全,就给出验证码,这就很好的有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试了,这就实现了安全。我们看一下腾讯QQ是怎么做的:
如果多次登陆不成功,就会出现如下窗口提示:
我们的验证码出来了,这就证明了我们的验证码确实能有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试进行破解。所以当我们要输入验证码的时候,我们要想到这些,就不必心烦了,程序员想的不是不周到,是想让大家的数据更加安全,也为我们的秘密泄露加上了更好的防护。转念又想,至于春运买火车票的,小编总是抱怨说输入验证码导致自己没买到票,换句话说,要是不输入验证码,那更买不到了,至于人家的铁道部网站做的怎么样,我们先不讨论。相信很多人跟小编一样,有过这样的经历,其实特别美好,如果没有这样的疑惑,我们就没有进步的动力,就难以跟上时代的步伐。今天,小编就带领大家来揭开验证码的神奇面纱,看看她的背后是如何工作?首先我们做一个登陆页面,来看看验证码的背后是怎么工作的:
<span style="font-size:18px;"><%@ Page Language="C#" AutoEventWireup="true" CodeFile="login.aspx.cs" Inherits="admin_login" %>
<!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.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 id="loginfrm" class="round1">
<h3>后台登陆-牛腩新闻发布系统</h3>
<div id="login">
<img src="../images/niunanlogo.jpg" alt="LOGO" class="login_logo" />
<p>用户名:<asp:TextBox ID="txtName" runat="server" CssClass="textbox"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txtName" ErrorMessage="姓名不能为空">*123</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="textcode"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="请输入验证码!" Text="*" ControlToValidate="txtCode"></asp:RequiredFieldValidator>
</p>
<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
<p>
<asp:Button ID="btnLogin" runat="server" Text="登陆" οnclick="btnLogin_Click" /></p>
</div>
<div id="footer">版权所有 © <a href="http://niunan.javaeye.com" target="_blank">牛腩</a>&<a href="http://www.tg029.com"
target="_blank">众志网 </a></div>
</div>
</form>
</body>
</html></span>
Login.aspx.cs的代码:
<span style="font-size:18px;">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;
public partial class admin_login : 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().ToUpper();
string rightCode = Session["Code"].ToString();
if (code != rightCode)
{
Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('验证码输入错误!');</script>");
return;
}
string name = txtName.Text.Trim();
string pwd = txtPassword.Text.Trim();
// 把密码转为MD5码的形式
pwd = FormsAuthentication.HashPasswordForStoringInConfigFile(pwd, "MD5");
bool b = LoginManager.Login(name, pwd);
if (b)
{
// 登陆成功
Session["admin"] = name;
Response.Redirect("categorymanager.aspx");
}
else
{
Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('登陆失败,用户名或者密码错误!');</script>");
}
}
}
</span>
css排版中的代码
<span style="font-size:18px;">/*
*登陆验证码测试
*/
*
{
margin :0;
padding :0;
}
body
{
font-size :14px;
}
#loginfrm #login p
{
padding-bottom :10px;
}
.textbox
{
width :150px;
}
.txtCode
{
width :73px;
} </span>
业务逻辑层:
<span style="font-size:18px;">/*
*创建人:丁国华
*创建时间:2014年11月19日 14:36:59
*说明:登陆的业务逻辑类
*版权所有:丁国华&www.tg029.com(众志网)
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 ("niunan" == name && "E10ADC3949BA59ABBE56E057F20F883E" == pwd)
{
flag = true;
}
return flag;
}
#endregion
}
}
</span>
最后我们来看看验证码这块的内容:
<span style="font-size:18px;"><%@ WebHandler Language="C#" Class="WaterMark" %>
/*
* 创建人:丁国华
* 创建时间:2014年11月22日 21:54:52
* 版权所有:丁国华&众志网(www.tg029.com)
*/
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;
}
}
}</span>
最后,我们来看一下我们的界面效果:
这个登录验证码的窗体已经完成了,我们看的出来验证码其实就是通过一张图片,来区分用户和计算机,就能达到很好的防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试;所以为了咱们的网络安全,这个验证码确实发挥了很大的作用。牛腩新闻发布系统,未完,待续......