Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在当前HTTPContext中生成新的ASP.NET会话_Asp.net_Session State_Sessionid_Httpsession - Fatal编程技术网

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

在当前HTTPContext中生成新的ASP.NET会话,asp.net,session-state,sessionid,httpsession,Asp.net,Session State,Sessionid,Httpsession,由于对我们正在生产的一些产品进行了渗透测试,当时看似“容易”解决的问题现在变成了一个棘手的问题 当然,这并不是说它应该,我的意思是为什么仅仅为当前的HTTPContext生成一个全新的会话会如此困难?奇怪的无论如何,我写了一个厚颜无耻的小实用程序类来“就这么做”: (对代码格式/突出显示/Visual Basic我一定是做错了什么表示歉意) 它可以很好地处理请求的其余部分,并正确地将自己标识为新会话(例如,HTTPContext.Current.session.SessionID返回新生成的会话

由于对我们正在生产的一些产品进行了渗透测试,当时看似“容易”解决的问题现在变成了一个棘手的问题

当然,这并不是说它应该,我的意思是为什么仅仅为当前的
HTTPContext
生成一个全新的会话会如此困难?奇怪的无论如何,我写了一个厚颜无耻的小实用程序类来“就这么做”:

(对代码格式/突出显示/Visual Basic我一定是做错了什么表示歉意)

它可以很好地处理请求的其余部分,并正确地将自己标识为新会话(例如,
HTTPContext.Current.session.SessionID
返回新生成的会话标识符)

令人惊讶的是,当下一个请求到达服务器时,
HTTPContext.Session
(一个
HTTPSessionState
对象)用正确的
SessionID
标识自己,但将
IsNewSession
设置为
True
,并且为空,丢失了上一个请求中设置的所有会话值

因此,从初始请求中删除的前一个
HTTPSessionState
对象,这里有一个事件处理程序,那里有一个回调,处理跨请求持久化会话数据的东西,或者我缺少的东西,一定有什么特别之处


有人有魔法可以分享吗?

你有没有考虑过使用?那应该会把一切都清理干净。然后启动一个新会话,并用上面代码中存储的所有项目填充它

Session.放弃()应该足够了。否则,如果它仍然很顽固,你可以尝试多打几个电话,多走一段路:

Session.Contents.Abandon();
Session.Contents.RemoveAll(); 
你不能只设置:

<sessionState regenerateExpiredSessionId="False" />


在web.config中,然后使用Ahmad建议的解决方案?

我想分享我的魔法。事实上,不,它还不神奇。。我们应该更多地测试和改进代码。 我只在cookie、InProc会话模式下测试了这些代码。将这些方法放入您的页面中,并在需要重新生成ID的位置调用它(请将您的web应用设置为完全信任):

我一直在挖掘.NET源代码(可在中获得),发现如果不破解会话管理机制的内部结构,我无法重新生成SessionID。所以我只做了-hack SessionStateModule内部字段,这样它会将当前会话保存到一个新的ID中。可能当前的HttpSessionState对象仍然具有以前的ID,但可能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, newId, 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, oldId, lockId)
    rqStateNotFoundField.SetValue(ssm, True)
    rqIdField.SetValue(ssm, newId)

End Sub

对于MVC4,请使用以下代码:

 System.Web.SessionState.SessionIDManager manager = new System.Web.SessionState.SessionIDManager();
            HttpContext Context = System.Web.HttpContext.Current;
            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)System.Web.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);

正如Gencer所提到的,ReleaseItemExclusive不会从存储中删除旧会话,这会导致该会话最终过期,并在Global.asax中调用session_End。这在生产中给我们带来了一个巨大的问题,因为我们正在会话结束时清除线程标识,正因为如此,用户自发地丢失了线程上的身份验证

下面是正确的代码

Dim oHTTPContext As HttpContext = HttpContext.Current

Dim oSessionIdManager As New SessionIDManager
Dim sOldId As String = oSessionIdManager.GetSessionID(oHTTPContext)
Dim sNewId As String = oSessionIdManager.CreateSessionID(oHTTPContext)

Dim bIsRedir As Boolean = False
Dim bIsAdd As Boolean = False
oSessionIdManager.SaveSessionID(oHTTPContext, sNewId, bIsRedir, bIsAdd)

Dim oAppContext As HttpApplication = HttpContext.Current.ApplicationInstance

Dim oModules As HttpModuleCollection = oAppContext.Modules

Dim oSessionStateModule As SessionStateModule = _
  DirectCast(oModules.Get("Session"), SessionStateModule)

Dim oFields() As FieldInfo = _
  oSessionStateModule.GetType.GetFields(BindingFlags.NonPublic Or _
                                        BindingFlags.Instance)

Dim oStore As SessionStateStoreProviderBase = Nothing
Dim oRqIdField As FieldInfo = Nothing
Dim oRqItem As SessionStateStoreData = Nothing
Dim oRqLockIdField As FieldInfo = Nothing
Dim oRqStateNotFoundField As FieldInfo = Nothing

For Each oField As FieldInfo In oFields
    If (oField.Name.Equals("_store")) Then
        oStore = DirectCast(oField.GetValue(oSessionStateModule), _
                            SessionStateStoreProviderBase)
    End If
    If (oField.Name.Equals("_rqId")) Then
        oRqIdField = oField
    End If
    If (oField.Name.Equals("_rqLockId")) Then
        oRqLockIdField = oField
    End If
    If (oField.Name.Equals("_rqSessionStateNotFound")) Then
        oRqStateNotFoundField = oField
    End If
    If (oField.Name.Equals("_rqItem")) Then
        oRqItem = DirectCast(oField.GetValue(oSessionStateModule), _
                             SessionStateStoreData)
    End If
Next

If oStore IsNot Nothing Then

    Dim oLockId As Object = Nothing

    If oRqLockIdField IsNot Nothing Then
        oLockId = oRqLockIdField.GetValue(oSessionStateModule)
    End If

    If (oLockId IsNot Nothing) And (Not String.IsNullOrEmpty(sOldId)) Then
        oStore.ReleaseItemExclusive(oHTTPContext, sOldId, oLockId)
        oStore.RemoveItem(oHTTPContext, sOldId, oLockId, oRqItem)
    End If

    oRqStateNotFoundField.SetValue(oSessionStateModule, True)
    oRqIdField.SetValue(oSessionStateModule, sNewId)

End If

如果您出于安全意识,希望此答案的C#版本删除旧字段,请使用以下命令

private static void RegenerateSessionId()
{

    // Initialise variables for regenerating the session id
    HttpContext Context = HttpContext.Current;
    SessionIDManager manager = new SessionIDManager();
    string oldId = manager.GetSessionID(Context);
    string newId = manager.CreateSessionID(Context);
    bool isAdd = false, isRedir = false;

    // Save a new session ID
    manager.SaveSessionID(Context, newId, out isRedir, out isAdd);

    // Get the fields using the below and create variables for storage
    HttpApplication ctx = HttpContext.Current.ApplicationInstance;
    HttpModuleCollection mods = ctx.Modules;
    SessionStateModule ssm = (SessionStateModule)mods.Get("Session");
    FieldInfo[] fields = ssm.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
    SessionStateStoreProviderBase store = null;
    FieldInfo rqIdField = null, rqLockIdField = null, rqStateNotFoundField = null;
    SessionStateStoreData rqItem = null;

    // Assign to each variable the appropriate field values
    foreach (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;
        if (field.Name.Equals("_rqItem")) rqItem = (SessionStateStoreData)field.GetValue(ssm);
    }

    // Remove the previous session value
    object lockId = rqLockIdField.GetValue(ssm);
    if ((lockId != null) && (oldId != null))
        store.RemoveItem(Context, oldId, lockId, rqItem);

    rqStateNotFoundField.SetValue(ssm, true);
    rqIdField.SetValue(ssm, newId);
}

不幸的是,这种方法似乎重用了相同的会话标识符。我需要生成一个新的会话标识符:(我通过给我的
SwitchSession
类一些状态(替换
会话)来改进它)并为活动的ASP.NET应用程序实例连接
SessionStateModule
事件。当
Start
事件触发时,它会检查ASP.NET派生的会话是否具有相同的
SessionID
,并将前一个请求中的所有会话状态值复制到其中。显然,只有当所有请求都通过时,它才会工作处理上一个请求的
HTTPApplication
实例。我正在使用reflector对
SessionStateModule
进行更深入的挖掘,但它并不漂亮。请投票支持这个问题!我到达了与您几乎相同的位置(通过搜索RemoveHttpSessionStateFromContext到达您的页面)。不幸的是,您也遇到了同样的问题-似乎无法生成新会话。关键当然是SessionStateModule.CompleteAcquiredState(),这是非常困难的-Yudhi的反射方法将是实现它的一种方法,但我不确定它是否值得这么麻烦。我必须说,尽管我非常喜欢C#,.NET的API非常令人失望-他们怎么能不公开它!仅供参考:CompleteAcquiredState()调用SessionStateUtility.AddDelayedHttpSessionStateToContext(),它为新会话发挥了所有的神奇作用。不幸的是,它仍然保留活动的
会话ID
,在下一个请求命中时使用该ID。但是在这种情况下,“过期”的含义是什么?我没有使会话过期-除了使客户端cookie过期之外,我看不到其他方法使会话“过期”。这对我的工作没有帮助虽然是活动的
HTTPContext
。但即使如此,使用此方法-在我放弃会话并删除所有内容后,我会对我的用户进行身份验证,并在会话中放置一些内容,因为会话已被“放弃”,在下一个请求时它是空的。:(:)(感谢您的贡献,我的结论与此类似,即会话状态模块的本机行为需要进行操作。提升到完全信任权限是一种耻辱,尤其是在修复
Dim oHTTPContext As HttpContext = HttpContext.Current

Dim oSessionIdManager As New SessionIDManager
Dim sOldId As String = oSessionIdManager.GetSessionID(oHTTPContext)
Dim sNewId As String = oSessionIdManager.CreateSessionID(oHTTPContext)

Dim bIsRedir As Boolean = False
Dim bIsAdd As Boolean = False
oSessionIdManager.SaveSessionID(oHTTPContext, sNewId, bIsRedir, bIsAdd)

Dim oAppContext As HttpApplication = HttpContext.Current.ApplicationInstance

Dim oModules As HttpModuleCollection = oAppContext.Modules

Dim oSessionStateModule As SessionStateModule = _
  DirectCast(oModules.Get("Session"), SessionStateModule)

Dim oFields() As FieldInfo = _
  oSessionStateModule.GetType.GetFields(BindingFlags.NonPublic Or _
                                        BindingFlags.Instance)

Dim oStore As SessionStateStoreProviderBase = Nothing
Dim oRqIdField As FieldInfo = Nothing
Dim oRqItem As SessionStateStoreData = Nothing
Dim oRqLockIdField As FieldInfo = Nothing
Dim oRqStateNotFoundField As FieldInfo = Nothing

For Each oField As FieldInfo In oFields
    If (oField.Name.Equals("_store")) Then
        oStore = DirectCast(oField.GetValue(oSessionStateModule), _
                            SessionStateStoreProviderBase)
    End If
    If (oField.Name.Equals("_rqId")) Then
        oRqIdField = oField
    End If
    If (oField.Name.Equals("_rqLockId")) Then
        oRqLockIdField = oField
    End If
    If (oField.Name.Equals("_rqSessionStateNotFound")) Then
        oRqStateNotFoundField = oField
    End If
    If (oField.Name.Equals("_rqItem")) Then
        oRqItem = DirectCast(oField.GetValue(oSessionStateModule), _
                             SessionStateStoreData)
    End If
Next

If oStore IsNot Nothing Then

    Dim oLockId As Object = Nothing

    If oRqLockIdField IsNot Nothing Then
        oLockId = oRqLockIdField.GetValue(oSessionStateModule)
    End If

    If (oLockId IsNot Nothing) And (Not String.IsNullOrEmpty(sOldId)) Then
        oStore.ReleaseItemExclusive(oHTTPContext, sOldId, oLockId)
        oStore.RemoveItem(oHTTPContext, sOldId, oLockId, oRqItem)
    End If

    oRqStateNotFoundField.SetValue(oSessionStateModule, True)
    oRqIdField.SetValue(oSessionStateModule, sNewId)

End If
private static void RegenerateSessionId()
{

    // Initialise variables for regenerating the session id
    HttpContext Context = HttpContext.Current;
    SessionIDManager manager = new SessionIDManager();
    string oldId = manager.GetSessionID(Context);
    string newId = manager.CreateSessionID(Context);
    bool isAdd = false, isRedir = false;

    // Save a new session ID
    manager.SaveSessionID(Context, newId, out isRedir, out isAdd);

    // Get the fields using the below and create variables for storage
    HttpApplication ctx = HttpContext.Current.ApplicationInstance;
    HttpModuleCollection mods = ctx.Modules;
    SessionStateModule ssm = (SessionStateModule)mods.Get("Session");
    FieldInfo[] fields = ssm.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
    SessionStateStoreProviderBase store = null;
    FieldInfo rqIdField = null, rqLockIdField = null, rqStateNotFoundField = null;
    SessionStateStoreData rqItem = null;

    // Assign to each variable the appropriate field values
    foreach (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;
        if (field.Name.Equals("_rqItem")) rqItem = (SessionStateStoreData)field.GetValue(ssm);
    }

    // Remove the previous session value
    object lockId = rqLockIdField.GetValue(ssm);
    if ((lockId != null) && (oldId != null))
        store.RemoveItem(Context, oldId, lockId, rqItem);

    rqStateNotFoundField.SetValue(ssm, true);
    rqIdField.SetValue(ssm, newId);
}