ASP.NET:Session.SessionID更改请求之间


142

为什么物业的SessionID会议中要求之间的ASP.NET页面的变化-object?

我有一个这样的页面:

...
<div>
    SessionID: <%= SessionID %>
</div>
...

每当我按F5键时,输出就会不断变化,而与浏览器无关。

Answers:


225

这就是原因

使用基于cookie的会话状态时,ASP.NET不会为会话数据分配存储,直到使用Session对象。结果,为每个页面请求生成一个新的会话ID,直到访问该会话对象为止。如果您的应用程序需要整个会话的静态会话ID,则可以在应用程序的Global.asax文件中实现Session_Start方法,并将数据存储在Session对象中以修复会话ID,或者可以在代码的另一部分使用代码应用程序将数据显式存储在Session对象中。

http://msdn.microsoft.com/zh-CN/library/system.web.sessionstate.httpsessionstate.sessionid.aspx

因此,基本上,除非您在后端访问会话对象,否则每个请求都会生成一个新的sessionId

编辑

此代码必须添加到文件Global.asax上。它将一个条目添加到Session对象,以便您修复会话,直到会话过期。

protected void Session_Start(Object sender, EventArgs e) 
{
    Session["init"] = 0;
}

23
我不知道,从来没有一个问题与它但有趣的是知道
Pharabus

1
@Cladudio您可以只输入一行代码,您的答案就是完美的。来自一个有趣的问题的有趣信息...再加上一个?;)
Seb Nilsson 2010年

2
有趣的是,这解决了我的问题-但该问题仅在使用代码库约6个月后才出现。我想不出为什么这会突然改变的任何原因-任何人都可以提出为什么sessionid在以前没有被突然重置的原因吗?
Moo 2012年

2
@KumarHarsh:将任何对象存储在会话中后,会话ID将被修复。这就是我的意思,“除非您在后端访问会话对象...”。一旦分配someid了会话,if将保持不变。考虑到该答案已有4年以上的历史了,不确定是否对此进行了任何修改。
克劳迪奥·雷迪

9
我注意到,只需在我的Global.asax中添加不带任何内容的Session_Start方法即可完成此工作。感谢@Claudio的提示。
Pedro

92

还有另一个更隐蔽的原因,为什么即使Cladudio演示了Session对象已经初始化,也可能发生这种情况。

在Web.config中,如果有一个<httpCookies>设置为,requireSSL="true"但您实际上并未使用HTTPS 的条目:对于特定请求,则不发送会话cookie(或者可能不返回,我不确定哪个),这意味着您最终将为每个请求创建一个全新的会话。

我发现这很困难,在源代码管理中的几次提交之间花了几个小时来回切换,直到发现什么特定的更改破坏了我的应用程序。


5
我知道这一点,但仍然每3个月左右就忘记了,并花几个小时进行调试..
sotn

就我而言,我正在localhost上进行测试,并且web.config中的“ requireSSL”被设置为“ true”。谢谢。
威廉·佩雷拉

这是我的情况,我花了太多时间试图弄清楚(使用不同的web.config文件时出现了红色鲱鱼)。
jmoreno

您的上述建议在2018年仍然有帮助。这是最常见的情况。谢谢!
维杰·班萨尔

5

在我的情况下,我发现会话cookie的域名包含www.前缀,而我请求的页面则没有www.
添加www.到URL立即解决了该问题。后来,我将cookie的域更改为.mysite.com而不是www.mysite.com


5

我的问题是我们在web.config中设置了此设置

<httpCookies httpOnlyCookies="true" requireSSL="true" />

这意味着在非SSL(默认)调试中,auth cookie不会被发送回服务器。这意味着服务器将针对每个请求将新的身份验证Cookie(带有新会话)发送回客户端。

修复方法是在web.config中将requiresl设置为false,在web.release.config中将true设置为true,或者在调试时打开SSL:

开启SSL


这与内维尔·库克(Neville Cook)从2011年以来的回答有何不同?
伊恩·肯普

4

使用Neville的答案(在web.config中删除requireSSL = true),略微修改Joel Etherton的代码,以下代码应处理同时在SSL模式和非SSL模式下运行的网站,具体取决于用户和页面(我正在跳回代码并且尚未在SSL上对其进行测试,但是希望它能正常工作-稍后会很忙而无法返回到此,因此这里是:

if (HttpContext.Current.Response.Cookies.Count > 0)
        {
            foreach (string s in HttpContext.Current.Response.Cookies.AllKeys)
            {
                if (s == FormsAuthentication.FormsCookieName || s.ToLower() == "asp.net_sessionid")
                {
                    HttpContext.Current.Response.Cookies[s].Secure = HttpContext.Current.Request.IsSecureConnection;
                }
            }
        }

2

即使定义了Session_OnStart和/或已初始化会话,导致SessionID在请求之间更改的另一种可能性是URL主机名包含无效字符(例如下划线)。我相信这是特定于IE的(未验证),但是,如果您的URL是http://server_name/app,则IE将阻止所有cookie,并且在两次请求之间将无法访问您的会话信息。

实际上,每个请求都会在服务器上启动一个单独的会话,因此,如果您的页面包含多个图像,脚本标签等,则每个GET请求都会在服务器上导致一个不同的会话。

更多信息:http : //support.microsoft.com/kb/316112


2

就我而言,这在我的开发和测试环境中经常发生。在尝试了所有上述解决方案而没有成功之后,我发现我可以通过删除所有会话cookie来解决此问题。Web开发人员扩展使此操作非常容易。我主要使用Firefox进行测试和开发,但是在Chrome中进行测试时也会发生这种情况。该修复程序还可以在Chrome浏览器中使用。

我还没有在生产环境中进行此操作,也没有收到任何人无法登录的报告。这似乎只是在使会话cookie变得安全之后才发生。当他们不安全时,过去从未发生过。


更新:只有在我们更改了会话cookie以使其安全之后,才开始发生这种情况。我确定确切的问题是由浏览器中具有相同路径和域的两个或多个会话cookie引起的。始终存在问题的一个是具有空值或null的值。删除该特定Cookie后,此问题已解决。我还在Global.asax.cs Sessin_Start方法中添加了代码,以检查此空Cookie,如果已设置,则将其过期日期设置为过去的某个日期。
马特L

2

就我而言,这是因为我从外部应用程序中的网关重定向后正在修改会话,所以因为我在该页面URL的本地主机上使用IP代替,所以实际上它被认为是具有不同会话的不同网站。

综上所述

如果要在IIS上而不是IIS Express上调试托管应用程序,并在各种页面中混合使用计算机http:// Iphttp:// localhost,则应多加注意


1

我的问题是与Microsoft MediaRoom IPTV应用程序有关。事实证明,MPF MRML应用程序不支持cookie。更改为在web.config中使用无cookie会话解决了我的问题

<sessionState cookieless="true"  />

这是关于它的一篇非常古老的文章: 无Cookie ASP.NET


1

我使用的是.NET Core 2.1,我很清楚,问题不在于Core。可是互联网却很匮乏,谷歌把我带到了这里,希望能节省几个小时。


Startup.cs

services.AddCors(o => o.AddPolicy("AllowAll", builder =>
            {
                builder
                    .WithOrigins("http://localhost:3000")     // important
                    .AllowCredentials()                       // important
                    .AllowAnyMethod()
                    .AllowAnyHeader();       // obviously just for testing
            }));

client.js

const resp = await fetch("https://localhost:5001/api/user", {
            method: 'POST',
            credentials: 'include',                           // important
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(data)
        })

Controllers/LoginController.cs

namespace WebServer.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        [HttpPost]
        public IEnumerable<string> Post([FromBody]LoginForm lf)
        {
            string prevUsername = HttpContext.Session.GetString("username");
            Console.WriteLine("Previous username: " + prevUsername);

            HttpContext.Session.SetString("username", lf.username);

            return new string[] { lf.username, lf.password };
        }
    }
}

请注意,会话的写入和读取有效,但似乎没有cookie传递给浏览器。至少我在任何地方都找不到“ Set-Cookie”标题。



0

确保您没有非常短的会话超时,并且还确保如果您使用的是基于cookie的会话,那么您正在接受该会话。

FireFox webDeveloperToolbar在这种情况下非常有用,因为您可以看到为应用程序设置的cookie。


2
我猜我的会话超时未设置为小于一秒。每按一次F5键,它就会改变。
塞伯·尼尔森

0

会话ID重置可能有很多原因。但是,上面提到的任何问题都与我的问题无关。因此,我将对其进行描述以供将来参考。

以我为例,在每个请求上创建一个新会话都会导致无限重定向循环。重定向操作在OnActionExecuting事件中发生。

另外,我一直在清除所有http标头(也使用Response.ClearHeaders方法在OnActionExecuting事件中),以防止在客户端缓存网站。但是该方法会清除所有标头,包括有关用户会话的信息,并因此清除Temp存储中的所有数据(我稍后在程序中使用了该数据)。因此,即使在Session_Start事件中设置新会话也无济于事。

为了解决我的问题,我确保在发生重定向时不要删除标题。

希望它能帮助某人。


0

我以不同的方式遇到了这个问题。[SessionState(SessionStateBehavior.ReadOnly)]即使我在应用程序启动时在原始会话中设置了一个值,具有此属性的控制器仍在从另一个会话中读取。我是通过_layout.cshtml添加会话值的(也许不是最好的主意?)

显然是ReadOnly引起了问题,因为当我删除该属性时,原始会话(和SessionId)将保持原样。使用克劳迪奥/微软的解决方案将其修复。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.