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

为什么 ASP.NET 页面中 会议-对象的属性 SessionID会在请求之间发生变化?

我有一个这样的页面:

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

而且每次我点击 F5的时候输出都在不断变化,与浏览器无关。

126374 次浏览

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

FireFoxwebDeveloperToolbar 在这种情况下很有帮助,因为您可以看到为您的应用程序设置的 cookie。

这就是原因

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

Http://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.sessionid.aspx

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

剪辑

这段代码必须添加到 Global.asax 文件中。它将一个条目添加到 Session 对象,这样您就可以修复会话,直到它过期。

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

还有另外一个更隐蔽的原因,为什么即使 Session 对象已经初始化,Cladudio 也会出现这种情况。

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

我在源代码控制中花了几个小时来回提交,直到我发现哪些特定的更改破坏了我的应用程序。

使用 Neville 的回答(在 web.config 中删除必要的 SSL = 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;
}
}
}

在我的案例中,我发现会话 cookie 有一个包含 www.前缀的 域名,而我请求的页面没有 www.
www.添加到 URL 中立即解决了这个问题。后来我将 cookie 的域设置为 .mysite.com而不是 www.mysite.com

导致 SessionID 在请求之间变化的另一种可能性是 URL 主机名包含无效字符(例如下划线) ,即使在 Session _ OnStart 已定义和/或 Session 已初始化的情况下也是如此。我相信这是 IE 特有的(未经验证) ,但如果您的 URL 是,比如说,http://server_name/app,那么 IE 将阻止所有 cookie 和您的会话信息将无法在请求之间访问。

事实上,每个请求都会在服务器上产生一个单独的会话,所以如果页面包含多个图像、脚本标记等,那么每个 GET 请求都会在服务器上产生一个不同的会话。

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

我的问题是微软 MediaRoom IPTV 应用程序。事实证明,MPMRML 应用程序不支持 cookie; 在 web.config 中改为使用无 cookie 会话解决了我的问题

<sessionState cookieless="true"  />

这里有一篇很老的文章: 无 Cookie 的 ASP.NET

会话 ID 重置可能有许多原因。然而,上面提到的任何问题都与我的问题无关。所以我会描述一下,以备将来参考。

在我的例子中,为每个请求创建一个新会话会导致无限重定向循环。重定向操作发生在 行动执行事件中。

此外,我一直在清除所有的 http 头(也在 行动执行事件使用 回应,清除队方法) ,以防止缓存站点在客户端。但是,该方法清除所有头部,包括关于用户会话的信息,以及因此清除 Temp 存储中的所有数据(我在后面的程序中使用了 Temp 存储)。因此,即使在 Session _ Start 事件中设置新会话也无济于事。

为了解决这个问题,我确保了在发生重定向时不会删除标头。

希望能帮到别人。

我的问题是我们在 web.config 中有这个集合

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

这意味着在非 SSL (默认)中进行调试时,不会将 auth cookie 发送回服务器。这意味着服务器将为每个请求向客户机发送一个新的 auth cookie (带有一个新的会话)。

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

turn on SSL

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

显然是 ReadOnly 导致了这个问题,因为当我删除该属性时,原始会话(和 SessionId)将保持不变。用克劳迪奥/微软的解决方案解决了这个问题。

在我的例子中,这在我的开发和测试环境中经常发生。在尝试了以上所有的解决方案都没有成功之后,我发现我可以通过删除所有的会话 cookie 来解决这个问题。Web 开发人员扩展使这一点非常容易做到。我大多数时候使用 Firefox 进行测试和开发,但在 Chrome 中测试时也会出现这种情况。这个补丁在 Chrome 中也有效。

我还没有在生产环境中这样做,也没有收到任何人无法登录的报告。这似乎也只有在使会话 cookie 安全之后才会发生。在过去,当他们不安全的时候,这从来没有发生过。

更新: 这只是在我们更改会话 cookie 以确保其安全之后才开始发生的。我已经确定,确切的问题是由于浏览器中有两个或多个具有相同路径和域的会话 cookie 造成的。一直存在问题的是一个空值或空值。在删除了那个特定的 cookie 之后,问题就解决了。我还在 Global.asax.cs Sessin _ Start 方法中添加了代码来检查这个空 cookie,如果是这样,则将其过期日期设置为过去的某个日期。

HttpCookieCollection cookies = Response.Cookies;
for (int i = 0; i < cookies.Count; i++)
{
HttpCookie cookie = cookies.Get(i);


if (cookie != null)
{
if ((cookie.Name == "ASP.NET_SessionId" || cookie.Name == "ASP.NET_SessionID") && String.IsNullOrEmpty(cookie.Value))
{
//Try resetting the expiration date of the session cookie to something in the past and/or deleting it.
//Reset the expiration time of the cookie to one hour, one minute and one second in the past
if (Response.Cookies[cookie.Name] != null)
Response.Cookies[cookie.Name].Expires = DateTime.Today.Subtract(new TimeSpan(1, 1, 1));
}
}
}

在我的情况下,这是因为我修改了会话 在外部应用程序中从网关重定向之后,因此,因为我使用 IP 而不是本地主机在该网页的网址,它实际上被认为是不同的网站与不同的会话。

总结一下

如果您在 IIS 上调试托管应用程序,而不是在 IIS 表达式上调试,并在不同的页面中混合使用机器 http://Iphttp://localhost,请多加注意

我来了。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”的标题。

从一开始,我就改变了。NET 4.7.2,这是由于会话 cookie 上的 SameSite 属性。更多信息请点击这里: https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/

默认值改为“ Lax”,并开始破坏东西。我把它改为“无”,事情按预期运行。