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:
//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.