蛙蛙池塘

没有公主的蛙蛙王子

胡浩ID:onlytiancai
122681次访问,排名673好友1人,关注者1
onlytiancai的文章
原创 93 篇
翻译 0 篇
转载 22 篇
评论 117 篇
蛙蛙王子的公告
残荷听雨,梨花飞雪,落英缤纷时节。晓来谁染枫林醉?点点都是离人泪
活着,就是快乐!自信,就是美丽! 有人爱,就是幸福。

但愿野百合也有春天

最近评论
hdnero:wow power leveling
hdnero:wow power leveling
lindahou:THANK YOU VERY MUCH
mylittledog:如果我要添加http://172.20.50.11呢?
hm8030:问题2:请教:怎样让页面局部无刷新更新数据呀,xmlhttp可以发送recordset吗?

问题是这样的:我的首页上有好几处显示数据的表格,每个表示对应着服务器的一个记录集(recordset),我想让其中几个表格能够每隔30秒种更新一下数据,前提是网页的其它部分,比如说广告,图片等不用更新。
整个页面的无刷新更新和只更新某个字符串我已经做到了,现在我是想让一……
文章分类
收藏
    相册
    友情博客
    Anatoly 姐姐的博客
    Bob Beauchemin姐姐的博客
    chnking姐姐的博客
    cocosoft姐姐的博客
    donet姐姐的博客
    Eric/xin姐姐的博客
    ilqtj姐姐的博客
    JAVA姐姐的博客
    Nathan Dunlap姐姐的博客
    Sinoprise Studios姐姐的博客
    千山一鸟的博客
    土人姐姐的博客
    微软姐姐的博客
    思归姐姐的博客
    木子姐姐的博客
    笨笨姐姐的博客
    阿好姐姐的博客
    飞信美眉 飞信交友
    龙卷风姐姐的博客
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 蛙蛙推荐:一套.net窗体身份验证方案(解决了防止用户重复登陆,session超时等问题)收藏

    新一篇: 蛙蛙推荐:两个好看的文本框样式 | 旧一篇: 蛙蛙推荐:第一个实际应用中开发的自定义web服务器控件

    一.      设置web.config相关选项

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

    <authentication mode="Forms">

           <forms loginUrl="default.aspx"></forms>

    </authentication>

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

    <authorization>

               <allow users="*" />

    </authorization>

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

         <location path="admin">

           <system.web>

               <authorization>

                  <deny users="?"></deny>

               </authorization>

           </system.web>

    </location>

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

    <globalization requestEncoding="gb2312" responseEncoding="gb2312" />

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

    <sessionState mode="InProc" cookieless="true" timeout="1" />

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

    <trace enabled="true" requestLimit="1000" pageOutput="true" traceMode="SortByTime" localOnly="true" />

    二.      设置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()方法,方法源码如下

    /// <summary>

        /// 清除Cache里当前的用户,主要在Global.asaxSession_End方法和用户注销的方法里调用      /// </summary>

        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目录下有一个页打开着,即使不手工向服务器发送请求,也会自动发送一个请求更新登陆时间,下面我在页面基类里写了一个函数来做到这一点,其实这会增加服务器的负担,但在一定情况下也是一个可行的办法.

    /// <summary>

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

           /// </summary>

           /// <param name="name">要验证的用户名字</param>

           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<60)

                         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

        {

     

           /// <summary>

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

           /// </summary>

           protected bool IsAdminDir

           {

               get

               {

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

               }

           }

     

           /// <summary>

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

           /// </summary>

           private void PreventSessionTimeout()

           {

               if(!this.IsAdminDir) return;

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

               {            

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

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

               }

           }

           /// <summary>

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

           /// </summary>

           private void UpdateCacheTime()

           {

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

               if(h!=null)

               {

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

               }

               Cache["Online"]=h;

           }

           /// <summary>

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

           /// </summary>

           /// <param name="myList"></param>

           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++;

               }

           }

     

           /// <summary>

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

           /// </summary>

           /// <param name="msg">弹出的消息</param>

           /// <param name="url">指定转向的页面</param>

           protected void Alert(string msg,string url)

           {

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

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

                  this.RegisterStartupScript("alert", scriptString);

           }

           /// <summary>

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

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

           /// </summary>

           protected void XmlReLoad()

           {     

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

               htmlstr.Append("<SCRIPT LANGUAGE=\"JavaScript\">");

               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("</SCRIPT>       ");

               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

    {

        /// <summary>

        /// MyException 的摘要说明。

        /// </summary>

        public class MyException:ApplicationException

        {

     

               /// <summary>

               /// 构造函数

               /// </summary>

               public MyException():base()

               {

               }

               /// <summary>

               /// 构造函数

               /// </summary>

               /// <param name="ErrMessage">异常消息</param>

               public MyException(string Message):base(Message)

               {

                   System.Web.HttpContext.Current.Response.Redi