我的申请背景
我有一个安装了
apollo-server-express
包的 Express 应用程序,它允许我将 GraphQL 服务器附加到正在运行的 Express 服务器。
Express 服务器用于身份验证/授权(使用 Keycloak 和 Passport),GraphQL 服务器作为 API 层用于查询数据。
我想要完成什么
实现一种在用户处于非活动状态 10 分钟后自动注销的方法。 “非活动”定义为用户无法向 GraphQL 服务器进行查询。
我目前的策略
在初始化 Express 应用程序时创建一个全局变量,用于跟踪每个登录用户以及他们上次发出请求的时间。示例:
const userSessionTracker = {
userId1: 300000, // a user's timer: last time they logged in/made a request (in ms)
userId2: 5000,
...
}
每次用户登录/发出请求时,应用程序都会将计时器重置回 0。下次发出请求时,如果计时器超过 10 分钟,应用程序会将用户注销。
问题
当用户调用 GraphQL 查询时,我想检查/重置 GraphQL 查询解析器内的计时器。我怎样才能做到这一点?
我尝试过的
userSessionTracker
传递到 Apollo 服务器的 context
,使得可以从解析器的 contextValue
userSessionTracker
console.log(userSessionTracker)
来自 Express 服务器userSessionTracker
显示 GraphQL 解析器所做的编辑,但发现它仍保持编辑前的状态总之,我可以从 GraphQL 解析器内部访问
userSessionTracker
变量,但我无法编辑它,也无法从 Express 应用程序访问编辑后的版本。
这似乎是设计使然,正如 Apollo 文档指出的那样“解析器永远不应该破坏性地修改 contextValue 参数”。我怎样才能绕过这个限制?
解析器是实现此逻辑的错误位置 - 您需要在
context
函数中完成所有操作。在任何查询和解析器触发之前,来自用户的每个 GraphQL 请求都必须首先经过 context
函数,因此它是放置身份验证和超时逻辑的中心位置。解析器只能读取上下文,而不能更改它。
您甚至不需要查看解析器内的
userSessionTracker
,您只需要知道请求背后是否有经过身份验证的用户。
如果您使用 JWT,那么您可以简单地让 JWT 在 10 分钟后过期,但在过期之前随时收到请求时刷新它 - 这样每个经过身份验证的查询都会重新启动时钟。
存储会话过期服务器端意味着数据库或共享缓存,如果您想要扩展到多个服务器,您可以在其中管理过期时间。