为什么ASP.NET页面中会话 - 对象上的属性 SessionID 会在请求之间发生变化?
我有一个这样的页面:
...
<div>
SessionID: <%= SessionID %>
</div>
...
每次点击F5时输出都会不断变化,与浏览器无关。
答案 0 :(得分:202)
这就是原因
使用基于cookie的会话状态时,在使用Session对象之前,ASP.NET不会为会话数据分配存储空间。结果,为每个页面请求生成新的会话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;
}
答案 1 :(得分:85)
还有另一个更阴险的原因,即使Clauddio已经初始化Session对象,为什么会出现这种情况。
在Web.config中,如果<httpCookies>
条目设置为requireSSL="true"
但您实际上并未使用HTTPS:对于特定请求,则不会发送会话cookie(或也许没有退回,我不确定是哪个)这意味着你最终会为每个请求结束一个全新的会话。
我发现这个很难,在源代码控制中的几次提交之间花了几个小时来回,直到我发现哪些特定的更改破坏了我的应用程序。
答案 2 :(得分:5)
在我的情况下,我发现会话Cookie的域包含www.
前缀,而我请求的页面没有www.
。
将www.
添加到URL会立即解决问题。之后我将Cookie的域名更改为.mysite.com
而不是www.mysite.com
。
答案 3 :(得分:4)
使用Neville的答案(删除requireSSL = true,在web.config中)和稍微修改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;
}
}
}
答案 4 :(得分:2)
导致SessionID在请求之间切换的另一种可能性,即使定义了Session_OnStart和/或初始化了Session,也就是URL主机名包含无效字符(例如下划线)。我相信这是IE特定的(未经验证),但如果您的网址是http://server_name/app
,那么IE将阻止所有Cookie,并且您的会话信息将无法在请求之间访问。
实际上,每个请求都会在服务器上启动一个单独的会话,因此如果您的页面包含多个图像,脚本标记等,那么每个GET请求都将导致服务器上的不同会话。
答案 5 :(得分:1)
我的问题在于Microsoft MediaRoom IPTV应用程序。事实证明,MPF MRML应用程序不支持cookie;更改为在web.config中使用无Cookie会话解决了我的问题
<sessionState cookieless="true" />
这是一篇关于它的真正的老文章: Cookieless ASP.NET
答案 6 :(得分:1)
我的问题是我们在web.config中设置了此设置
<httpCookies httpOnlyCookies="true" requireSSL="true" />
这意味着在非SSL(默认)下调试时,auth cookie不会被发送回服务器。这意味着服务器会为每个请求发回一个新的auth cookie(带有一个新会话)。
修复是在web.config中将requiressl设置为false,在web.release.config中设置为true,或在调试时启用SSL:
答案 7 :(得分:1)
就我而言,这在我的开发和测试环境中发生了很多。在尝试了所有上述解决方案但没有成功后,我发现我能够通过删除所有会话cookie来解决此问题。 Web开发人员扩展使这很容易做到。我主要使用Firefox进行测试和开发,但这也发生在使用Chrome进行测试时。该修复程序也适用于Chrome。
我还没有在生产环境中做到这一点,并且没有收到任何人无法登录的报告。这也似乎只是在使会话cookie安全之后才发生。过去,当它们不安全时,它从未发生过。
答案 8 :(得分:1)
在我的情况下是因为我在从外部应用程序中的网关重定向后修改了会话 ,所以因为我在该页面的本地主机上使用IP而不是它实际上被认为是不同的网站不同的会议。
总结
如果您在IIS而不是IIS express上调试托管应用程序并在各个页面中混合您的计算机http://Ip和http://localhost,则需要更加注意
答案 9 :(得分:1)
从.NET 4.7.2开始,这对我来说已经改变了,这是由于会话cookie上的SameSite属性所致。有关更多信息,请参见此处:https://devblogs.microsoft.com/aspnet/upcoming-samesite-cookie-changes-in-asp-net-and-asp-net-core/
默认值更改为“松散”并开始破坏。我将其更改为“无”,并且一切正常。
答案 10 :(得分:0)
请确保您没有非常短的会话超时,并确保如果您使用基于cookie的会话即表示您正在接受会话。
FireFox webDeveloperToolbar在这种情况下非常有用,因为您可以看到为您的应用程序设置的cookie。
答案 11 :(得分:0)
会话ID重置可能有很多原因。但是,上面提到的任何内容都与我的问题无关。所以我将其描述以供将来参考。
在我的情况下,在每个请求上创建的新会话导致无限重定向循环。重定向操作发生在 OnActionExecuting 事件中。
此外,我还清除了所有http标头(也使用 Response.ClearHeaders 方法在 OnActionExecuting 事件中),以防止在客户端缓存网站。但是该方法清除所有标题,包括关于用户会话的信息,以及因此临时存储中的所有数据(我稍后在程序中使用)。因此,即使在Session_Start事件中设置新会话也没有帮助。
为了解决我的问题,我确保在重定向发生时不删除标题。
希望它有所帮助。
答案 12 :(得分:0)
我以不同的方式遇到了这个问题。具有此属性[SessionState(SessionStateBehavior.ReadOnly)]
的控制器正在从不同的会话中读取,即使我在应用启动时在原始会话中设置了值。我是通过_layout.cshtml添加会话值的(也许不是最好的主意?)
显然ReadOnly导致了这个问题,因为当我删除属性时,原始会话(和SessionId)会保持原状。使用Claudio的/ Microsoft的解决方案修复了它。
答案 13 :(得分:0)
我使用的是.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”标题。