再来一贴,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查看时,有时不到五分钟就自动跳到登录页面了。
用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查看时,有时不到五分钟就自动跳到登录页面了。
具体实现不会,按照网上说的要启动apsnet状态进程,还要序列化,但说序列化的类不能继承。
所以还是不能解决。非常谢谢,希望详细点。
==
默认的配置方式很容易丢失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。
导致的原因都列出,但具体引出的原因还是没找到。感觉Session过期,更多的原因是客户端引起。
我希望各位能否赐教用
“3. 如果允许的话,建议使用state server或sql server保存session,这样不容易丢失 ”
这个实现。在开这个贴之前,我用state server试过,但类要求序列化,在网上也看到了序列化的类不能继承。
而这里的基类中要求继承,所以又被难到了。
现打算改方法,用state server或sql server保存session实现。
另外,在开发环境中,用程序运行和用IE运行同一页面是有分别的。
要试的话,得编译成网站后,设置好timeout再做同样事情。 还有如果你在200内,另开IE再开一网站页面,同样会得到session,这就是不安全因素。所以,在用这种方法之后,最好配合使用 Server.Transfer("")方法跳转页面,以加强全安性。
我写的代码的主要作用是在iis重启、webconfig被改等等这种突发性 session失丢的情况下,使session能从cookie读取。时间根据安全要求设置,毕竟,cookie保存这些敏感信息是不安全的。
25楼的方法在多数时好用,不过也不用不了的时候。iis很稳定,但不是很稳健。
Response.AppendCookie(hcooTmp);
Session["LoginEmpno"] = sKo; 这段代码没道理
在另外要开IE读同一页面,会走到这里,如果这时能读取session,就会导致200秒内操作员可以作弊。
这时要做的
hcooTmp.Expires = DateTime.Now.AddHours(-1); 设置 cookie过期为现在的时间-1小时。
Response.AppendCookie(hcooTmp); 添加到客户端cooke
cookie过期
这时你在上边读到的sKo应该是没有数据的。如果赋给session...就没用了
{
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;
}
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);
}
}
}
}
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());
}
}
} }
你的这段代码,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,是没必要的。
hcooTmp.Expires = DateTime.Now.AddSeconds(200);
这样的代码而不是
hcooTmp.Expires = DateTime.Now.AddHours(-1);
看下Expires 的msdn
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;
}
}哎,这样怎么还不行啦?
麻烦替我看看这样为什么还不行?
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;
}
} 这样为什么还不行啦?
页面隔了一个小时没用后,开始操作,可单击按钮都没反应。(以前session失效,单击按钮时就打开login.aspx)
现在treeview中打开其它的页面,能获得登录ID。(session应该没有失效)这样过了一段时间后,还是需重新打开这个页面,才能操作。
我用了ajax,不知与ajax有没有关系。
如:Cookie有效期设置为10天,那么必须要保证客户端的时间小于服务器时间+10天。当然,一般上将,服务器时间与客户段时间基本一致的。