用户未登录或Session超时时重定向到登录页,不那么简单!

   在网站开发中,我们经常有这样的场景出现:
   情景1:对未登录的用户或没有权限的用户,当其想访问某个受限网页时,系统要能够自动转到登录页面.
   情景2:对于用Session保存用户状态的情况还有这样一种需求,当用户的Session已超时时,用户再想执行操作时,也要将其转到登录页面.
   在asp.net中,要实现上述的功能容易吗?有人会说:"这太容易了,可以通过下面两种方式实现".
   方法一:直接调用asp.net中的Response.Redirect方法实现  
Response.Redirect("login.aspx");
   方法二:通过asp.net调用js脚本来实现
Response.Write("<script>window.location='login.aspx';</script>");
   然而,真的这么简单吗?对于情景1,两种方法的确都可以实现.在网站的后台管理中,我们经常把管理功能放在一个框架集(或者用iframe来实现),左边是操作功能,右边是具体的操作页面.这时候,对于两种方法,都会出现是在左边或右边框架中打开login.aspx页,而不是我们想要的那种在顶层窗口中打开login.aspx页的情况.出现这种情况,第一种方法已经无能为力了,因为其只能在当前操作窗口中进行转向.对于第二种方法,有人说我可以修改一下就可以了嘛:  
Response.Write("<script>window.parent.location='login.aspx';</script>");
这样,就可以保证在父窗口中打开登录页了.不过,我们的代码要同时考虑到情景1和情景2的情况,在情景1中,上边那段代码会报错,因为其没有父窗口嘛.可能有人已经急不可待地说,这有什么难的,我再修改成下面这样不就可以了吗?
Response.Write("<script>window.top.location='login.aspx';</script>");
   看起来,对于情景1和情景2两种情况来说,这种写法已经可以解决这个问题了。但真的是这样吗?我们一般把判断用户是否登录放在Page_Load事件中,当用户未登录,没有权限或session超时时,就执行上面的代码,让其转到登录页.而在Page_Load事件中,我们还要经常做一些跟用户Session相关的操作.举一个最简单的例子,当用户未登录或session超时时,我们将其转向登录页,当用户已经登录时,我们将用户的信息显示在页面中.这时如果我们调试程序,呈现session超时的情景(可以通过命令行下iisreset命令重启iis来模拟),就会发现出现异常.出现异常的原因是当执行Response.Write时程序会再次向服务器回传,触发Page_Load事件,这时Session已丢失,所以写在Page_Load中的取Session的代码会产生异常.
   经过研究,我想出了解决办法:
   那就是先使用Response.Redirect转向一个中间页,比如Nologin.htm,再在这个中间页的onLoad事件中执行转向到登录页的javascript代码:  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    
<title></title>
</head>
<script type="text/javascript">
function Redirect()
{        
    window.top.location 
= "login.aspx";
}

</script>
<body onload="Redirect();">
</body>
</html>
  这样就能适应前面所说的所有场景了.
  大家可能注意到了我这个html页面的<title></title>标记之间没有内容.为什么呢?如果有标题的话,你执行完转向之后,会在浏览器的"后退"按钮的下拉列表中看到对应的标题,也就是说用户会知道我们通过中间页进行了中转.如果没有标题的话,就看不我们中转的那个页,就和直接转到登录页一样.
  通过这个问题的解决可以发现,多想一些,想全面一些对做程序有多么重要!

  
posted @ 2007-12-13 18:05  John Liu  阅读(8549)  评论(55编辑  收藏  举报