【问题标题】:Regenerate SessionID in ASP.NET在 ASP.NET 中重新生成 SessionID
【发布时间】:2011-03-31 15:36:04
【问题描述】:

请建议如何在 ASP.NET 中重新生成新的会话 ID。如果我们使用 SessionManager 来生成一个新的 id,那么它不会改变 Session.SessionID 的值。请建议如何实现这一点。基本上我想在放弃 Session 或用 SessionManager 生成 NewID 后有一个新的 Session.SessionID。

谢谢

【问题讨论】:

    标签: c# asp.net


    【解决方案1】:

    看一下SessionIDManager.SaveSessionID 方法,它将新创建的会话标识符保存到 HTTP 响应中。:

    SessionIDManager manager = new SessionIDManager();
    var newId = manager.CreateSessionID(Context);
    var isRedirected = false;
    var isAdded = false;
    manager.SaveSessionID(Current, newId, out isRedirected, out isAdded);
    

    【讨论】:

    • 我们试过了,但 Session.SessionID 没有采用新生成的数字。谢谢你。任何帮助表示赞赏。
    • @user686021,您能否使用web.config 中与会话相关的部分来扩展您的问题。我还想在manager.SaveSessionID 方法调用之后查看isRedirectedisAdded 变量的值。
    • 查看创建 id 的 CreateSessionID 方法。 SaveSessionId 仅用于将生成的 id 附加到响应(cookies/url)。
    【解决方案2】:
    //Regenerate new Session ID after login
    private void RegenerateSessionId()
    {
        System.Web.SessionState.SessionIDManager manager = new System.Web.SessionState.SessionIDManager();
        string oldId = manager.GetSessionID(Context);
        string newId = manager.CreateSessionID(Context);
        bool isAdd = false, isRedir = false;
        manager.SaveSessionID(Context, newId, out isRedir, out isAdd);
        HttpApplication ctx = (HttpApplication)HttpContext.Current.ApplicationInstance;
        HttpModuleCollection mods = ctx.Modules;
        System.Web.SessionState.SessionStateModule ssm = (SessionStateModule)mods.Get("Session");
        System.Reflection.FieldInfo[] fields = ssm.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
        SessionStateStoreProviderBase store = null;
        System.Reflection.FieldInfo rqIdField = null, rqLockIdField = null, rqStateNotFoundField = null;
        foreach (System.Reflection.FieldInfo field in fields)
        {
            if (field.Name.Equals("_store")) store = (SessionStateStoreProviderBase)field.GetValue(ssm);
            if (field.Name.Equals("_rqId")) rqIdField = field;
            if (field.Name.Equals("_rqLockId")) rqLockIdField = field;
            if (field.Name.Equals("_rqSessionStateNotFound")) rqStateNotFoundField = field;
        }
        object lockId = rqLockIdField.GetValue(ssm);
        if ((lockId != null) && (oldId != null)) store.ReleaseItemExclusive(Context, oldId, lockId);
        rqStateNotFoundField.SetValue(ssm, true);
        rqIdField.SetValue(ssm, newId);
    }
                    //get sessionId
                string SessionId = HttpContext.Current.Session.SessionID; //new System.Web.SessionState.SessionIDManager().GetSessionID(Context);
    

    【讨论】:

    • 其他解决方案正在刷新会话,但我总是无法成功登录。这个解决方案确实对我有用,但我真的不知道如何。是否有可能对那些反射(有点“hacky”)调用有用的东西进行遮蔽?
    【解决方案3】:

    我们使用了 Alex 的解决方案,但最初它不起作用,返回了原始 sessionID,并且忽略了新生成的 sessionID。我们尝试了很多方法,最终奏效的是确保 sessionID 重新生成步骤位于任何登录步骤之外,并且步骤之间存在重定向。首先我们销毁会话 cookie,然后我们重新创建一个新的 sessionID,最后我们重定向到登录页面。任何登录前的重定向是关键步骤:

     //delete session cookie
     Session.Abandon();
     Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));
    
     //create new sessionID
     SessionIDManager manager = new SessionIDManager();
     manager.RemoveSessionID(System.Web.HttpContext.Current);
     var newId = manager.CreateSessionID(System.Web.HttpContext.Current);
     var isRedirected = true;
     var isAdded = true;
     manager.SaveSessionID(System.Web.HttpContext.Current, newId, out isRedirected, out isAdded);
    
     //redirect so that the response.cookies call above actually enacts
     Response.Redirect("/account/logon");
    

    【讨论】:

    • 嗯,我认为这个解决方案没有抓住重点。您想在登录后更改会话 ID。否则会话固定攻击仍然是可能的,因为来自登录页面的提交具有将在授予权限后使用的会话 ID。
    【解决方案4】:

    诀窍是在重定向之前在this.Session 中设置任何值,否则“空且因此无法使用的会话”将被回收。

    下面的示例代码是我用来跨域共享一些会话相关信息的一些帮助函数的精简版本。首先进行服务器到服务器调用以设置会话 ID;其次,用户的浏览器被重定向到一个页面,该页面将设置会话 ID 并重定向到首页(或更相关的地方)。

    private static string CreateSessionId(HttpContext httpContext)
    {
        var manager = new SessionIDManager();
    
        string newSessionId = manager.CreateSessionID(httpContext);
    
        return newSessionId;
    }
    
    public static void SetSessionId(HttpContext httpContext, string newSessionId, string redirect)
    {
        var manager = new SessionIDManager();
    
        bool redirected;
        bool cookieAdded;
    
        manager.SaveSessionID(httpContext, newSessionId, out redirected, out cookieAdded);
    
        // Just write anything to the session, so it isn't abandoned
        httpContext.Session["WriteAnythingToTheSession"] = "Ok boss, consider it done!";
    
        httpContext.Response.Redirect(redirect, true);
    }
    

    上面的测试是通过在正常页面周期的后期设置会话 ID,在Page_Load 中进行的。如果在 HttpHandler 或类似的东西中实现,可能会有所不同。此外,这是在旧版 ASP.NET 2.0 应用程序中实现的,并在 IIS Express 上进行了本地测试 - 您的情况可能会有所不同。

    【讨论】:

    • 我知道我晚了 3 年。但是,如果您想使用这个新的 SessionID 发送会话数据,它就会从我这里丢失。就像如果在接下来的操作中我想使用 .Session["WriteAnythingToTheSession"] 它只是空的。它被保存到上一个会话。
    • @SomeRandomName:重点不是保存值,而是激活会话,可以这么说。
    • 但是如果你想将数据保存到这个新会话中怎么办。 ?
    • @SomeRandomName:在这种情况下,我们设置了第二次重定向之后的所有值;这段代码只是为了在第二台服务器上设置新的会话 ID。不幸的是,我无法显示更多代码。
    猜你喜欢
    • 2012-08-22
    • 2013-07-07
    • 2013-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-25
    • 1970-01-01
    • 2017-10-17
    相关资源
    最近更新 更多