您的位置:首页 > 编程语言 > ASP

ASP.Net用户验证的实现

2010-03-10 08:29 183 查看
在Web程序中,我们知道,服务器端和IE客户端不是常连的,只有访问时才连接,一旦页面加载完后,这个连接就会断开,也就是说,访问页面A后,再访问页面B时,服务器端是不知道你已经访问过页面A了,甚至对于同一个页面,服务器端也不会去记录你的访问,每次都会重新实例话访问的页面。

这就带来一个问题,如果实现我访问了Login.aspx登陆页并且登陆后,就可以在其它页面中访问,如果没有登陆,在访问其它页面时就会自动跳转到登陆页面让用户重新登陆呢?

思路一:

我们知道服务器端一般不保存客户信息,但是有一个对象,session是可以保存的,当一个用户访问系统后,服务器端就会为其分配一个session,当再访问页面时,保存在session中的对象还可以取出来。这个典型应用就是购物篮,在各个页面切来切去,选择要购的东东,然后一起结算,这个过程就是将每次选择的信息保存在session中。

那么,我们就以此想到,我们可以将用户的信息也记录在session中:

Protected void Login_click(object sender,EventArg e)

{

//验证客户信息

//取得用户标识 UserGuid

Session[“UserGuid”] = UserGuid;

}

然后当注销时:

Protected void Logout_click(object sender,EventArg e)

{

Session.clear();

}

然后我们写一个基类,来判断是否登陆过,如果没有登陆过直接跳转到登陆页面:

If (Session[“UserGuid”] == null)

Response.Redirect(“login.aspx”);

这样也就基本实现了我们的功能,但是问题来了:

1. 这个session服务器不会永久帮我们保存着,它会有一个有效期,默认是20分钟,如果超过这个时间,就会失效,这个时间可以在<sessionState timeout="20"/>,也就是说在20分钟内用户必须登陆一次,否则将会失效。

2. Session是保存在服务器中的内存中,如果说这个Application重启了,比如说我们更改了一个dll,或重启了IIS服务,那么所有的Session就都会丢失,所有IE端都必须要重新登陆,这样很不友好。其实ASP.Net提供了,可以将Session存在其它机器上,或数据库,方式只需要改写下配置文件,如下:

<sessionState mode="StateServer"

stateConnectionString="tcpip=127.0.0.1:42424"

sqlConnectionString="data source=127.0.0.1;Integrated Security=SSPI"

cookieless="false" timeout="30"/>

期中,保存Session的机器,需要启动一项服务才行实现:



3. 现在session问题也解决了,基本也就可以实现我们的功能了,但是所有页面都必须继续一个基类来进行验证判断,而且session由于存内存的,其稳定性相对比较差,所以在实现过程中,还是会出现莫名其妙地强迫某个用户登陆一下。

我们再看看另一种办法吧:

思路二:

从web程序中配置文件Web.config中,我们可以看到<authentication mode="Windows" />这个结点,可以得知,在ASP.Net中共有3种认证方式(以下从MSDN中解释):

Mode

验证方式

Windows

将 Windows 验证指定为默认的身份验证模式。将它与以下任意形式的 Microsoft Internet 信息服务 (IIS) 身份验证结合起来使用:基本、摘要、集成 Windows 身份验证 (NTLM/Kerberos) 或证书。在这种情况下,您的应用程序将身份验证责任委托给基础 IIS。

Forms

将 ASP.NET 基于窗体的身份验证指定为默认身份验证模式。

Passport

将 Microsoft Passport Network 身份验证指定为默认身份验证模式。

None

不指定任何身份验证。您的应用程序仅期待匿名用户,否则它将提供自己的身份验证。

Windows验证方式,顾名思义就是利用windows来认证,配置的帐号信息就效验IIS来管理,需要登陆时,将会出现这样的信息:



而Passport使用情况比较少,所以本章内容主要讲Forms验证。

前面讲到,我们将登陆信息保存到了服务器端,那么,我们想能否将登陆信息保存到客户端,这样,服务器即使在做更们,也不会再丢失我们的登陆信息了。

答案是可以的,ASP.Net提供了Form认证,就是将登陆信息保存到客户端Cookie中,然后访问其它页面时,根据这个Cookie来验证。

方法这样,首先在web.Config中配置:

<authentication mode="Forms">

<forms name="userlogin_EpontOA7" loginUrl="login.aspx" protection="All" timeout="120"/>

</authentication>

在这里,定义好loginUrl:登陆页面,系统中一旦认证失败就会自动跳转到这个页面中,也就无须再写什么基类来处理了。

然后登陆时:

protected void btnLogin_Click(object sender, EventArgs e)

{

//验证用户

//获取用户Guid

FormsAuthentication.RedirectFromLoginPage(UserGuid,false);//将用户标识写入Cookie中。

RefreshSessionFormUserGuid(UserGuid) //根据用户Guid,初使化session

}

就这样,IE端的用户就可以通过了认证,就相当于手里拿到一张系统认可的身份证。

注销时:

protected void btnLogOut_Click(object sender, EventArgs e)

{

//退出

FormsAuthentication.SignOut();

//清除所有的session

HttpContext.Current.Session.Clear();

HttpContext.Current.Session.RemoveAll();

Response.Redirect("Login.aspx");

}

这样,手里拿的这张身份证系统就不认可了,再访问系统中的页面,系统就会自动跳转到登陆页面。

好了,认证工作完成了,感觉要比原来的简单许多。

但问题来了,这个身份证可以不过期,那么Session会过期,一旦Session过期了,那么,通过Session[“”]取值的,就会取到一个null值。这就是说,我们得当Session过期时,但身份证不过期时,自动将Session中的值再刷出来,可以采用以下方法:

Public class Global : System.Web.HttpApplication

protected void Session_Start(object sender, EventArgs e)

{

string UserGuid = Context.User.Identity.Name; //取出Cookie中的身份证号

if (UserGuid!= "")

RefreshSessionFormUserGuid(UserGuid) //根据用户Guid,初使化session

}

这样整个系统就转起来了。但现在要加个功能,就是某些页面不需要认证就能访问,比如脚本升级页面,有可能更新了某个版本后,登陆页面都无法访问了,这里要升级时需要直接访问,那么相当于在认证过程中,需要排除这个页面,可以在Web.Config中加上这段话:

<location path="ABC/Test.aspx">

<system.web>

<authorization>

<allow users="*" />

</authorization>

</system.web>

</location>

这样ABC/Test.aspx这个页面访问里就不需要验证了。

回头看一下,相比而言,思路二更加方便了。

在第二种方法中,还有一个功能,就是我们看到在配置验证方式时有一个<forms name="”。。。   这个name选项,由于在同一台服务器上可能会存在多个应用服务,每个应用服务需要独立的Cookie,这里的名字就是这个标识。

我们知道,为了安全性,这个保存在Cookie中的值,肯定是加密过的,如果我们将两个系统的Cookie加密方式与验证的name改成相同,同时保存在Cookie中的身份值意义都兼容时,我们就可以实现两个系统的单点登陆了,具体的单点登陆的配置方式,请搜索相应的专题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐