目标:在用户注册或登录时,为了进一步保片安全性,越来越多的网站开始采用动态生成图形码或者附加码进行验证。
思路:图形码需要动态生成且看不清楚时需要重新生成,所以不可能采用整个登录页面来刷新完成,所以将验证码图片的生成放入另一个页面去做。
所谓图形码,通常是动态生成的一个验证码,并以图形的形式显示出来,要求用户在一定时间内输入与图形中显示内容一致的信息。由于设定的很短的时间之后图形码会重新动态生成,因此要求用户必须在限定时间内进行输入验证。这样可以从时效和显示两方面进行安全性保证。
前台代码:
<table id="tab_Vilidate" runat="server" cellpadding="0" cellspacing="0" style="margin: 0;
height: 100%; width: 100%" visible="false">
<tr>
<td class="tdMod" style="font-size: 14px; color: Red; font-weight: bolder" align="right">
验证码:
</td>
<td style="width: 160px;" align="left">
<input type="text" id="txt_Vcode" runat="server" class="txt_Style" />
</td>
</tr>
<tr>
<td>
</td>
<td align="left">
<img src="ValidatePage.aspx?
ImgWidth=72&ImgHeight=22&Fineness=95&CodeLen=4&FontName=Times New Roman&FontSize=13&FontStyle=3&PosX=4&PosY=0"
alt="图像无法显示" id="SaveCode" onclick="javascript:reloadcode();" style="border: solid 1px white"
onmouseover="this.style.cursor='hand'; " />
<span id="span_Time" style="color: Red"></span>
</td>
</tr>
<tr>
<td>
</td>
<td align="left">
<a href="javascript:reloadcode()" title="刷新验证码">更换一张图片</a>
</td>
</tr>
</table>
验证码的引用地方:
<img src="ValidatePage.aspx? ImgWidth=72&ImgHeight=22&Fineness=95&CodeLen=4&FontName=Times New Roman&FontSize=13&FontStyle=3&PosX=4&
PosY=0" alt="图像无法显示" id="SaveCode" onclick="javascript:reloadcode();" style="border: solid 1px white"
onmouseover="this.style.cursor='hand'; " />
可以看到,在输入框右边增加一个图形元素,这个图形元素由ValidatePage.aspx页面动态生成和检验,并且在地址后面增加了很多的参数,这些就是图形码生成所需要的图片高度、宽度、清晰度等。那么ValidatePage.aspx中包含了怎样的处理代码呢?
首先在ValidatePage.aspx页面的Page_Load处理函数中包含了这样的代码:
//获取Request参数
// 获取图片宽度
if (Request["ImgWidth"] != null)
{
try
{
this.m_imgWidth = Int32.Parse(Request["ImgWidth"]);
if (this.m_imgWidth < 16 || this.m_imgWidth > 480)
throw new Exception("图像宽度必须在16到480之间");
}
catch (Exception Ex)
{ throw; }
}
其它获取参数的代码从略。
接下来代码:
// 生成随机验证码
string ValidateCode = CreateValidateCode();
// 生成Bitmap图像
Bitmap bitmap = new Bitmap(this.m_imgWidth, this.m_imgHeight);
// 给图像设置干扰
DisturbBitmap(bitmap);
// 绘制验证码图像
DrawValidateCode(bitmap, ValidateCode);
// 用Session保存验证码
Session["ValidateCode"] = ValidateCode;
// 保存验证码图像,等待输出
bitmap.Save(Response.OutputStream, ImageFormat.Gif);
可以看到,上面的图形元素中通过Request 对象将图形码生成所需要的参数读取过来。然后生成随面验证码,再产生一个Bitmap图像,并设置图像干扰效果,接下来将验证码写入到这个Bitmap图像中,并保存输出到Response 对象,这样就可以显示在注册输入页面了,到此便生成了图形码,但为了进行图形码验证,实际生成的验证码被保存在Session对象中,以便跨页面进行比对(即与验证码文本输入框的值进行比对)
验证码比对验证过程:
// 先判断验证码是否有效,然后再判断用户名与密码是否正确
if (this.txt_Vcode.Value == "" || this.txt_Vcode.Value.ToUpper().Trim() != (string)Session["ValidateCode"].ToString())
{
ClientScript.RegisterStartupScript(Page.GetType(), "", "<script>alert('验证码无效')</script>");
}
下面是相应的函数功能实现:
// 生成随机验证码
private string CreateValidateCode()
{
string ValidateCode = "";
Random random = new Random();
for (int i = 0; i < this.m_codeLen; i++)
{
int n = random.Next(26);
ValidateCode += (char)(n + 65);
}
return ValidateCode;
}
// 干扰图像
private void DisturbBitmap(Bitmap bitmap)
{
Random random = new Random();
for (int i = 0; i < bitmap.Width; i++)
for (int j = 0; j < bitmap.Height; j++)
{
if (random.Next(100) < this.m_imgFineness)
bitmap.SetPixel(i, j, Color.LightBlue);
}
}
// 画出验证码图像
private void DrawValidateCode(Bitmap bitmap, string ValidateCode)
{
Graphics g = Graphics.FromImage(bitmap);
Font font = new Font(this.m_fontName, this.m_fontSize, (FontStyle)(Enum.Parse(typeof(FontStyle), this.m_fontStyle, false)));
g.DrawString(ValidateCode, font, Brushes.Black, m_posX, m_posY);
}
这里的验证码生成函数是引用了随机函数,并将生成结果转换为大写字母,这样,图形码将不区分大小写。这个图形码生成算法,可以根据个人爱好自己编写。
扩展功能:登录界面更换生成验证码。
看到前台代码中有这一段:
<a href="javascript:reloadcode()" title="刷新验证码">更换一张图片</a>
调用了reloadcode()这个函数来重新加载图形验证码,这个无非是等于重新刷新Validate.aspx这个页面而已,这个页面的刷新并不会影响到登录页面刷新,故称为动态加载。
<%--图形码的动态加载--%>
<script type="text/javascript">
var timeMax=6; // 图形码可见时间最大值
var timeCnt=0; // 记数
// 当出现验证码验证时触发此函数开始记时
function CreateListen()
{
var intervalId=setInterval(SetTime,1000);
}
// 判断时间如果在设置的最大时间之后将自动切换图形码
function SetTime()
{
timeCnt+=1;
// 显示当前图形码可用时间
document.getElementById("span_Time").innerText=timeMax-timeCnt+"秒";
if(timeCnt>=timeMax)
{
// 超过可用时间的最大值则更换图形码
reloadcode();
timeCnt=0;
}
}
// 动态生成图形验证码
function reloadcode()
{
document.getElementById("SaveCode").src="ValidatePage.aspx?"+Math.random()+"ImgWidth=72&ImgHeight=22&Fineness=95&CodeLen=4&FontName=Times New Roman&FontSize=13&FontStyle=3&PosX=4&PosY=0";
}
</script>
扩展功能:设置N秒后,动态更换验证码(即保证验证码的时效性,N可设置)
上面的<script>中的功能函数中已包含这段代码了
function CreateListen():开始记时,这个函数是后台执行用户验证后出错次数达到一定次数后出现验证码的时候触发该函数做记时。即检测当前验证码的可用时间。
后台触发该函数的代码:
his.tab_Vilidate.Visible = true;
ClientScript.RegisterStartupScript(Page.GetType(), "", "<script>alert('用户名与密码输错" + i_ErrorCnt.ToString() + "次,请输入验证码');CreateListen();</script>");
i_Cnt = 0;
这里利用后台注册前台js脚本的方法来调用CreateListen函数。关于后台注册前台js脚本我会在另一篇文章详细讲述它们的方法及注意点。
总结一下:今天学习了图形验证码的动态生成、更换验证码、即指定时间内更换验证码等功能。