首页 > 解决方案 > 获取会话状态而不从前端发送 HTTP 请求

问题描述

使用 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 is IHttpContextAccessor):

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

            return null;
        }

所以我们从SessionExtension. 但是可能有某种方法可以在不连接到后端的情况下获得它?

标签: c#asp.net-coreasp.net-identityasp.net-session

解决方案


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

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

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

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

然后,在您的 AJAX 回调中:

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

推荐阅读