首页 php教程 php手册 (转贴)一套.net窗体身份验证方案(解决了防止用户重复登陆,sessio

(转贴)一套.net窗体身份验证方案(解决了防止用户重复登陆,sessio

Jun 06, 2016 pm 08:01 PM
.net 方案 窗体 解决 身份 防止 验证

http://blog.csdn.net/johnsontj/articles/324369.aspx 一. 设置 web.config 相关选项 先启用窗体身份验证和默认登陆页,如下。 authenticationmode="Forms" formsloginUrl="default.aspx"/forms /authentication 设置网站可以匿名访问,如下 authorization

http://blog.csdn.net/johnsontj/articles/324369.aspx

 

一.      设置web.config相关选项 

 

先启用窗体身份验证和默认登陆页,如下。

 

 

       

 

 

设置网站可以匿名访问,如下

 

 

           

 

 

 

 

 

然后设置跟目录下的admin目录拒绝匿名登陆,如下。注意这个小节在System.Web小节下面。

 

     

 

       

 

           

 

              

 

           

 

       

 

 

把http请求和发送的编码设置成GB2312,否则在取查询字符串的时候会有问题,如下。

 

 

设置session超时时间为1分钟,并启用cookieless,如下。

 

 

为了启用页面跟踪,我们先启用每一页的trace,以便我们方便的调试,如下。

 

 

 

二.      设置Global.asax文件

 

处理Application_Start方法,实例化一个哈西表,然后保存在Cache里

 

    protected void Application_Start(Object sender, EventArgs e)

 

    {

 

       Hashtable h=new Hashtable();

       Context.Cache.Insert("online",h);

}

    在Session_End方法里调用LogoutCache()方法,方法源码如下

 

/// 

    /// 清除Cache里当前的用户,主要在Global.asax的Session_End方法和用户注销的方法里调用      /// 

    public void LogoutCache()

   {

 

      Hashtable h=(Hashtable)Context.Cache["online"];

       if(h!=null)

       {

           if(h[Session.SessionID]!=null)

           h.Remove(Session.SessionID);

           Context.Cache["online"]=h;

       }

}

 

三.      设置相关的登陆和注销代码

 

登陆前调用PreventRepeatLogin()方法,这个方法可以防止用户重复登陆,如果上次用户登陆超时大于1分钟,也就是关闭了所有admin目录下的页面达到60秒以上,就认为上次登陆的用户超时,你就可以登陆了,如果不超过60秒,就会生成一个自定义异常。在Cache["online"]里保存了一个哈西表,哈西表的key是当前登陆用户的SessionID,而Value是一个ArrayList,这个ArrayList有两个元素,第一个是用户登陆的名字第二个元素是用户登陆的时间,然后在每个admin目录下的页刷新页面的时候会更新当前登陆用户的登陆时间,而只admin目录下有一个页打开着,即使不手工向服务器发送请求,也会自动发送一个请求更新登陆时间,下面我在页面基类里写了一个函数来做到这一点,其实这会增加服务器的负担,但在一定情况下也是一个可行的办法.

 

/// 

 

       /// 防止用户重复登陆,在用户将要身份验证前使用

       /// 

       /// 要验证的用户名字

       private void PreventRepeatLogin(string name)

       {

           Hashtable h=(Hashtable)Cache["online"];

           if(h!=null)

           {

              IDictionaryEnumerator e1=h.GetEnumerator();

 

              bool flag=false;

 

              while(e1.MoveNext())

              {    

                  if((string)((ArrayList)e1.Value)[0]==name)

                  {

                     flag=true;

 

                     break;

                  }

              }

              if(flag)

              {

                  TimeSpan ts=System.DateTime.Now.Subtract(Convert.ToDateTime(((ArrayList)e1.Value)[1]));

                  if(ts.TotalSeconds

                     throw new oa.cls.MyException("对不起,你输入的账户正在被使用中,如果你是这个账户的真正主人,请在下次登陆时及时的更改你的密码,因为你的密码极有可能被盗窃了!");

                  else

                     h.Remove(e1.Key);    

              }

           }

           else

           {

              h=new Hashtable();

           }

           ArrayList al=new ArrayList();

           al.Add(name);

           al.Add(System.DateTime.Now);

           h[Session.SessionID]=al;

           if(Cache["online"]==null)

           {

              Context.Cache.Insert("online",h);

           }else

              Cache["Online"]=h; 

    }

 

用户注销的时候调用上面提到LogoutCache()方法

 

四.      设置admin目录下的的所有页面的基类

 

using System;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.HtmlControls;

using System.Collections;

namespace oa.cls

{

    public class MyBasePage : System.Web.UI.Page

    {

       /// 

       /// 获取本页是否在受保护目录,我这里整个程序在OA的虚拟目录下,受保护的目录是admin目录

       /// 

       protected bool IsAdminDir

       {

           get

           {

              return Request.FilePath.IndexOf("/oa/admin")==0;

           }

       }

 

       /// 

       /// 防止session超时,如果超时就注销身份验证并提示和转向到网站默认页

       /// 

       private void PreventSessionTimeout()

       {

           if(!this.IsAdminDir) return;

           if(Session["User_Name"]==null&&this.IsAdminDir)

           {   

 

             System.Web.Security.FormsAuthentication.SignOut();

 

              this.Alert("登陆超时",Request.ApplicationPath)

           }

       }

       /// 

 

       /// 每次刷新本页面的时候更新Cache里的登陆时间选项,在下面的OnInit方法里调用.

       /// 

       private void UpdateCacheTime()

       {

           Hashtable h=(Hashtable)Cache["online"];

           if(h!=null)

           {

              ((ArrayList)h[Session.SessionID])[1]=DateTime.Now;

           }

 

           Cache["Online"]=h;

 

       }

 

       /// 

       /// 在跟踪里输出一个HashTable的所有元素,在下面的OnInit方法里调用.以便方便的观察缓存数据

       /// 

       /// 

       private void TraceValues( Hashtable myList) 

       {

           IDictionaryEnumerator myEnumerator = myList.GetEnumerator();

           int i=0;

           while ( myEnumerator.MoveNext() )

           {

              Context.Trace.Write( "onlineSessionID"+i, myEnumerator.Key.ToString());

              ArrayList al=(ArrayList)myEnumerator.Value;

              Context.Trace.Write( "onlineName"+i, al[0].ToString());

              Context.Trace.Write( "onlineTime"+i,al[1].ToString());

              TimeSpan ts=System.DateTime.Now.Subtract(Convert.ToDateTime(al[1].ToString()));

               Context.Trace.Write("当前的时间和此登陆时间间隔的秒数",ts.TotalSeconds.ToString());

              i++;

           }

       }

 

       /// 

       /// 弹出信息并返回到指定页

       /// 

       /// 弹出的消息

       /// 指定转向的页面

       protected void Alert(string msg,string url)

       {

           string scriptString = "<script>alert(/""+msg+"/");location.href=/""+url+"/"</script>";

           if(!this.IsStartupScriptRegistered("alert"))

              this.RegisterStartupScript("alert", scriptString);

       }

 

       /// 

       /// 为了防止常时间不刷新页面造成会话超时,这里写一段脚本,每隔一分钟向本页发送一个请求以维持会话不被超时,这里用的是xmlhttp的无刷新请求

       /// 这个方法也在下面的OnInit方法里调用

       /// 

       protected void XmlReLoad()

       {     

           System.Text.StringBuilder htmlstr=new System.Text.StringBuilder();

           htmlstr.Append("

           htmlstr.Append("function GetMessage(){");

           htmlstr.Append("  var xh=new ActiveXObject(/"Microsoft.XMLHTTP/");");

           htmlstr.Append("  xh.open(/"get/",window.location,false);");

           htmlstr.Append("  xh.send();");

           htmlstr.Append("  window.setTimeout(/"GetMessage()/",60000);");

           htmlstr.Append("}");

           htmlstr.Append("window.onload=GetMessage();");

           htmlstr.Append("       ");

           if(!this.IsStartupScriptRegistered("xmlreload"))

              this.RegisterStartupScript("alert", htmlstr.ToString());

       }

       override protected void OnInit(EventArgs e)

       {

 

           base.OnInit(e);

           this.PreventSessionTimeout();

           this.UpdateCacheTime();

           this.XmlReLoad();

           if(this.Cache["online"]!=null)

           {

              this.TraceValues((System.Collections.Hashtable)Cache["online"]);

           }

       }

    }

}

 

五.      写一个自定义异常类

 

首先要在跟目录下写一个错误显示页面ShowErr.aspx,这个页面根据传递过来的查询字符串msg的值,在一个Label上显示错误信息。

 

 

using System;

namespace oa.cls

{

    /// 

    /// MyException 的摘要说明。

    /// 

    public class MyException:ApplicationException

    {

           /// 

           /// 构造函数

           /// 

           public MyException():base()

           {

 

           }

           /// 

           /// 构造函数

           /// 

           /// 异常消息

           public MyException(string Message):base(Message)

           {

               System.Web.HttpContext.Current.Response.Redirect("~/ShowErr.aspx?msg="+Message);

           }

 

           /// 

           /// 构造函数

           /// 

           /// 异常消息

           /// 引起该异常的异常类

           public MyException(string Message,Exception InnerException):base(Message,InnerException)

          {

           }

       }

} 

 

 

六.总结

我发现在Session里保存的值,比如session["name"]是没有任何向服务器的请求达到1分钟后就会自动丢失,但是session ID是关闭同一进程的浏览器页面后达1分钟后才会丢失并更换的,因为只要你开着浏览器就会有session ID,无论是在url里保存还是在cookies里。不知道这个结论对不对,反正我在设置了session的timeout为1分钟后,session["name"]的值已经没有了,可是SessionID还是旧的,Global.asax里的Session_End里的代码也没有执行,而身份验证票据也没有丢失。我不知道这三者之间的关系是怎样的,谁先谁后,好像在小节可以设置一个timeout属性,不过项目赶的紧,我没时间研究了。

 

以上这些代码比较零散,我花费了2天的时间才总结出来这套方案,不是很完美,但是暂时只能这样了,不能在这方面浪费很多时间了,大家可以把上面的代码组织到一个类里,然后把方法都修改成静态方法方便调用

 

最后大家有什么建议和改进的意见欢迎和我交流。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Win11系统无法安装中文语言包的解决方法 Win11系统无法安装中文语言包的解决方法 Mar 09, 2024 am 09:48 AM

Win11系统无法安装中文语言包的解决方法随着Windows11系统的推出,许多用户开始升级他们的操作系统以体验新的功能和界面。然而,一些用户在升级后发现他们无法安装中文语言包,这给他们的使用体验带来了困扰。在本文中,我们将探讨Win11系统无法安装中文语言包的原因,并提供一些解决方法,帮助用户解决这一问题。原因分析首先,让我们来分析一下Win11系统无法

五招教你解决黑鲨手机开不了机的问题! 五招教你解决黑鲨手机开不了机的问题! Mar 24, 2024 pm 12:27 PM

随着智能手机技术的不断发展,手机在我们日常生活中扮演着越来越重要的角色。而作为一款专注于游戏性能的旗舰手机,黑鲨手机备受玩家青睐。然而,有时候我们也会面临到黑鲨手机开不了机的情况,这时候我们就需要采取一些措施来解决这一问题。接下来,就让我们来分享五招教你解决黑鲨手机开不了机的问题:第一招:检查电池电量首先,确保你的黑鲨手机有足够的电量。可能是因为手机电量耗尽

小红书发布自动保存图片怎么解决?发布自动保存图片在哪里? 小红书发布自动保存图片怎么解决?发布自动保存图片在哪里? Mar 22, 2024 am 08:06 AM

随着社交媒体的不断发展,小红书已经成为越来越多年轻人分享生活、发现美好事物的平台。许多用户在发布图片时遇到了自动保存的问题,这让他们感到十分困扰。那么,如何解决这个问题呢?一、小红书发布自动保存图片怎么解决?1.清除缓存首先,我们可以尝试清除小红书的缓存数据。步骤如下:(1)打开小红书,点击右下角的“我的”按钮;(2)在个人中心页面,找到“设置”并点击;(3)向下滚动,找到“清除缓存”选项,点击确认。清除缓存后,重新进入小红书,尝试发布图片看是否解决了自动保存的问题。2.更新小红书版本确保你的小

无法在此设备上加载驱动程序怎么解决?(亲测有效) 无法在此设备上加载驱动程序怎么解决?(亲测有效) Mar 14, 2024 pm 09:00 PM

  大家都知道,如果电脑无法加载驱动程序,该设备可能就无法正常工作或与计算机进行正确的交互。那在电脑上弹出无法在此设备上加载驱动程序的提示框,我们要如何解决呢?下面小编就教大家两招轻松解决问题。  无法在此设备上加载驱动程序解决方法  1、开始菜单搜索“内核隔离”。  2、将内存完整性关闭,上方提示“内存完整性已关闭。你的设备可能易受攻击。”点击后方忽略即可,不会对使用有影响。  3.重启机器之后即可解决问题。

微信好友辅助验证进行解封的详细方法 微信好友辅助验证进行解封的详细方法 Mar 25, 2024 pm 01:26 PM

1、打开微信进入后,点击搜索图标,输入微信团队,点击下方的服务进入。2、进入后,点击左下方的自助工具的选项。3、点击后,在上方的选项内,点击解封/申诉辅助验证的选项。

解决PyCharm无法打开的方法分享 解决PyCharm无法打开的方法分享 Feb 22, 2024 am 09:03 AM

标题:如何解决PyCharm无法打开的问题PyCharm是一款功能强大的Python集成开发环境,但有时候我们可能会遇到无法打开PyCharm的问题。在本文中,我们将分享一些常见的解决方法,并提供具体的代码示例。希望能帮助到遇到这个问题的小伙伴们。方法一:清除缓存有时候PyCharm的缓存文件可能会导致程序无法正常打开,我们可以尝试清除缓存来解决这个问题。具

如何解决默认网关自动消失的问题 如何解决默认网关自动消失的问题 Feb 24, 2024 pm 04:18 PM

默认网关自动消失怎么解决在现代社会中,互联网已经成为人们生活中不可或缺的一部分。无论是工作还是娱乐,我们都需要稳定的网络连接来完成各种任务。而默认网关是连接本地网络与外部互联网的关键要素之一。然而,有时我们可能会遇到默认网关自动消失的问题,导致无法上网。那么,当默认网关消失时,我们应该如何解决这个问题呢?首先,我们应该明确默认网关的概念。默认网关是一个网络路

华为浏览器已停止访问该网页怎么解决 华为浏览器已停止访问该网页怎么解决 Feb 26, 2024 pm 01:28 PM

华为浏览器已停止访问该网页怎么解决?在使用华为手机浏览器访问某些网站时,可能会出现禁止访问的提示,使用户无法正常浏览相关内容。这对用户而言非常不便。那么,当我们遇到华为手机浏览器网站禁止访问的情况时,该怎么办呢?下面小编将为您提供华为浏览器网站禁止访问解决方法,希望对您有所帮助。华为浏览器网站禁止访问解决方法1、打开华为手机浏览器后,点击下方的三点图标,然后点击设置。2、进入设置后,点击【安全与隐私】3、将【安全浏览】右侧的开关关闭,即可解除网站访问限制。以上便是华为浏览器网站禁止访问解决方法的

See all articles