Asp.Net 中中的Form验证
1. 网站为什么要验证
要想弄清楚这个问题,先得弄清楚网站的权限问题,有的页面匿名用户就可以看,譬如login页面,help页面等;
有些页面必须有权限才能看,譬如purchase页面;
还有些页面需要更高的权限才能看,譬如admin页面,configuration页面;
有些页面不同的人都可以看,但是不同类型的人看到的内容也不一样。
2. 解释几个名词,说清Form验证
为了解决这样的问题,我们先来解释三个词语
Identity: Who am I? 这个意思是我是谁,就是说通过identity(在asp.net Form验证中是HttpContext.Current.User.Identity.)可以识别当前用户是谁。你可能又有疑问,怎么忽然出来了一个HttpContext.Current.User.Identity,他怎么知道我是谁了,请看下面。
Authentication: This is Who am I? 这个问题是用来解决我是谁的,也就是说用户输入了用户名,密码后,通过Authentication可以确定用户是谁,并且让整个网站知道我是谁,它怎么做到的呢?细心的你可以注意到了FormsAuthentication,它提供了一个静态方法
public static bool Authenticate(string name, string password);
你现在的问题可能是我都没有写到数据库验证的方法,都没有和数据库连接,我就传一个name和password,它就知道我是合法用户了?扯淡吧?的确是扯蛋,谁也没有通天的本领,任何事情都是一步一步来的。我们看一下这个方法的注释:
// Validates a user name and password against credentials stored in the configuration
// file for an application.
验证一个存储在web.config中对应于credentials这个节点中的用户名和密码,也就是说这个方法只是用来验证web.config中的用户名和密码,一般情况下,我们不会把用户名和密码存在那里,所有这个方法对于我们来说应该会比较少用。
那么真正是怎么验证的呢?肯定要访问数据库,和其中的数据进行比较,看是否是合法用户。既然这个Authenticate不能被我们所用,可以写一个我们自己的Authenticate方法,到数据库中进行验证,一般来说如果验证成功了的话,还需要做第三步,也就是下面要说的。
Authorization: What Can I do in this site? 这个意思是说我在这个网站的到底能够做些什么事情,换句话说就是有多少权限? 这个在网站中一般也是用户在Authenticate成功后,需要取出这个用户的所有权限,一般需要访问权限表,这样验证过程算是完成了。
既然90%以上的页面都需要进行验证,那么我么可以考虑加一个基类BasePage,所有需要验证的Form都继承这个基类,我们在基类的OnLoad方法中去进行做验证,这样就省了很多事情。
3. 还漏掉了那些事情
其实漏掉的事情还是很多的:
第一, 既然所有的页面都要验证,否则就直接近login页面,现在还不行,请在web.config 中的<system.web>节点中加入
<authentication mode="Forms">
<forms loginUrl = "Lonin.aspx" name = ".ASPXFORMSAUTH"/>
</authentication>
第二, 有些页面不要验证怎么办,请在web.config 中加入
<location path="pagePath ">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
第三, 如果我要记录住用户名,方便下次登录,或者甚至记住用户名和密码,下次自动登录,怎么做?
下面是一个实例,我们可以在写自己的Authenticate的方法的时候处理
///验证成功后我们讲用户名和密码已经用户的类别存在cookie中,保存期限是30天
public bool Authenticate(string username, string password)
{
UserInfo u = GetUserFromDB(username,password);
If(u==null){
Return false;
}
Else{
WrieCookie(u);
Return true;
}
}
Public void WriteCookie(UserInfo u)
{
string m_userData = u.UserID.ToString()+","+u.UserName +","+u.UserType.ToString();
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
"WebbUser",
System.DateTime.Now,
System.DateTime.Now.AddDays(30),
false,
m_userData,
"/");
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpContext.Current.Response.Cookies.Add(new HttpCookie("WebbUser", encTicket));
}
虽然我们可以将这个Cookie保存在客户端30天,但是不用它保存了也没有用,也就是说我们需要在验证的时候先判断该用户是不是不需要登录的,如果是,那么直接返回true。怎么做呢?
protected UserInfo GetCookie()
{
UserInfo u = null;
if(User.Identity.IsAuthenticated)
{
string m_userData;
FormsIdentity id = (FormsIdentity)User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
m_userData = ticket.UserData;
if(m_userData!=null)
{
//将获取的user数据写到UserInfo中
u = SetUserData(m_userData);
}
}
Return u;
}
private UserInfo SetUserData(string m_Data)
{
string[] m_string = m_Data.Split(new char[]{','});
UserInfo u = new UserInfo();
if(m_string.Length==3)
{
u.UserID = Convert.ToInt64(m_string[0]);
u.UserName = m_string[1];
u.UserType = PageHelper.ConvertToUserTypes(m_string[2]);
}
Return u;
}
现在我们在修改一下Authenticate方法
public bool Authenticate(string username, string password)
{
UserInfo u = GetCookie();
If(u!=null){
Return true;
}else{
GetUserFromDB(username,password);
If(u==null){
Return false;
}
Else{
WrieCookie(u);
Return true;
}
}
}
这样基本上就完成了整个Form验证, 当然使用过程自然还有不少细节问题,也不是一两句话可以说得清的,遇到问题多思考,看看google,找到答案应该也会很快。