创建一个新的会话ID(无缝ID传输)

本文关键字:ID 会话 无缝 传输 一个 创建 | 更新日期: 2023-09-27 18:12:39

所以我遇到了一个有趣的问题,在登录/更改访问级别/等后实现会话ID滚动

登录时,我目前正在尝试使用SessionIDManager生成一个新的会话ID,但是这只会改变cookie头,它不会在HttpContext中交换会话,所以当我添加额外的详细信息到会话(各种详细信息将用户绑定到会话ID)时,它们立即丢失(更不用说旧会话被放弃了)。

为了防止会话劫持(通过存储主要的非ssl通信)和会话固定,我们应该在登录时生成一个新的会话ID,但是Microsoft似乎不允许您这样做(grr,那么多只读变量和没有构造函数的密封类)。我可以只迁移后端SQL中的所有数据,但这似乎有点"肮脏的hack"。

关于如何正确地做到这一点,有什么想法吗?

编辑:

我发现的实现:

Session.Abandon();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));

会话仍然是旧的会话,所以在下一页,所有的更改都将丢失。

SessionIDManager不返回SaveSessionID之后的会话对象,所以我不能添加细节到我刚刚创建的会话。在下一个页面加载我可以,但旧的会话现在是不可访问的(和放弃,但即使它没有放弃…)。

HttpContext。会话是只读的,即使它不是,httpessionstate也没有构造函数。

编辑2:

ASP中的会话固定。净

显然,会话固定和劫持在这里之前已经讨论过了,答案是"微软似乎并不关心",并且有一个执行不佳的两阶段修复。

创建一个新的会话ID(无缝ID传输)

好吧,这是一个小问题,展示了如何使用这种方法劫持基于身份验证的会话和基于身份验证的表单(你需要一个有效的用户帐户,但你可以劫持别人的会话),网上有一些博客抱怨会话固定和容易利用劫持的能力。所以很明显这是个大问题。Yahia指出微软对解决这个问题不感兴趣。

我所做的是创建一个与会话ID配对的真实性密钥,在登录时,我们会生成一个新的并将其放在会话中并给用户一个cookie,如果会话中有密钥,它们必须匹配,如果没有,我们会踢用户(劫持企图)。这似乎是在博客上提到的一种常见的方法(另一种方法是使用表单验证来加密cookie,虽然这很好,但我希望解决方案能够兼容多种类型的身份验证)。


推荐的一件事可以帮助防止使用另一个应用程序作为只提供302重定向的非ssl前端的任何非ssl通信,正如Yahia所建议的那样,虽然这首先有助于防止会话id的泄露,但它需要对应用程序的部署方式进行大量重组来修复,并且IMO:. net的不可靠的会话管理应该首先修复,我希望我们的应用程序从一开始就完全安全,而不是依赖于其他应用程序进行302重定向,这样任何信息泄漏都是无关紧要的,因为cookie将在登录时旋转。

您看过FormsAuthentication.SetAuthCookie方法吗?

试试这样写:

FormsAuthentication.SignOut();
HttpContext.Current.Session.Abandon();
FormsAuthentication.SetAuthCookie(newCode, true);

希望这对你有帮助....

我的回答有点晚了,但我正在寻找同样的东西,所以我想我应该发布我发现的…比起使用SessionIdManager来重置cookie,安装自定义会话id管理器似乎是一个更好的"钩子":

<sessionState mode="InProc" ... 
              sessionIDManagerType="MyAssembly.SessionFixationIdManager, MyAssembly" />

然后,我使用现有的SessionIdManager实现了我的ISessionIdManager。例如:

class SessionFixationIdManager : ISessionIDManager
{
    private SessionIDManager _originalManager = new SessionIDManager();
    public string CreateSessionID(System.Web.HttpContext context)
    {
        // Default process for creating session IDs is fine...
        return _originalManager.CreateSessionID(context);
    }
    etc.
}

唯一不同的方法是GetSessionID方法—如果请求未经过身份验证,则忽略传入的cookie并发出一个新cookie:

public string GetSessionID(System.Web.HttpContext context)
{
    // Never use a session ID from an unauthenticated request...
    if (!context.Request.IsAuthenticated) 
        return null;
    return _originalManager.GetSessionID(context);
}

这样做,似乎可以保证:

  1. 会话ID cookie将在对用户进行身份验证的响应上重新发布。我正在使用表单认证,所以这是发出表单认证Cookie的响应

  2. 我实际上可以在我认证用户的请求上使用会话 -因为在会话被分配给该请求的上下文之前,会话ID被重新分配

现在,这仅仅是安全工作的开始。例如,我仍然需要做一些事情来将会话绑定到经过身份验证的用户(例如,将一些会话值加密到表单身份验证cookie中)。这意味着我不能在登录过程中使用Session State(它必须作为单个请求处理,或者使用ViewState等)。

但是我认为这保证了未经身份验证的用户不能执行会话固定。

老实说,我还不确定这是否值得。针对每个请求的会话验证表单身份验证数据(或其他一些真实性密钥)可能提供相同级别的安全性,而无需跳过这些额外的障碍。但是实现安全最佳实践是一个目标,而且我认为这可以在没有失去初始请求的所有上下文的两阶段解决方案的情况下工作…)