其实,在asp.net中,我们有更好的解决方案,那就是通过Forms身份验证,从而对用户进行授权,这种方法可以轻松的保持用户的登录状态(如果用户想这样),便捷的用户授权配置,增强的安全性等好处。废话不再多说,下面我们来做一个简单的用户身份验证。
在做例子之前,我们先定义如下用户类,类名为SampleUser,代码如下:
public partial class SampleUser
{
string username;
public string UserName
{
get { return username; }
set { username = value; }
}
string userpwd;
public string UserPWD
{
get { return userpwd; }
set { userpwd = value; }
}
public override bool Equals(object obj)
{
SampleUser other = obj as SampleUser;
if (other == null || other.UserName != this.UserName)
return false;
return true;
}
}
public partial class SampleUser
{
public static List<SampleUser> userList = new List<SampleUser> {
new SampleUser() { UserName = "01", UserPWD = "123"},
new SampleUser() { UserName = "02", UserPWD = "123" },
new SampleUser() { UserName = "03", UserPWD = "123" },
new SampleUser() { UserName = "04", UserPWD = "123" },
};
public static SampleUser GetUser(string userName)
{
return userList.Find(u=>u.UserName == userName);
}
}
在类SampleUser中,定义了UserName和UserPWD两个字段,分别用来存储用户的登录名和密码信息。在SampleUser类的另一部分中,我们提供了一个用户的静态类表,用来代替存储在数据库中的用户信息,提供一个方法GetUser,用来获取用户信息。
在这个例子中,我们演示用户必须进行登录才能访问网站的资源,如果没有登录,则将用户导航到login.aspx页面中。
第一步,在web.config中添加配置信息,说明网站要使用Forms身份验证,并指定登录页面和默认登录成功后的跳转页面,然后指定拒绝未登录用户的访问,代码如下:
<authentication mode="Forms">
<forms loginUrl="~/Login.aspx" defaultUrl="~/Default.aspx" />
</authentication>
<authorization>
<deny users="?"/>
</authorization>
完成这一步后,我们再打开Default.aspx页面,在没有登录的情况下,页面会被导航到Login.aspx页面,我们的第一步的目的已经达到了。
第二步,完成Login.aspx的页面逻辑。在页面中添加两个TextBox控件,用来输入用户名和密码;添加一个CheckBox控件,用来选择是否保持登录状态;添加一个Button控件,响应用户的登录操作。相应的代码如下:
<fieldset>
<legend>用户登陆</legend>
<div>
用户名:<asp:TextBox ID="txtUserID" runat="server" Width="150" /><br /><br />
密 码:<asp:TextBox ID="txtUserPWD" runat="server" TextMode="Password" Width="150" /><br /><br />
<asp:CheckBox ID="cbSaveUserName" runat="server" Checked="true" Text="保持登录状态" />
</div><br />
<asp:Literal ID="ltMessage" Text="" runat="server" Visible="false" />
<br />
<p>
<asp:Button ID="btnLogin" Text="登陆" runat="server" OnClick="btnLogin_Click" />
</p>
</fieldset>
接下来完成后台代码,添加登陆按钮的后台处理方法:对用户名和密码进行验证,如果验证通过,则为用户名创建一个身份验证票据,并将其添加到响应的Cookie中。代码如下:
protected void btnLogin_Click(object sender, EventArgs e)
{
string userID = this.txtUserID.Text.Trim();
string userPWD = this.txtUserPWD.Text.Trim();
SampleUser userEx = SampleUser.GetUser(userID);
if (userEx == null)
{
ltMessage.Text = "用户不存在!";
ltMessage.Visible = true;
return;
}
if (userEx.UserPWD != userPWD)
{
ltMessage.Text = "用户名或密码错误,请重新输入!";
ltMessage.Visible = true;
return;
}
//添加票据,并将用户导航到默认页面
FormsAuthentication.RedirectFromLoginPage(userEx.UserName, this.cbSaveUserName.Checked);
}
完成这一步后,我们就已经完成了简单Froms验证的功能。运行程序,你会发现,这里存在一个问题!!!
你发现了吗?当我们被导航到login.aspx时,这个页面的样式丢失了!这是因为我们对整个网站的资源进行了访问限制,如果没有登陆,用户不仅无法访问.aspx页面,甚至连css文件、js文件都无法访问。显然,这不是我们想要的,因为这些资源并不是敏感的资源。在通常情况下,我们只希望对部分文件夹中的文件进行验证访问限制,而不是整个网站,例如,我们允许只对User文件夹下的页面进行访问限制,因为这个文件夹中存放的是用户的私人信息,这些信息是敏感的。这该如何实现呢?
为了完成演示分目录验证,我们在项目中添加一个User文件夹,并添加UserInfo.aspx、 UserLogin.aspx两个页面。UserInfo.aspx用来展示用户信息,它的业务逻辑我们不是我们关心的,UserLogin.aspx页面用来让用户登陆,代码跟Login.aspx页面几乎完全相同。
第一步:修改Web.config文件,允许匿名用户访问系统资源。
<authorization>
<allow users="?"/>
</authorization>
第二步:在User文件夹下添加一个Web.config文件,修改代码,拒绝匿名用户访问该文件夹下的资源。
<authorization>
<deny users="?"/>
</authorization>
完成这两步后,我们访问UserInfo.aspx时,如果没有登陆,则会被导航到~/User/UserLogin.aspx页面,当登陆后,又会被导航到~/User/UserInfo.aspx页面。这个时侯,我们的登陆页面样式并没有丢失,这说明我们的配置文件起作用了。
接下来,我们想在UserInfo.aspx页面中显示出已登陆用户的用户名和密码(这里完全是为了演示如何获取登陆用户数据才这样做的,通常用户的密码是不会展示的)。在进行登陆后,用户的票据信息被加密保存在Cookie中,这个票据中,有已登录用户的名称信息,我们通过获取票据中的用户名,即可获取到完整的用户信息。
为了显示用户信息,我们在页面中放置两个Label控件,代码如下:
<h2>
<p>用户名:<asp:Label ID="lblUserName" Text="" runat="server" /></p>
<p>密 码:<asp:Label ID="lblUserPWD" Text="" runat="server" /></p>
</h2>
然后,我们在页面的Load方法中,获取并展示用户信息:
if (this.Context.User != null && this.Context.User.Identity != null && this.Context.User.Identity.IsAuthenticated)
{
SampleUser user = SampleUser.GetUser(this.Context.User.Identity.Name);
if (user != null)
{
this.lblUserName.Text = user.UserName;
this.lblUserPWD.Text = user.UserPWD;
}
}
再次运行我们的代码,当用户登陆后(如果保持登陆状态,即使关掉并重新打开浏览器),我们都可以获取到已登录用户的Name,从而获取用户的对象。
如果要退出登陆,我们只需要删除保存在Cookie中的票证信息即可,这个功能Forms验证已经帮我们完成,代码很简单:
FormsAuthentication.SignOut(); //退出登陆
在本文中,没有涉及到角色的验证,这是因为通过在配置文件中指定角色这种方法并不够灵活,如果角色是可以在程序中维护的,那么我们在这里的指定就形同虚设了。感兴趣的朋友可以自行学习,也并不复杂。在本文的结尾,附上详细的Forms验证在Web.config中的配置说明:
<forms
name="name"
loginUrl="URL"
defaultUrl="URL"
protection="[All|None|Encryption|Validation]"
timeout="[MM]"
path="path"
requireSSL="[true|false]"
slidingExpiration="[true|false]">
enableCrossAppRedirects="[true|false]"
cookieless="[UseUri|UseCookie|AutoDetect|UseDeviceProfile]"
domain="domain name"
ticketCompatibilityMode="[Framework20|Framework40]">
<credentials>...</credentials>
</forms>
credentials:允许选择在配置文件中定义名称和密码凭据。 您还可以实现自定义的密码架构,以使用外部源(如数据库)来控制验证。