阅读文章

BS结构之单人登入

[日期:2008-02-20] 来源:  作者: [字体: ]

     最近,公司有个BS结构的项目的deadline临近,但是在处理“单人登入,即时登出”时,一直没有找到一个比较理想的方案,因为使用这个项目的客户群是警察叔叔,如果在登入登出的时候“卡壳”,那我不要混了,公司也得玩完。
  
  防止同一帐号多人同时登入的一般解决方案,无非就是把登入时的用户ID保存在数据库中,或application中,或cache中,然后在用户登出的时候删除用户ID,但是要删除用户ID还是有点棘手。
  
  不管用户ID保存在哪里,当我点击“登出”button的时候,都需要我们通过一个事件去告诉系统,用户ID现在该清除了。假设我把用户ID保存到cache中,并设置cache的销毁时间为Session的结束时间,Session一结束,cache跟着销毁,这样设计也合情合理。
  
  如果您一相情愿的认为使用者都会去点击“登出”button,那就大错特错了,我平常也喜欢直接X掉IE,懒得去点那小小的“登出”button。可能有人马上会说,可以用js来判断浏览器是否关闭了呀!没错,js很容易判断IE是否关闭。但是,如果电源插头不小心被你那急着上WC的,有点肾亏同事绊掉了呢?那些警察叔叔就只能干等着session自动过期,如果Timeout设置得稍微长一点,客户那边马上电话不断,然后,公司技术员不得不restart服务器。公司以前有些系统就如此,老要restart服务器,我是看在眼上,痛在心里。如果还有人要说,俺有UPS,怕什么,那我也不好再说什么了^-^
  
  我想,如果单靠JS来判断,“年长日久,难免发生意外”,怎么办呢?能不能让服务器自己来判断呢?这还问,当然可以,把session的Timeout的值设置小点,不就得了!如果只个值太小,等警察叔叔抽完一根烟,再使用系统的时候,系统马上提示;“您的会话已经过期,请重新登录“。如果老是要登入,那就玩不下去了。能不能想个办法,不让系统会话很快过期,又能在一个合适的时间让系统自动注销呢?可能没等我说完,马上有人会说,在client端适时的激活服务器,不就得了。您说的没错,我也是这么想的。
  
  那我就按您的思路去实现吧;
  
  首先设置web.config文件;
  
  <sessionState mode="StateServer" cookieless="false" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" timeout="1"/>
  
   然后在登入事件中加入;
  
   ///同一时间点,检查登录用户ID的唯一性
  
  ///</summary>
  
   ///<param name="strZh">用户ID </param>
  
   ///<returns></returns>
  
   private bool ckeckUserOnlyOne(string strZh)
  
   {
  
   string strTempZh=strZh;
  
   if (Cache[strZh] == null)
  
   {
  
   TimeSpan SessTimeout = new TimeSpan(0,0,System.Web.HttpContext.Current.Session.Timeout,0,0);
  
   HttpContext.Current.Cache.Insert(strTempZh,strTempZh,null, DateTime.MaxValue, SessTimeout, System.Web.Caching.CacheItemPriority.NotRemovable, null);
  
   return true;
  
   }
  
   else
  
   return false;
  
  }
  
   然后在登出事件加入;
  
   try
  
   {
  
   Session.Abandon();
  
   System.Web.HttpContext.Current.Session.RemoveAll();
  
   Cache.Remove("用户ID");
  
   }
  
   catch (Exception ex)
  
   { }
  
  主角登场了,在每个页面引入下面的JS;
  
  <script>
  
  var step=0;
  
   function myRefresh()
  
   {
  
   var httpRequest = new ActiveXObject("microsoft.XMLhttp");
  
   httpRequest.open("GET", "delSession.ASPx", false);
  
   httpRequest.send(null);
  
   step ++;
  
   if(step <2)//注意2
  
   {
  
   setTimeout("myRefresh()",30*1000); //30秒
  
   }
  
   }
  
   myRefresh();
  
  </script>
  
   最后,别忘记项目的Root目录下new一个delSession.ASPx文件,然后在她的page_laod方法中写上Response.Expires = -1;
  
   按ctr+F5,期间不要激活,是不是在2分种之后,您的系统提示会话过期了呢?哈哈
  
  由于代码比较简单,就不一一解释了,讲一下思路;
  
  首先在未继续激活会话的情况下,设置她的生命周期为一分钟,我感觉一分钟刚好,(哎,自古红颜多薄命!)
  
  然后,在判断此时userID 没有登入时,把user ID 保存在cache中,且cache的过期时间为SessTimeout,也就是说当前会话一销毁,cache也就跟着殉情。(烈女啊!)
  
   又然后,在“登出“事件中注销当前会话,清除cache集合中的当前user ID,这样就可以在点击“登出”button时,及时清除对应的cache项。
  
   再然后,在页面的JS中通过setTimeout("myRefresh()",30*1000)方法,不断请求激活服务器,直至玩不下去,注意并没有获取响应。
  
   再然后,在被请求的页面中设置自己不使用“页面输出缓存”,以免无法激活当前会话。
  
  现在已经是0:16分了,长沙的冬天晚上比较寒冷,刚刚泡的大麦红茶已经凉了,再罗嗦一句,可以修改“step <2”和setTimeout("myRefresh()",30*1000),把这些参数放到配置文件中,可以随便修改,直到找到最佳平衡点,祝大家好运!
  
  后记;
  
   言多必失,说得不妥当之处,还望多多指教!
  
    


阅读:
录入:blue1000

评论 】 【 推荐 】 【 打印
上一篇:如何去集合网站内所以的后台,去实现统一的管理,统一的权限
下一篇:群发UDP的性能测试
相关文章      
本文评论
发表评论


点评: 字数
姓名:

  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款