突然想写点东西,因为知道的东西越来越多,我需要整理了,不然我没法全心全意奔向更热忠的其它技术。头脑里面乱成一团,因为想写的东西太多太多了,都不知道应该从哪里开始。
索性就先不想,通过简单的一个登陆验证机制来引发出其它的扩展知识,并逐步深入,将尽可能多的知识点结合起来,并适当添加示例代码讲解加以巩固,我会尽量将所有知识点结合到源程序中,以后会发布相应的源程序文件。希望自己有更多的时间跟毅力去将这些东西写下来,只是为了跟大家一起分享学习的过程,希望有缘看到这些文章的朋友多多支持。
第一课:登陆验证验证N次后添加验证码验证
目标:登陆时我们常常需要验证码的验证才让用户得以登陆,签于某些用户不喜欢验证码验证登陆且又为了防止爆力破解。所以出现了用户以用户名密码进行验证出错N次后,出现验证码加强验证。出错次数N可设置。
思路: 通过一静态变量来记录验证出错次数,再与自己设置的出错总次数进行比对,如果达到出错次数的,界面中将显示验证码及输入框(即让验证码所在的服务器控件属性visible设置为true),并通过这个visible的属性做为判断需不需要执行验证码验证(当visible为true则验证码验证,当visible为false则不需要验证码验证)。
1、登陆界面
2、出错后界面
这里列出部分代码让读者更好的了解设计思路。具体的代码实例我会在csdn上发布。
前台页面代码:
<table cellspacing="0" cellpadding="0" style="width: 250px; height: 120px">
<tr>
<td class="tdMod" align="right">
用户名:
</td>
<td style="width: 160px">
<asp:TextBox ID="txt_UserName" runat="server" tabindex="1" class="txt_Style"
onblur="CheckUserName()"></asp:TextBox>
<span id="span_Info" style="color:Red; font-size:9pt"></span>
</td>
</tr>
<tr>
<td class="tdMod" align="right">
密码:
</td>
<td style="width: 160px">
<asp:TextBox ID="txt_UserPwd" runat="server" tabindex="2" class="txt_Style" TextMode="Password"></asp:TextBox>
</td>
</tr>
<tr>
<td colspan="2">
<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;">
<input type="text" id="txt_Vcode" runat="server" class="txt_Style" />
</td>
</tr>
<tr>
<td>
</td>
<td>
<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'; "/>
<a href="javascript:reloadcode()" title="刷新验证码">更换一张图片</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td>
</td>
<td align="left">
<asp:CheckBox ID="check_Save" runat="server" Text="记住密码" />
</td>
</tr>
<tr>
<td colspan="2" style="color: Red;">
<asp:Label ID="lbl_Error" runat="server" Text=""></asp:Label>
</td>
</tr>
<tr>
<td align="center" colspan="3">
<asp:ImageButton ID="imgBtn_Login" runat="server" ImageUrl="~/Images/userLogin.jpg"
OnClick="imgBtn_Login_Click" />
</td>
</tr>
</table>
扩展知识:
A、这边验证码的输入框与验证码的图片放在容器<table></table>当中,然后为其属性加上runat="server",这样它就是一个服务器控件并能被后台调用。这个就是我后面要讲的html控件与web控件的区别。
<table id="tab_Vilidate" runat="server" cellpadding="0" cellspacing="0" style="margin: 0; height: 100%; width: 100%" visible="false">
B、这边看到验证码的图片是一个引用地址,没错,这个引用地址就是生成验证码的页面地址。验证码是通过另一个页面生成的一张图片,然后做为地址被登陆页面所引用。我也会有一篇是专门介绍验证码的生成及动态改变验证码图片。
<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'; "/>
后台代码:
定义一个静态变量来记录出错次数,并设置一个只读属性的出错次数参数
private static int i_Cnt;// 登陆出错次数记录
private static readonly int i_ErrorCnt = 2;// 登陆出错次数参数设置
后台登陆的验证事件:
// 登陆验证函数(mocklystone 2009-10-13)
protected void imgBtn_Login_Click(object sender, ImageClickEventArgs e)
{
string str_userName = this.txt_UserName.Text.ToString().Trim();
string str_userPwd = this.txt_UserPwd.Text.ToString().Trim();
DataTable dtLoginInfo = new DataTable();
if (string.IsNullOrEmpty(str_userName))
{
this.lbl_Error.Text = "请输入用户名";
this.lbl_Error.Visible = true;
return;
}
else if (string.IsNullOrEmpty(str_userPwd))
{
this.lbl_Error.Text = "请输入密码";
this.lbl_Error.Visible = true;
return;
}
// 如果用户名与密码都有输入,允许用户输入两次的用户名与密码
else if (this.tab_Vilidate.Visible == false)
{
// DataBaseHelper是放在App_code文件夹中的一个类,IsCheckPass即检测用户名是否正确
if (!DataBaseHelper.IsCheckPass(str_userName, str_userPwd))
{
i_Cnt += 1;
if (i_Cnt < i_ErrorCnt)
{
// 后台注册js脚本到前台
ClientScript.RegisterStartupScript(Page.GetType(), "", "<script>alert('用户名或密码错误')</script>");
}
else
{
this.tab_Vilidate.Visible = true;
ClientScript.RegisterStartupScript(Page.GetType(), "", "<script>alert('用户名与密码输错" + i_ErrorCnt.ToString() + "次,请输入验证码')</script>");
i_Cnt = 0;
}
return;
}
else
{
i_Cnt = 0;
HttpContext.Current.Session["UserName"] = str_userName;
//保存用户名密码到cookie
// 设置 Cookie 信息
HttpCookie cookie = new HttpCookie("USER_COOKIE");
if (this.check_Save.Checked)
{
// 设置用户昵称、密码
cookie.Values.Add("Name", str_userName);
cookie.Values.Add("Pwd", str_userPwd);
// 令 Cookie 永不过期
cookie.Expires = System.DateTime.Now.AddDays(7.0);
// 保存用户的 Cookie
HttpContext.Current.Response.Cookies.Add(cookie);
}
else
{
//Response.Cookies.Clear();
if (Response.Cookies["USER_COOKIE"] != null)
Response.Cookies["USER_COOKIE"].Expires = DateTime.Now;
}
Response.Redirect("Main.aspx");
}
}
//如果输错用户名与密码超过两次就强制输入验证码
else
{
// 先判断验证码是否有效,然后再判断用户名与密码是否正确
if (this.txt_Vcode.Value == "" || this.txt_Vcode.Value.ToUpper().Trim() != (string)Session["ValidateCode"].ToString())
{
ClientScript.RegisterStartupScript(Page.GetType(), "", "<script>alert('验证码无效')</script>");
}
else
{
if (DataBaseHelper.IsCheckPass(str_userName, str_userPwd) == false)
{
ClientScript.RegisterStartupScript(Page.GetType(), "", "<script>alert('用户名或密码错误')</script>");
return;
}
else
{
//保存用户名密码到cookie
// 设置 Cookie 信息
HttpCookie cookie = new HttpCookie("USER_COOKIE");
if (this.check_Save.Checked)
{
// 设置用户昵称、密码
cookie.Values.Add("Name", str_userName);
cookie.Values.Add("Pwd", str_userPwd);
// 令 Cookie 永不过期
cookie.Expires = System.DateTime.Now.AddDays(7.0);
// 保存用户的 Cookie
HttpContext.Current.Response.Cookies.Add(cookie);
}
else
{
if (Response.Cookies["USER_COOKIE"] != null)
Response.Cookies["USER_COOKIE"].Expires = DateTime.Now;
}
Response.Redirect("Main.aspx");
}
}
}
}
用一个大的判断来执行不同的验证,即之前说过的用验证码所在容器的visible属性来做为标志,判断该执行验证码验证。而两段验证代码只存在于说一个加了验证码的验证,一个没加,其它都一样。
扩展知识:
C、这段代码中涉及到以下几个内容,这些我会再发时间写些具体的细节。
1、Session与Cookie存储的差异
2、 Session的几种存储方式及区别
3、Session丢失的原因及解决方案
4、 Cookie的生存周期及安全性
5、 Session的作用域及跨项目的解决方案
6、后台注册js脚本到前台
7、 .net的应用文件夹如:App_Data、App_Code等
8、密码框的赋值
请大家继续关注~~~~~~~~~