再来一贴,http://topic.csdn.net/u/20080901/16/399ebd3d-e81a-4f37-a94d-c58e68e24821.html没能很好的解决。
用vs2005+ajax 开发的一个系统,现想要session 记录用户ID,现取userid是放在基类得到的。
由于页面很多,争取只改PageArchitecture类中的EmpNo 。
主要如下:
namespace Asset.BaseInfo 

  public class PageArchitecture :Page 
    { 
        public PageArchitecture() 
        { 
        }       
        //得到用户ID
        public string EmpNo 
        { 
            get 
            { 
                string sKo = "";
                if (Session["LoginEmpno"] != null)
                {
                    sKo = Session["LoginEmpno"].ToString();
                    HttpCookie hcooTmp = new HttpCookie("Def");
                    hcooTmp.Expires = DateTime.Now.AddHours(-1);
                    hcooTmp.Values.Add("Def1", Session["LoginEmpno"].ToString());
                    Response.AppendCookie(hcooTmp);
                }
                else
                {
                    HttpCookie cookTmp = HttpContext.Current.Request.Cookies["Def"];
                    if (cookTmp == null)
                    {
                        HttpContext.Current.Response.Redirect("/btsl/asset/asset/Login.aspx?id=2");
                    }
                    else
                    {
                        sKo = cookTmp.Values["Def1"].ToString();
                        if (!IsPostBack)
                        {
                            HttpCookie hcooTmp = new HttpCookie("Def");
                            if (hcooTmp != null)
                            {
                                hcooTmp.Expires = DateTime.Now.AddHours(-1);
                               Response.AppendCookie(hcooTmp);
                                Session["LoginEmpno"] = sKo;
                            }
                       }
                        else
                        {
                            Session["LoginEmpno"] = sKo;
                        }
                    }
                }
                return sKo;
            }
        }   public class basePage : PageArchitecture  //类继承
    {      
        protected override void OnLoad(EventArgs e) 
        { 
            base.OnLoad(e);            
        } 
    } 
} 页面B0001 .cs 
public partial class B0001 : basePage  //类继承
    { 
      ... 
      取登录者的时候就用: 
      string loginempno=Empno;    
      现经常取不到Empno,有时候过不了两分钟就要求重新登录 
    } 
另 webconfig内: 
      <sessionState mode="InProc"  cookieless="false"  timeout="180"    /> 
测试时,调试没感觉session过期情况,但用IIS查看时,有时不到五分钟就自动跳到登录页面了。

解决方案 »

  1.   

    我试着改用 <sessionState mode="StateServer" cookieless="false" timeout="240" stateConnectionString="tcpip=127.0.0.1:42424" stateNetworkTimeout="14400" />这个来实现,
    具体实现不会,按照网上说的要启动apsnet状态进程,还要序列化,但说序列化的类不能继承。
    所以还是不能解决。非常谢谢,希望详细点。
      

  2.   

    把session配置成数据库存储
      

  3.   

    mode="InProc"
    ==
    默认的配置方式很容易丢失Session 请参考asp中Session的工作原理:
    asp的Session是具有进程依赖性的。ASP Session状态存于IIS的进程中,也就是inetinfo.exe这个程序。所以当inetinfo.exe进程崩溃时,这些信息也就丢失。另外,重起或者关闭IIS服务都会造成信息的丢失。原因1:
    bin目录中的文件被改写,asp.net有一种机制,为了保证dll重新编译之后,系统正常运行,它会重新启动一次网站进程,这时就会导致Session丢失,所以如果有access数据库位于bin目录,或者有其他文件被系统改写,就会导致Session丢失原因2:
    文件夹选项中,如果没有打开“在单独的进程中打开文件夹窗口”,一旦新建一个窗口,系统可能认为是新的Session会话,而无法访问原来的Session,所以需要打开该选项,否则会导致Session丢失原因3:
    似乎大部分的Session丢失是客户端引起的,所以要从客户端下手,看看cookie有没有打开原因4:
    Session的时间设置是不是有问题,会不会因为超时造成丢失原因5:
    IE中的cookie数量限制(每个域20个cookie)可能导致session丢失原因6:
    使用web garden模式,且使用了InProc mode作为保存session的方式解决丢失的经验
    1. 判断是不是原因1造成的,可以在每次刷新页面的时候,跟踪bin中某个文件的修改时间
    2. 做Session读写日志,每次读写Session都要记录下来,并且要记录SessionID、Session值、所在页面、当前函数、函数中的第几次Session操作,这样找丢失的原因会方便很多
    3. 如果允许的话,建议使用state server或sql server保存session,这样不容易丢失
    4. 在global.asa中加入代码记录Session的创建时间和结束时间,超时造成的Session丢失是可以在SessionEnd中记录下来的。
    5. 如果有些代码中使用客户端脚本,如javascript维护Session状态,就要尝试调试脚本,是不是因为脚本错误引起Session丢失问:为什么Session在有些机器上偶尔会丢失?
    答:可能和机器的环境有关系,比如:防火墙或者杀毒软件等,尝试关闭防火墙。问:为什么当调用Session.Abandon时并没有激发Session_End方法?
    答:首先Session_End方法只支持InProc(进程内的)类型的Session。其次要激发Session_End方法,必须存在Session(即系统中已经使用Session了),并且至少要完成一次请求(在这次请求中会调用该方法)。问:为什么当我在InProc模式下使用Session会经常丢失?
    答:该问题通常是由于应用程序被回收导致的,因为当使用进程内Session时,Session是保存在aspnet_wp进程中,当该进程被回收Session自然也就没有了,确定该进程是否被回收可以通过查看系统的事件查看器获得信息。
     具体信息请参考:
     Session variables are lost intermittently in ASP.NET applications
     http://support.microsoft.com/default.aspx?scid=kb;en-us;Q316148
     在1.0的时候也有一个bug会导致工作进程被回收并重启,该bug已经在1.1和sp2中修复。
     关于该bug的详细信息请参考:
     ASP.NET Worker Process (Aspnet_wp.exe) Is Recycled Unexpectedly. 
     http://support.microsoft.com/default.aspx?scid=kb;en-us;Q321792
    问:什么类型的对象可以保存在Session里?
    答:这依赖使用的Session的模式,当使用的是进程内(InProc)的Session那么可以轻松的保存任何对象。如果你使用了非InProc的模式,则只能保存可以序列化和反序列化的对象,如果此时保存的对象不支持序列化,则不能保存到这种模式(非InProc)的Session里。问:为什么在Session_End中不能使用Response.Redirect和Server.Transfer方法跳转页面?
    答:Session_End是一个在服务器内部激发的事件处理函数。它是基于一个服务器内部的计时器的,在激发该事件时服务器上并没有相关的HttpRequest对象,因此此时并不能使用Response.Redirect和Server.Transfer方法。问:在Session_End中是否可以获得HttpContext对象?
    答:不行,因为这个事件并没有和任何的请求(Request)相关联,没有基于请求的上下文。问:在Web Service中该如何使用Session?
    答:为了在Web Service中使用Session,需要在Web Service的调用方做一些额外的工作,必须保存和存储调用Web Service时使用的Cookie。详细信息请参考MSDN文档的HttpWebClientProtocol.CookieContainer属性。然而,如果你使用代理服务器访问Web Service由于框架的限制,两者不能共享Session。
    问:当我使用webfarm时,当我重定向到其他的Web服务器时Session为什么会丢失?
    答:详细信息请参考:
     PRB: Session State Is Lost in Web Farm If You Use SqlServer or StateServer Session Mode
     http://support.microsoft.com/default.aspx?scid=kb;en-us;325056问:Session在global.asax中的那些事件中有效?
    答:Session只有在AcquireRequestState事件之后有效,该事件之后的事件都可以使用Session。 
    问:为了可以顺序访问Session的状态值,Session是否提供了锁定机制?
    答:Session实现了Reader/Writer的锁机制:
     当页面对Session具有可写功能(即页面有<%@ Page EnableSessionState="True" %>标记),此时直到请求完成该页面的Session持有一个写锁定。
     当页面对Session具有只读功能(即页面有<%@ Page EnableSessionState="ReadOnly" %>标记),此时知道请求完成该页面的Session持有一个读锁定。
     读锁定将阻塞一个写锁定;读锁定不会阻塞读锁定;写锁定将阻塞所有的读写锁定。这就是为什么两个框架中的同一个页面都去写同一个Session时,其中一个要等待另一个(稍快的那个)完成后,才开始写。问:Session平滑超时意味着什么?
    答:Session平滑超时意味着只要你的页面访问(使用)了Session,超时时间将被刷新(可以理解为重新计时),即从该页面请求开始,将重新计算超时时间。但是,该页面不能禁用Session。它会自动的访问当前页面的Session,刷新超时时间。
     
    问:在global.asax中的事件处理函数中Session为什么无效?
    答:依赖于在哪个事件处理函数中使用Session,Session在AcquireRequestState事件之后才有效,该事件之后的所有事件处理函数都可以使用Session,之前的则不能。
    问:当我使用InProc模式保存Session时,此时的Session是保存在哪里?
    答:不同的IIS的处理方式不同,
     当使用的是IIS5的时候Session是保存在aspnet_wp.exe的进程空间里的。
     当使用的是IIS6时,默认情况下所有的应用程序共享应用程序池,Session保存在w3wp.exe的进程空间中。问:当页面出现错误后我的Session是否将被保存?我需要在Session_End中处理一些清理工作,但是失败了,为什么?
    答:Session_End只有在Session运行在InProc模式下才会被执行。Session_End使用的帐号是运行aspnet_wp工作进程的帐号(这个可以在machine.config中设置)。因此,如果在Session_End方法里,使用集成安全性链接到SQL,它将使用aspnet_wp进程的帐号打开链接,此时成功与否则依赖于你的SQL的安全性设置。问:在Session_End是我是否可以获得有效的HttpSessionState和HttpContext对象?
    答:你可以在这个方法中获得HttpSessionState对象,可以直接使用Session来访问即可。但是不能获得HttpContext对象,因为该事件并没有和任何请求相关联,因此不存在上下文对象。问:在SQLServer模式下使用Session,为什么我的Session不过期?
    答:在SqlServer模式下,Session的过期是通过SQL Agent的注册工作完成的,请检查你的SQL Agent是否运行?
     
    问:当我设置EnableSessionState为“ReadOnly”后,但是我在InProc模式下依然可以修改Session的值,这是为什么?
    答:即使EnableSessionState标示为ReadOnly,但是在InProc模式下用户依然可以编辑Session。唯一不同的是,在请求过程中Session将不会被锁住。问:为什么在切换成SQLServer模式后我的请求被挂起了?
    答:检查在Session里面是否都保存的是可以保存在SQLServer模式下的对象,即这些对象必须支持序列化。
     问:当Session设置成cookieless后会有什么影响?
    答:当把cookieless设置成true时,主要会有下面的约束:
     1、在页面中不能使用绝对链接
     2、在应用程序中在除了Http和Https之间的切换时需要完成一些其他的步骤。
     如果发送一个链接给其他人,此时的URL里面将包含Session ID的信息,所以两个人将公用一个Session。
      

  4.   

    谢谢,非常谢谢,
    导致的原因都列出,但具体引出的原因还是没找到。感觉Session过期,更多的原因是客户端引起。
    我希望各位能否赐教用
    “3. 如果允许的话,建议使用state server或sql server保存session,这样不容易丢失 ”
    这个实现。在开这个贴之前,我用state server试过,但类要求序列化,在网上也看到了序列化的类不能继承。
    而这里的基类中要求继承,所以又被难到了。
      

  5.   


    现打算改方法,用state server或sql server保存session实现。
      

  6.   

    用session和cookies两者也可以,但没能实现。
      

  7.   

    hcooTmp.Expires = DateTime.Now.AddSeconds(200); 设的是200。如果你这时间内不动,并且过了timeout,就会跳到登录页。 
    另外,在开发环境中,用程序运行和用IE运行同一页面是有分别的。 
    要试的话,得编译成网站后,设置好timeout再做同样事情。 还有如果你在200内,另开IE再开一网站页面,同样会得到session,这就是不安全因素。所以,在用这种方法之后,最好配合使用 Server.Transfer("")方法跳转页面,以加强全安性。 
    我写的代码的主要作用是在iis重启、webconfig被改等等这种突发性 session失丢的情况下,使session能从cookie读取。时间根据安全要求设置,毕竟,cookie保存这些敏感信息是不安全的。 
    25楼的方法在多数时好用,不过也不用不了的时候。iis很稳定,但不是很稳健。 
      

  8.   

    hcooTmp.Expires = DateTime.Now.AddHours(-1); 
                                  Response.AppendCookie(hcooTmp); 
                                    Session["LoginEmpno"] = sKo; 这段代码没道理
    在另外要开IE读同一页面,会走到这里,如果这时能读取session,就会导致200秒内操作员可以作弊。 
    这时要做的
    hcooTmp.Expires = DateTime.Now.AddHours(-1); 设置 cookie过期为现在的时间-1小时。
                                  Response.AppendCookie(hcooTmp); 添加到客户端cooke 
    cookie过期
    这时你在上边读到的sKo应该是没有数据的。如果赋给session...就没用了
      

  9.   

    我的想法是:先读session的值,如果session不为空,则写到cookie里,并返回值;如果为空则读cookie,如果cookie也为空,则跳到登录页面;如果cookie不为空,则读取值并赋给session,同时返回值. public string EmpNo 
            { 
                get 
                { 
                    string sKo = ""; 
                    if (Session["LoginEmpno"] != null)  //session不为空,则写进cookie里,存放在sKo
                    { 
                        sKo = Session["LoginEmpno"].ToString(); 
                        HttpCookie hcooTmp = new HttpCookie("Def"); 
                        hcooTmp.Expires = DateTime.Now.AddHours(-1); 
                        hcooTmp.Values.Add("Def1", Session["LoginEmpno"].ToString()); 
                        Response.AppendCookie(hcooTmp); 
                    } 
                    else  //session为空,
                    { 
                        HttpCookie cookTmp = HttpContext.Current.Request.Cookies["Def"];  //读取cookie
                        if (cookTmp == null)  //cookie为空,则跳到login.aspx
                        { 
                            HttpContext.Current.Response.Redirect("/btsl/asset/asset/Login.aspx?id=2"); 
                        } 
                        else  // cookie不为空,读取def1的值,并存放sKo中。其中ispostback 什么的是模仿"skywolfY"提供写的,具体还真不太明白。
                        { 
                            sKo = cookTmp.Values["Def1"].ToString(); 
                            if (!IsPostBack) 
                            { 
                                HttpCookie hcooTmp = new HttpCookie("Def"); 
                                if (hcooTmp != null) 
                                { 
                                    hcooTmp.Expires = DateTime.Now.AddHours(-1); 
                                    Response.AppendCookie(hcooTmp); 
                                    Session["LoginEmpno"] = sKo; 
                                } 
                          } 
                            else 
                            { 
                                Session["LoginEmpno"] = sKo; 
                            } 
                        } 
                    } 
                    return sKo; 
                } 
      

  10.   

    想通过session和cookie结合解决session过期的原因,各位能否针对以上代码给予指点。先谢谢了
      

  11.   

    关于序列化和反序列化的问题,你可以手动实现,以下是代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.Serialization;
    using System.Xml;
    using System.IO;namespace BofA.BL
    {
        public class SerializeEntity
        {
            public static String Serialize<T>(T data)
            {
                DataContractSerializer dcs = new DataContractSerializer(data.GetType());
                StringBuilder sb = new StringBuilder();
                XmlWriter writer = XmlWriter.Create(sb);
                dcs.WriteObject(writer, data);
                writer.Close();
                return sb.ToString();
            }        public static T DeSerialize<T>(String str)
            {
                DataContractSerializer dcs = new DataContractSerializer(typeof(T));
                using (Stream memStream = new MemoryStream(Encoding.Unicode.GetBytes(str)))
                {
                    XmlDictionaryReaderQuotas xdrq = new XmlDictionaryReaderQuotas() { MaxStringContentLength = 500000 };
                    XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(memStream, xdrq);
                    return (T)dcs.ReadObject(reader, true);
                }
            }
        }
    }
      

  12.   

    咦?这么多天了还没搞好?
    if (!IsPostBack) 首次进入网页
    IsPostBack 是不是同一网页进行了提交行为。  post back我和代码和你的不一样,我比你的多了个TYDefault.aspx  这个session是在网页的登录页上设定的。表示网站必须经过这个页面,否则认为非法。我来说明下。这只是一种逻辑方法罢了。也可以有别的方法,每个人的想法都会不同的。 if (Session["FirstPage"] != null)   //如果曾经登录过
            { 
                if (Session["FirstPage"].ToString() != "TYDefault.aspx")             
                { //如果输入或提交过程未经过了规定页面
                    Server.Transfer("~/BasePage/Main/DefaultErr.aspx"); 
                    Response.End(); 
                } 
                //如果输入或提匀过程经过了规定的页面,写入新的cookie,时间200
                HttpCookie hcooTmp = new HttpCookie("Def"); 
                hcooTmp.Expires = DateTime.Now.AddSeconds(200); 
                hcooTmp.Values.Add("Def1", Server.UrlEncode(Session["FirstPage"].ToString())); 
                hcooTmp.Values.Add("Def2", Server.UrlEncode(Session["psCurLoginID"].ToString())); 
                hcooTmp.Values.Add("Def3", Server.UrlEncode(Session["psCurLoginName"].ToString())); 
                hcooTmp.Values.Add("Def4", Server.UrlEncode(Session["psCurClientID"].ToString())); 
                Response.AppendCookie(hcooTmp); 
            } 
            else 
            { //未登录过或session丢失时,读取cookie
                HttpCookie cookTmp = HttpContext.Current.Request.Cookies["Def"]; 
                if (cookTmp == null) 
                { //如不存在退出
                    Response.Write("网站初始化失败,请重新登录."); 
                    Response.End();             } 
                else 
                { //如果存在,读取首页必经标识。
                    string sKo = Server.UrlDecode(cookTmp.Values["Def1"].ToString()); 
                    if (sKo != "TYDefault.aspx") 
                    { //标识如错误,为非法链接
                        Response.Write("网站初始化失败,请重新登录."); 
                        Response.End(); 
                    } 
                    else 
                    { 
                        if (!IsPostBack) 
                        { //如果此网页为首次进入。必须清除cookie,因为在session丢失,又是首次进入网页,
                             //无法确定是不是非法链接,如果不清除cookie,软件无安全可言。
                            HttpCookie hcooTmp = new HttpCookie("Def"); 
                            if (hcooTmp != null) 
                            { 
                                hcooTmp.Expires = DateTime.Now.AddHours(-1); 
                                Response.AppendCookie(hcooTmp); 
                            } 
                            Response.Write("网站初始化失败,请重新登录...."); 
                            Response.End(); 
                        } 
                        else 
                        { 
                          //如果不是首次进入网页,这种实际上是最可能发生session丢失的情况。
                             //因为一般session丢失不会在网页跳转时发生,而是在频繁提交数据过程中发生。
                             //此时读取cookie给session,
                            Session["FirstPage"] = Server.UrlDecode(sKo); 
                            Session["psCurLoginID"] = Server.UrlDecode(cookTmp.Values["Def2"].ToString()); 
                            Session["psCurLoginName"] = Server.UrlDecode(cookTmp.Values["Def3"].ToString()); 
                            Session["psCurClientID"] = Server.UrlDecode(cookTmp.Values["Def4"].ToString()); 
                        } 
                    } 
                }         }
      

  13.   


    你的这段代码,sKo = Session["LoginEmpno"].ToString(); 
                        HttpCookie hcooTmp = new HttpCookie("Def"); 
                        hcooTmp.Expires = DateTime.Now.AddHours(-1); 
                        hcooTmp.Values.Add("Def1", Session["LoginEmpno"].ToString()); 
                        Response.AppendCookie(hcooTmp); 
    实际执行的操作是删除cookie。你一进网页,删一个不存在的cookie,是没必要的。
      

  14.   

    算了,我再提醒你一句。你的第18行代码错了。应该是
    hcooTmp.Expires = DateTime.Now.AddSeconds(200); 
    这样的代码而不是
            hcooTmp.Expires = DateTime.Now.AddHours(-1); 
    看下Expires 的msdn
      

  15.   

     仅用户id的话,用cookie就可以了,如果是敏感信息,可考虑加密
      

  16.   


      public string EmpNo
            {
                get
                {
                    string sKo = "";
                    if (Session["LoginEmpno"] != null)  //session不为空,则写进cookie里,存放在sKo 
                    {
                        sKo = Session["LoginEmpno"].ToString();                  
                    }
                    else  //session为空, 
                      {
                        HttpCookie cookTmp = HttpContext.Current.Request.Cookies["Def"]; 
                        if (cookTmp == null)  //cookie为空,则跳到login.aspx 
                        {
                            HttpContext.Current.Response.Redirect("/btsl/asset/asset/Login.aspx?id=2");
                        }
                        else  
                          {
                            sKo = cookTmp.Values["Def1"].ToString();
                            if (!IsPostBack)
                            {
                                HttpCookie hcooTmp = new HttpCookie("Def");
                                if (hcooTmp != null)
                                {
                                    hcooTmp.Expires = DateTime.Now.AddHours(200);
                                    Response.AppendCookie(hcooTmp);
                                    Session["LoginEmpno"] = sKo;
                                }
                            }
                            else
                            {
                                Session["LoginEmpno"] = sKo;
                            }
                        }
                    }
                    return sKo;
                }
            }哎,这样怎么还不行啦?
      

  17.   

    session 默认过期时间是20分钟,可能是其它的问题。
      

  18.   

    to  skywolfY:
    麻烦替我看看这样为什么还不行?
    login.aspx登录页面,用户名、密码输入正确的时候把用户名对应的值保存到Session["LoginEmpno"]   public string EmpNo 
            { 
                get 
                { 
                    string sKo = ""; 
                    if (Session["LoginEmpno"] != null)  //session不为空,返回 Session["LoginEmpno"]
                   { 
                        sKo = Session["LoginEmpno"].ToString();                  
                    } 
                    else  //session为空, 
                      { 
                        HttpCookie cookTmp = HttpContext.Current.Request.Cookies["Def"]; 
                        if (cookTmp == null)  //cookie为空,则跳到login.aspx 
                        { 
                            HttpContext.Current.Response.Redirect("/btsl/asset/asset/Login.aspx?id=2"); 
                        } 
                        else  
                          { 
                            sKo = cookTmp.Values["Def1"].ToString(); 
                            if (!IsPostBack) 
                            { 
                                HttpCookie hcooTmp = new HttpCookie("Def"); 
                                if (hcooTmp != null) 
                                { 
                                    hcooTmp.Expires = DateTime.Now.AddSeconds(200); 
                                    Response.AppendCookie(hcooTmp); 
                                    Session["LoginEmpno"] = sKo; 
                                } 
                            } 
                            else 
                            { 
                                Session["LoginEmpno"] = sKo; 
                            } 
                        } 
                    } 
                    return sKo; 
                } 
            } 这样为什么还不行啦?
      

  19.   

    有可能是使用 ajax 的原因。
      

  20.   

    to skywolfY:
    页面隔了一个小时没用后,开始操作,可单击按钮都没反应。(以前session失效,单击按钮时就打开login.aspx)
    现在treeview中打开其它的页面,能获得登录ID。(session应该没有失效)这样过了一段时间后,还是需重新打开这个页面,才能操作。
    我用了ajax,不知与ajax有没有关系。
      

  21.   

    Session的设置除了Web.config里设置,还需要在你发布应用程序的服务器上设置,在站点(虚拟目录)里,是要设置的。建议使用Cookie。Cookie有效期时间是可以设置的,你可以设置长点或是长期有效,但如果是有期,
      如:Cookie有效期设置为10天,那么必须要保证客户端的时间小于服务器时间+10天。当然,一般上将,服务器时间与客户段时间基本一致的。
      

  22.   

    iis6吗?看看你的应用程序池的Web园是否为1
      

  23.   

    服务中的.asp.net的服务开启为自动