pnoeric
(Eric)
1
你好,我收到消息说我的几位论坛成员在 20 到 30 分钟后会自动被登出。
我使用了 SSO,所以我在想问题是否出在:他们先登录主站,然后进入 Discourse(这会在那里启动一个新会话?),再回到主站(此时 Discourse 处于空闲状态),最后再次进入 Discourse 时却莫名被登出。
不过,这似乎不太合理,因为每次他们进入 Discourse 时,应该都会将“空闲超时”重置为 0,对吧?
我在 meta 板块找到了几个关于超时等问题的讨论帖,但似乎都没有明确的答案。
问题:是否有某个设置可以防止成员在空闲 X 时间之前被登出?我似乎找不到这个选项。
我在 Discourse 设置中看到“最大会话时长”已设置为 1 小时,但我不认为这在 SSO 实现中会有什么影响,对吧?(注意:当成员在我的主站登出时,我会向 Discourse 发送一个 /logout 消息,以保持一切整洁。而且,每当成员在 Discourse 中进行任何活动时,我都会更新主站上的最后活动时间,因此并非主站超时。我现在正在添加额外的调试代码以确认这一切是否按预期工作。)
谢谢,
E
david
(David Taylor)
2
它确实适用于 SSO,因此这很可能是您遇到问题的根源。在 1 小时无活动后,Discourse 会话将被终止,用户必须重新通过 SSO 进行身份验证。
pnoeric
(Eric)
3
没问题,这完全合理……如果 1 小时无活动,用户应该会被登出。
问题在于,我收到了关于用户在 20-30 分钟后就被登出的报告。
有没有设置可以调整这个 1 小时的空闲超时时间?正如我在原帖中提到的,我找不到相关设置……这似乎应该是首先检查的地方,对吧?
david
(David Taylor)
4
为了排除最明显的原因……有没有可能人们对确切时间记错了?30 分钟和 1 小时的差别其实不大 
要继续排查这个问题,建议下一步查看 user_auth_tokens 和 user_auth_token_logs 表中的可用数据。这些表包含了所有关于会话令牌及其过期的信息。
pnoeric
(Eric)
6
同意
我正在测试它——登录我的网站,进入论坛,然后把浏览器放着不管!
感谢关于数据库表的提示,我会进一步调查。
pnoeric
(Eric)
7
嗯。当用户使用论坛并阅读话题等时,如果他们执行了某个会触发操作的行为(如 create_post、create_topic、edit_post 等),我就会通过 webhook 收到一条消息。这会通知主站该用户仍处于活跃状态,从而我可以更新其会话的“最后点击时间”值,防止其被登出。这本来应该是正确的,一切正常。
然而,如果某个成员只是长时间阅读消息……他们的 Discourse 空闲时间确实会在每次操作时被重置(这很好),但我的主站从未收到任何 webhook 消息来表明该用户是活跃的。因此,如果超过 1 小时没有任何活动(看起来像是他们去了论坛却离开了电脑),主站就会认为他们已离线并将其登出。
这似乎存在逻辑漏洞。对于正确的 SSO 实现,Discourse 是否应该有一种方式可以告知我用户的会话是否活跃(即使他们只是在阅读)?也许 Discourse 应该在用户活跃但未触发其他 webhook 消息时,每隔 5 分钟发送一次心跳检测。
或者,当我的站点认为用户已超时,我是否可以调用 Discourse 来询问该用户在其平台上是否仍活跃?有没有这样的方法?(我注意到 https://meta.discourse.org/t/is-there-an-endpoint-to-check-if-a-user-is-logged-in/72780/3,但我不太确定那是否正是我需要的,而且 /session/current.json 并未出现在 API 文档中。)不过,这样做会产生大量的 API 调用——我的站点每分钟因不活跃而登出约 15-20 个用户,这意味着需要为每个用户发起调用(如果我没有缓存他们的 Discourse ID,甚至可能需要多次调用)。
朋友们,你们怎么看或有什么建议?
david
(David Taylor)
8
每个个人资料端点都有一个 last_seen 值,你可以利用它。
我认为在任何 SSO 协议中都没有见过这种设置,我们也未曾收到过此类需求。更常见的做法是保持两个系统相互独立。
如果你确实想创建一个“用户已查看”的 webhook,或许可以通过自定义插件来实现。
pnoeric
(Eric)
9
我不太明白你所说的“保持两个系统独立”具体指什么?如果我忽略了某种显而易见的解决方案,请告诉我!
否则,我的选项似乎有以下几个:
-
当用户在主网站超时但尚未登出时,调用 Discourse 并检查 last_seen 值,以确认该成员是否实际上在论坛中有活动(只是没有触发 webhook 调用)。 优点:易于实现。 缺点:会产生大量 API 调用,而这正是我目前头疼并不得不绕开速率限制去处理的问题。
-
开发自己的插件,定期向主网站发送 ping 请求,以便更新主网站上用户的最后活动时间。 优点:感觉更像是“正确”的解决方案(通过推送消息来指示活动);某种程度上很优雅。 缺点:实现难度较大。
-
将主网站的登出时间延长至 2 小时。 优点:易于实现。 缺点:有什么坏处吗?
-
不管它。用户在 Discourse 会话中途被登出,然后大发牢骚。这就是我目前的情况。
优点:易于实现,哈哈。 缺点:用户体验极差。
我是否遗漏了什么?
看起来 #3 是个不错的方案,但我需要仔细权衡主网站登出时间延长带来的影响。
我仍然认为 #1 是最佳选择,但我得想办法解决那些该死的速率限制问题。我真希望能在 Discourse(以及 nginx,因为我使用的是 Discourse Docker 安装)中全局关闭所有速率限制,彻底关掉。我根本不需要这些限制。只有我的主网站在调用我的 Discourse 实例。我不允许用户 API 密钥,而且只有我拥有系统 API 密钥。这是一个完全封闭的系统,速率限制除了(不断地)给我添乱之外毫无用处。我想这算是另一个话题了。
david
(David Taylor)
10
如果您需要保持您概述的行为,那么是的,我认为这确实是四个选项。但如果您稍微调整一下行为,它将更好地与现有工具配合使用。
您的设置中不寻常的部分是:
只要主站上的会话过期,您就会终止 Discourse 会话。如果移除这一部分,我认为该设置将与典型设置相符。
当用户从您的主站显式注销时,您仍然可以调用 /logout。只是不要在会话自然过期时调用它。
bts
(Brendan Schlagel)
11
从原帖中无法判断,但你们是在运营一个围绕用户分享高度敏感信息的专门网站,还是大多数用户都从共享的公共电脑登录?
目前看来最简单的解决方案就是不要过于激进地设置用户会话过期和强制登出。作为用户,我的偏好始终是“除非我明确点击登出,否则永远不要让我退出”。如果这不可行,能否至少将期限设置为一天或一周之类的?
pnoeric
(Eric)
12
明白了——这是个不错的解决方案;我想足够多的成员在登录页面勾选了“保持登录状态”复选框,这样将他们无缝带回主站会很顺畅。如果他们在主站的会话已过期,此时(在后台)就会立即重新登录。嗯。
这是一个面向对隐私极为敏感的特定人群的网站。不过我明白你的意思,我想我可以按照你(和 David)的建议去做。
非常感谢你们两位。 我之前对这里的“大局”或如何处理此类场景缺乏清晰认识……现在我了解了 :-),也看到了针对我情况的几种可能解决方案。非常感谢!