在当前的HTTPContext中生成一个新的ASP.NET会话

前端之家收集整理的这篇文章主要介绍了在当前的HTTPContext中生成一个新的ASP.NET会话前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
由于对我们的一些产品进行了渗透测试,当时看起来是一个很容易解决的问题,这是一个艰难的任务。

不是说当然这应该是为什么只是为当前的HTTPContext生成一个全新的会话呢?奇怪的!无论如何 – 我写了一个厚脸皮的小实用类,“只是做到这一点:”

(道歉代码格式/突出显示/ Visual Basic我必须做错事)

Imports System.Web
Imports System.Web.SessionState

Public Class SwitchSession

    Public Shared Sub SetNewSession(ByVal context As HttpContext)
        ' This value will hold the ID managers action to creating a response cookie
        Dim cookieAdded As Boolean
        ' We use the current session state as a template
        Dim state As HttpSessionState = context.Session
        ' We use the default ID manager to generate a new session id
        Dim idManager As New SessionIDManager()
        ' We also start with a new,fresh blank state item collection
        Dim items As New SessionStateItemCollection()
        ' Static objects are extracted from the current session context
        Dim staticObjects As HttpStaticObjectsCollection = _
            SessionStateUtility.GetSessionStaticObjects(context)
        ' We construct the replacement session for the current,some parameters are new,others are taken from prevIoUs session
        Dim replacement As New HttpSessionStateContainer( _
                 idManager.CreateSessionID(context),_
                 items,_
                 staticObjects,_
                 state.Timeout,_
                 True,_
                 state.CookieMode,_
                 state.Mode,_
                 state.IsReadOnly)
        ' Finally we strip the current session state from the current context
        SessionStateUtility.RemoveHttpSessionStateFromContext(context)
        ' Then we replace the assign the active session state using the replacement we just constructed
        SessionStateUtility.AddHttpSessionStateToContext(context,replacement)
        ' Make sure we clean out the responses of any other inteferring cookies
        idManager.RemoveSessionID(context)
        ' Save our new cookie session identifier to the response
        idManager.SaveSessionID(context,replacement.SessionID,False,cookieAdded)
    End Sub

End Class

它对于请求的其余部分工作正常,并且将其自身正确地标识为新的会话(例如,HTTPContext.Current.Session.SessionID返回新生成的会话标识符)。

惊奇的是,当下一个请求命中服务器时,HTTPContext.Session(一个HTTPSessionState对象)使用正确的SessionID标识自身,但是将IsNewSession设置为True,并且为空,从而丢失先前请求中设置的所有会话值。

因此,先前的HTTPSessionState对象从初始请求中删除,这里的一个事件处理程序,这里的一个回调,一些处理在请求之间持久化会话数据的东西,还是仅仅是我缺少的东西?

有人有任何魔法分享吗?

解决方法

我想分享我的魔法。其实不,它还没有神奇..我们应该测试和演变代码更多。
我只用in-cookie,InProc会话模式测试了这些代码。将这些方法放在您的页面中,并将其称为需要重新生成ID的位置(请将您的网络应用设置为完全信任):
void regenerateId()
{
    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);
}

我一直在挖掘.NET源代码(在http://referencesource.microsoft.com/netframework.aspx中可用),并发现没有办法可以重新生成SessionID,而不会窃取会话管理机制的内部。所以我只是这样 – 将SessionStateModule内部的字段,因此它将保存当前会话到一个新的ID。也许当前的HttpSessionState对象仍然具有以前的Id,但是AFAIK的SessionStateModule忽略它。当它必须在某个地方保存状态时,它只需使用内部_rqId字段。我已经尝试过其他方法,像将SessionStateModule复制到具有重新生成ID功能的新类(我计划用此类替换SessionStateModule),但失败,因为它目前已经引用了其他内部类(如InProcSessionStateStore)。使用反思的黑客的缺点是我们需要将我们的应用设置为“完全信任”。

哦,如果你真的需要VB版本,请尝试这些:

Sub RegenerateID()
    Dim manager
    Dim oldId As String
    Dim newId As String
    Dim isRedir As Boolean
    Dim isAdd As Boolean
    Dim ctx As HttpApplication
    Dim mods As HttpModuleCollection
    Dim ssm As System.Web.SessionState.SessionStateModule
    Dim fields() As System.Reflection.FieldInfo
    Dim rqIdField As System.Reflection.FieldInfo
    Dim rqLockIdField As System.Reflection.FieldInfo
    Dim rqStateNotFoundField As System.Reflection.FieldInfo
    Dim store As SessionStateStoreProviderBase
    Dim field As System.Reflection.FieldInfo
    Dim lockId
    manager = New System.Web.SessionState.SessionIDManager
    oldId = manager.GetSessionID(Context)
    newId = manager.CreateSessionID(Context)
    manager.SaveSessionID(Context,isRedir,isAdd)
    ctx = HttpContext.Current.ApplicationInstance
    mods = ctx.Modules
    ssm = CType(mods.Get("Session"),System.Web.SessionState.SessionStateModule)
    fields = ssm.GetType.GetFields(System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)
    store = Nothing : rqLockIdField = Nothing : rqIdField = Nothing : rqStateNotFoundField = Nothing
    For Each field In fields
        If (field.Name.Equals("_store")) Then store = CType(field.GetValue(ssm),SessionStateStoreProviderBase)
        If (field.Name.Equals("_rqId")) Then rqIdField = field
        If (field.Name.Equals("_rqLockId")) Then rqLockIdField = field
        If (field.Name.Equals("_rqSessionStateNotFound")) Then rqStateNotFoundField = field
    Next
    lockId = rqLockIdField.GetValue(ssm)
    If ((Not IsNothing(lockId)) And (Not IsNothing(oldId))) Then store.ReleaseItemExclusive(Context,lockId)
    rqStateNotFoundField.SetValue(ssm,True)
    rqIdField.SetValue(ssm,newId)

End Sub

猜你在找的asp.Net相关文章