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

ASP.NET:Session.SessionID在请求之间更改,asp.net,session,sessionid,Asp.net,Session,Sessionid,为什么ASP.NET页面中的会话-对象的SessionID属性在请求之间发生更改 我有这样一个页面: ... <div> SessionID: <%= SessionID %> </div> ... 。。。 会话ID: ... 每次我点击F5时,输出都会不断变化,与浏览器无关。请确保您没有很短的会话超时,并且如果您使用的是基于cookie的会话,请确保您正在接受该会话 FireFox webDeveloperToolbar在这种情况下非常有用,因为

为什么ASP.NET页面中的会话-对象的SessionID属性在请求之间发生更改

我有这样一个页面:

...
<div>
    SessionID: <%= SessionID %>
</div>
...
。。。
会话ID:
...

每次我点击F5时,输出都会不断变化,与浏览器无关。

请确保您没有很短的会话超时,并且如果您使用的是基于cookie的会话,请确保您正在接受该会话

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

这就是原因所在

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

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

编辑

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

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

还有另一个更隐秘的原因,为什么即使会话对象已经初始化,也会发生这种情况,如Cladudio所示

在Web.config中,如果有一个
条目被设置为
requireSSL=“true”
,但您实际上没有为特定请求使用HTTPS:

我很难找到这个问题,在我的源代码管理中花了几个小时在几次提交之间来回搜索,直到我发现什么具体的更改破坏了我的应用程序。

使用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;
                }
            }
        }

在我的例子中,我发现会话cookie有一个包含
www.
前缀的域,而我请求的页面没有
www.


向URL添加
www.
立即解决了问题。后来我将cookie的域设置为
.mysite.com
,而不是
www.mysite.com

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

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


进一步信息:

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

<sessionState cookieless="true"  />

这是一篇非常古老的文章:

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

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

此外,我一直在清除所有http头(也是在OnActionExecuting事件中使用Response.ClearHeaders方法),以防止在客户端缓存站点。但该方法清除所有头,包括有关用户会话的信息,以及临时存储中的所有数据(我稍后在程序中使用)因此,即使在会话启动事件中设置新会话也没有帮助

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


希望它能帮助别人。

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

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

修复方法是在web.config中将requiressl设置为false,在web.release.config中将其设置为true,或者在调试时启用SSL:


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


这显然是导致问题的只读原因,因为当我删除该属性时,原始会话(和SessionId)将保持机智。使用Claudio/Microsoft的解决方案解决了此问题。

在我的开发和测试环境中,这种情况经常发生。在尝试了上述所有解决方案但未取得任何成功后,我发现我能够通过删除所有会话cookie来解决此问题。web developer扩展使此操作非常容易。我大多数情况下使用Firefox进行测试和数据挖掘
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));
        }
    }
}
services.AddCors(o => o.AddPolicy("AllowAll", builder =>
            {
                builder
                    .WithOrigins("http://localhost:3000")     // important
                    .AllowCredentials()                       // important
                    .AllowAnyMethod()
                    .AllowAnyHeader();       // obviously just for testing
            }));
const resp = await fetch("https://localhost:5001/api/user", {
            method: 'POST',
            credentials: 'include',                           // important
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(data)
        })
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 };
        }
    }
}