【问题标题】:Fetching session state without sending HTTP request from front end获取会话状态而不从前端发送 HTTP 请求
【发布时间】:2018-09-24 10:57:06
【问题描述】:

使用 Reactjs + Redux + Saga 设置 ASP.NET Core。当 asp.net 核心会话过期时,它需要通知用户。但问题是通过发送 GET 请求来检查我们扩展会话的会话状态,这意味着会话将永远不会结束,除非浏览器中的选项卡将被关闭(然后 GET 请求将不会被发送)。这是会话设置Startup.cs

services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromSeconds(60 * 60);
                options.Cookie.HttpOnly = true;
            });

然后我们每 5 分钟从客户端发送一次请求以获取身份:

function* checkSessionIsValid() {
    try {
        const response = yield call(axios.get, 'api/Customer/FetchIdentity');

            if (!response.data) {
                return yield put({
                    type: types.SESSION_EXPIRED,
                });

            yield delay(300000);
            return yield put({ type: types.CHECK_SESSION_IS_VALID });
        }
        return;
    } catch (error) {
        return;
    }
}

而后端端点(_context 是IHttpContextAccessor):

        [HttpGet("FetchIdentity")]
        public LoginInfo GetIdentity()
        {
            if (SessionExtension.GetString(_context.Session, "_emailLogin") != null)
            {
                return new LoginInfo()
                {
                    LoggedInWith = "email",
                    LoggedIn = true,
                    Identity = ""
                };
            }

            return null;
        }

所以我们从SessionExtension 获取会话信息。但是可能有一些方法可以在不连接到后端的情况下获得它?

【问题讨论】:

  • 当您拨打GetIdentity 时,是否设置了任何cookie(检查Chrome 开发者工具中的网络选项卡)?
  • @mjwills 我认为每次您发送请求或访问 SessionExtension 类时,cookie 都会使用新的时间戳进行更新,但它们是加密的,您无法从中读取
  • 您能否向我们展示来自 Chrome 开发者工具的 cookie 的详细信息 - 包括它们何时到期?

标签: c# asp.net-core asp.net-identity asp.net-session


【解决方案1】:

您的要求是不可能的,坦率地说,当您了解会话的工作原理时,它没有任何意义。会话仅存在于请求的上下文中。 HTTP 是一种无状态协议。会话本质上是通过让服务器和客户端传递“会话 id”来伪造状态。当服务器想要与客户端建立“会话”时,它会向客户端发出会话 ID,通常通过 Set-Cookie 响应头。然后,客户端将在每个后续请求中传回此 ID,通常通过 Cookie 请求标头。当服务器接收到这个 id 时,它会从 store 中查找相应的 session,然后可以访问之前的任何状态。

关键是如果没有请求首先,服务器不会知道或关心特定会话的情况。到期部分发生在服务器下一次尝试查找会话时。如果时间过长(会话过期),那么它会销毁前一个会话并创建一个新会话。它不会主动监视会话以在特定时间做任何事情。而且,正如您所指出的,会话是滑动的,到期时间范围内的每个请求都会重置该时间范围。因此,只要客户端积极使用会话,会话就永远不会过期。

总而言之,了解会话状态的唯一方法是使用会话 ID 发出请求,以提示服务器尝试恢复该会话。如果您想在客户端跟踪会话到期,您可以做的最好的事情是根据已知的超时设置一个计时器客户端。然后,您需要在每次进一步请求时重置所述时间。

 var sessionTimeout = setTimeout(doSomething, 20 * 60 * 1000); // 20 minutes

然后,在您的 AJAX 回调中:

 clearTimeout(sessionTimeout);
 sessionTimeout = setTimeout(doSomething, 20 * 60 * 1000);

【讨论】:

  • 我想可能只有 2 种可能的解决方法,例如首先是在标头中发送时间戳并设置计时器,其次是使用 SignalR 之类的东西。由于我想与后端会话完全同步,我不想在前端硬编码计时器
【解决方案2】:

也许可以使用 SessionState 属性。

[SessionState(SessionStateBehavior.Disabled)]

https://msdn.microsoft.com/en-US/library/system.web.mvc.sessionstateattribute.aspx?cs-save-lang=1&cs-lang=cpp

编辑:意识到您正在使用 .NET Core,不确定截至今天是否存在 SessionState 属性或类似属性。

【讨论】:

    猜你喜欢
    • 2012-03-09
    • 1970-01-01
    • 2015-02-11
    • 2015-12-22
    • 1970-01-01
    • 2023-03-16
    • 2013-10-24
    • 2010-11-25
    相关资源
    最近更新 更多