简体   繁体   中英

Regenerate SessionID in ASP.NET

Please suggest how to regenerate a new Session ID in ASP.NET. If we are using SessionManager to generate a new id then it doesn't change the value of Session.SessionID. Please suggest how this can be achieved. Basically I want to have a new Session.SessionID after abandoning Session or generating NewID with SessionManager.

Thanks

Take a look onto SessionIDManager.SaveSessionID method, it saves a newly created session identifier to the HTTP response.:

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

We used Alex's solution but initially it did not work, the original sessionID returned and the newly generated sessionID was ignored. We tried a bunch of approaches and in the end what worked was to ensure the sessionID regeneration step sits outside any login step and that there is a redirect between steps. First we destroy the session cookie, then we recreate a new sessionID and lastly we redirect to the login page. The redirect before any log in is the critical step:

 //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");
//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);

The trick is to set any value in this.Session before redirecting , otherwise the "empty and therefor unusable session" will be recycled.

The example code below is the condensed version of some helper functions I'm using to share some session-related info across domains. First a server-to-server call is made to set up the session id; second the user's browser is redirected to a page that will set the session id and redirect to the front page (or somewhere more relevant).

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);
}

The above was tested by setting the session id late in the normal page cycle, in Page_Load . Might work differently if implemented in an HttpHandler or something like it. Also, this was implemented in a legacy ASP.NET 2.0 application and tested locally on IIS Express - your mileage may vary.

I thing, we need to make in this order:

  1. Generate a new SessionId with the SessionIdManager
  2. Save this new SessionId
  3. Set all variables attached to old session, to new session. Otherwise the session variables will be null in the new sessio

 //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); }

I tried adding this function and then calling it immediately done login, and it works for me.

Sources:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM