# 会话超时

**URL:** https://meta.discourse.org/t/session-timeout/34686
**Category:** Data & reporting
**Created:** [2015年十月19日 19:26 UTC](https://meta.discourse.org/t/session-timeout/34686 "2015-10-19T19:26:35Z")
**Posts on this page:** 20
**Page:** 3

<div class="post-metadata">

### Author: ![peteratkins](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/peteratkins/32/190723_2.png) [@peteratkins](https://meta.discourse.org/u/peteratkins)
#### Post date: [2020年九月8日 16:19 UTC](https://meta.discourse.org/t/session-timeout/34686/41 "2020-09-08T16:19:12Z")

</div>

Stephen，我理解你的 reasoning，但这并非危言耸听。

IT 人员每天都在与缺乏意识或所谓的“愚钝用户”打交道。我们努力建立能够应对各种突发情况的系统，这并不容易。如今身份验证至关重要，而正是测试让我们发现了这个问题——如果能提前告知一声就好了，尤其是考虑到这个问题从 2016 年就开始讨论（并在修复后）。

我原本希望是自己遗漏了什么，或是配置有误，但现在我知道这是按设计运行的。我们将寻找外部解决方案，并为用户记录相关说明。希望未来有人能施加压力，推动在 Discourse 内部解决这一问题。

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [2020年九月8日 16:48 UTC](https://meta.discourse.org/t/session-timeout/34686/42 "2020-09-08T16:48:25Z")

</div>

> [@peteratkins](#):
>
> 基本上，我需要用户在关闭浏览器且已通过 SSO 登录后被登出。

但如果用户忘记关闭浏览器呢？这该怎么处理？

> [@Falco](#):
>
> 这正是我的补丁所做的，但后来被回退了。

不过我很好奇，@falco，2016 年的补丁为什么被回退了？是因为这是一个不安全的更改吗？

---

<div class="post-metadata">

### Author: ![Sailsman63](https://avatars.discourse-cdn.com/v4/letter/s/b5ac83/32.png) [@Sailsman63](https://meta.discourse.org/u/Sailsman63)
#### Post date: [2020年九月8日 17:00 UTC](https://meta.discourse.org/t/session-timeout/34686/43 "2020-09-08T17:00:25Z")

</div>

有些观点确实有道理。

不过，你举的几个例子让我相当震惊：

医院：我近几年去过的医院绝对_确实_设有独特的自动锁定机制，甚至护士去处理几秒钟的验血工作后，也需要重新登录。

在急诊室，可能会有一些专门系统能访问与急救相关的数据，但它们不应访问个人身份信息（PII），也不应访问部门聊天论坛。

图书馆：  
我所在的所有当地公共图书馆（包括一些_非常_小的城镇、技术不熟练的工作人员）都使用通用的登录 ID（所有用户通用，直接张贴在显示器上）。它们也实行“离开即重启”的政策，所有人都被要求遵守，包括孩子们。重启过程会自动清除浏览器历史记录、缓存和 Cookie。

我并不是说在言论方面采取更谨慎的政策不好，只是这个话题中列出的一些“引发”情境让我感到担忧，因为论坛帖子被错误归因，远非他们面临的最大问题。

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2020年九月8日 17:27 UTC](https://meta.discourse.org/t/session-timeout/34686/44 "2020-09-08T17:27:07Z")

</div>

> [@codinghorror](#):
>
> > [@Falco](#):
> >
> > 这正是我的补丁所做的，但后来被回退了。
> 
> 不过我很好奇，@falco，为什么 2016 年的补丁被回退了？是因为这是一个不安全的更改吗？

时间线如下：

- 2012 年 – 2016 年 5 月：Discourse 会话 Cookie 始终设置为永久有效。

- 2016 年 5 月 – 2016 年 7 月：Discourse 会话 Cookie 默认设置为永久有效，但可通过站点设置使其在浏览器关闭时失效。

- 2016 年 7 月 – 至今：Discourse 会话 Cookie 设置为 1440 小时，使用时刷新。站点设置可控制其最大有效期。浏览器会话 Cookie 设置已移除。

它被主要移除是因为：

> [@sam](#):
>
> 选择登录的默认行为（基于会话还是永久）——默认为永久登录。

> [@codinghorror](#):
>
> 我们只需要将 1440 作为站点设置，其他内容可以忽略。

我能理解，在世界某些地区，与他人共用计算机的概念非常陌生，尤其是在移动个人设备普及以及新冠疫情之后更是如此。但在学校图书馆、工作场所等地方，这种情况其实非常普遍。

> [@codinghorror](#):
>
> 但如果用户忘记关闭浏览器怎么办？这该如何处理？

大多数情况下，用户在使用完电脑后会直接关机。关闭计算机会自动关闭浏览器，因此关机也会间接结束网页应用中的登录会话。

当下一个员工开始下一个班次时，计算机会重新启动，浏览器中将不再包含基于会话的 Cookie。

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [2020年九月8日 17:30 UTC](https://meta.discourse.org/t/session-timeout/34686/45 "2020-09-08T17:30:30Z")

</div>

> [@codinghorror](#):
>
> 我们只需要 1440 这个值作为站点设置，其他内容可以忽略。

没错，但我认为如果不会引发太多支持问题，或在技术上不太困难的话，将此值设置为类似 `0` 的值或许应该实现“Cookie 仅在浏览器会话期间有效”的行为。因此，站点设置的描述中应予以说明。

> 最大会话时长 [默认 1440 小时]
> 
> 用户自上次访问起将保持登录状态 n 小时。若设置为 0，用户将在关闭浏览器时退出登录。

---

<div class="post-metadata">

### Author: ![dajoker](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dajoker/32/193010_2.png) [@dajoker](https://meta.discourse.org/u/dajoker)
#### Post date: [2020年九月8日 17:52 UTC](https://meta.discourse.org/t/session-timeout/34686/46 "2020-09-08T17:52:49Z")

</div>

医院：我只分享我通过实践经验所了解的内容。我同意屏幕会快速锁定，但这并不等同于退出浏览器，更不用说退出操作系统的用户会话了。你能想象，如果计算机必须先登录、应用策略、建立网络连接，然后才能加载某个应用程序，供医生和护士在有人生命垂危时进行必要操作，那会是什么情况？同样地，出于同样的原因，登录方式通常不是用户名/密码，而是工牌加一个简短的PIN码。急诊室、手术室以及其他大多数房间仍需记录患者信息，因此在我参与过的项目中，这一做法始终一致。

图书馆：存在“注销时重启”的策略，只要管理员手动清理机器上所有缓存，这些策略就能有效运行。但我见过不少地方并未这样做（这也是我从未在任何情况下使用共享工作站并用自己凭据登录的原因之一）。就我所见，酒店、网吧（或咖啡馆）也经常出现类似的令人遗憾的设置。

在我看来，任何应用程序默认对所有用户、所有安装实例都采用这种设置都显得奇怪。大多数人在首次设置计算机时并不把安全作为重点，而且安全配置本身足够复杂，以至于需要专人全职负责。那些为公众设置计算机的人本应更清楚这一点，但浏览器引入了会话Cookie的概念，使应用开发者能够在对用户直观的同时轻松实现会话管理。

要求用户理解必须手动清除某个网站的Cookie才能登出，而实际上许多网站既会在会话超时时自动登出，也会在浏览器关闭时终止会话，这似乎对用户提出了过高的要求。如果完全不允许其他选项，迫使用户必须记得使用Discourse特定的登出链接，那么一旦用户因任何原因错过该链接，就会出现问题。例如：

- 用户点击链接后离开了Discourse页面。
- 用户主动使用该标签页前往其他网站。
- 用户匆忙关闭标签页，赶去上课、开会等。
- 浏览器因任何原因崩溃。
- SSO实施者使用SAML进行登录，但不知道应用程序需要显式登出才能终止应用会话。

此外，登录持久化长达两个月似乎实在太长了。我知道如今一些其他网站可能也会这样做，甚至时间更长，但用户通常可以通过“公共电脑”复选框来控制这些设置，而SSO可能不适用此选项，或者根本没有任何控制方式（我不是Discourse专家）。

以上仅是一些供参考的想法。

---

<div class="post-metadata">

### Author: ![SeanSTB](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/seanstb/32/137114_2.png) [@SeanSTB](https://meta.discourse.org/u/SeanSTB)
#### Post date: [2020年九月9日 02:28 UTC](https://meta.discourse.org/t/session-timeout/34686/47 "2020-09-09T02:28:12Z")

</div>

我也遇到了这个问题，但不知道如何解决。

---

<div class="post-metadata">

### Author: ![peteratkins](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/peteratkins/32/190723_2.png) [@peteratkins](https://meta.discourse.org/u/peteratkins)
#### Post date: [2020年九月10日 10:32 UTC](https://meta.discourse.org/t/session-timeout/34686/48 "2020-09-10T10:32:31Z")

</div>

感谢 @codinghorror 的分享。请问评估和实施这一建议的流程和时间表是怎样的？

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [2020年九月10日 23:49 UTC](https://meta.discourse.org/t/session-timeout/34686/49 "2020-09-10T23:49:44Z")

</div>

我不知道，这取决于技术上的难度有多大。@sam，你对 [我上面帖子中提出的内容](https://meta.discourse.org/t/session-timeout/34686/45) 的难度有什么看法？

---

<div class="post-metadata">

### Author: ![Cody\_Kerr](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/cody_kerr/32/137533_2.png) [@Cody\_Kerr](https://meta.discourse.org/u/Cody_Kerr)
#### Post date: [2020年九月11日 02:01 UTC](https://meta.discourse.org/t/session-timeout/34686/50 "2020-09-11T02:01:07Z")

</div>

我觉得这也会是一个很棒的功能，因为它可以让人们知道谁真正在线，谁只是暂时离开。

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2020年九月11日 02:29 UTC](https://meta.discourse.org/t/session-timeout/34686/51 "2020-09-11T02:29:47Z")

</div>

我们确实需要在这里添加一个新的站点设置，因为从概念上讲这是解耦的，否则会让代码难以理解。

具体来说，我们需要在这里添加最小值限制：

> <https://github.com/discourse/discourse/blob/468417a7162a5337fe99a4fdbea51cd51c4ad49a/app/models/user_auth_token.rb#L103-L103>

以及在其他几个地方，以确保代码继续正常工作。

我们需要的设置是一个独立的“在浏览器关闭时自动注销用户”类型的选项。

即使使用会话 Cookie（即省略 expires 参数），会话时长仍然适用。

例如，你可以这样设定：

1. 如果用户合上笔记本电脑，3 小时后再打开，希望他们被注销。
2. 如果用户退出 Chrome，希望他们被注销。

这是两个不同的关注点。

也许我们可以添加一个 `persistent_sessions` 选项，默认值为 true？含义是“设置为 true 时，会话会在浏览器关闭后保持”。这个改动大约只需要 20 分钟。

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [2020年九月11日 03:52 UTC](https://meta.discourse.org/t/session-timeout/34686/52 "2020-09-11T03:52:16Z")

</div>

好的，如果独立的站点设置更好，而且只需 20 分钟就能轻松完成，那我们就这么做吧。

---

<div class="post-metadata">

### Author: ![neounix](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/neounix/32/215617_2.png) [@neounix](https://meta.discourse.org/u/neounix)
#### Post date: [2020年九月11日 04:39 UTC](https://meta.discourse.org/t/session-timeout/34686/53 "2020-09-11T04:39:13Z")

</div>

也许未来可以将这个好主意扩展为“每个用户”的设置，而不仅仅是“每个站点”的设置？

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2020年九月11日 05:15 UTC](https://meta.discourse.org/t/session-timeout/34686/54 "2020-09-11T05:15:51Z")

</div>

这现在已作为每个站点的设置完成。

[https://review.discourse.org/t/feature-add-support-for-not-persistent-sessions/15171](https://review.discourse.org/t/feature-add-support-for-not-persistent-sessions/15171)

在我看来，这实际上是一个管理员的选择。它是一项安全功能。从长远来看，我们可能会考虑一个允许绕过此限制的 IP 地址白名单（例如，让公司网络内的计算机保持登录状态，而外部计算机则自动注销）。

---

<div class="post-metadata">

### Author: ![neounix](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/neounix/32/215617_2.png) [@neounix](https://meta.discourse.org/u/neounix)
#### Post date: [2020年九月11日 05:26 UTC](https://meta.discourse.org/t/session-timeout/34686/55 "2020-09-11T05:26:13Z")

</div>

我认为，根据此请求的性质，这是一个按用户划分的特性。

一些用户在家中或办公室的电脑上使用，他们不需要 Cookie 过期，因此这应由他们自行决定。

另一些用户可能是那些在咖啡馆使用共享电脑的“游牧者”，他们希望自己的会话能够过期。

该特性的本质是用户账户的安全性，因此这一设置通常作为用户登录时的用户设置或复选框来实现。

例如，vBulletin 早在十多年前就内置了此功能，当我们登录时，只需勾选一个复选框，表示“我们用户”希望会话持久化。

“安全性”针对的是用户账户，因此过去这通常是一个按用户设置的选项，特此说明。

更新：当用户拥有特权账户（如管理员、版主、领导者等）时，还存在整体网站安全性的更大问题。

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2020年九月11日 06:05 UTC](https://meta.discourse.org/t/session-timeout/34686/56 "2020-09-11T06:05:36Z")

</div>

> [@neounix](#):
>
> 因此，该设置通常作为用户登录时的用户设置或用户复选框来实现。

我在许多网站上都见过这种实现，典型的做法是：

> 30 天内保持登录状态
> 
> [登录]

目前还不确定我们何时会实现这一功能，但一旦实现，我们很可能会要求通过站点设置来启用它。如果启用了社交登录，关于在哪里显示此类复选框还存在一些复杂情况。

---

<div class="post-metadata">

### Author: ![peteratkins](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/peteratkins/32/190723_2.png) [@peteratkins](https://meta.discourse.org/u/peteratkins)
#### Post date: [2020年九月11日 09:49 UTC](https://meta.discourse.org/t/session-timeout/34686/57 "2020-09-11T09:49:39Z")

</div>

感谢大家，你们的帮助和理解我们非常感激。

---

<div class="post-metadata">

### Author: ![neounix](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/neounix/32/215617_2.png) [@neounix](https://meta.discourse.org/u/neounix)
#### Post date: [2020年九月11日 11:12 UTC](https://meta.discourse.org/t/session-timeout/34686/58 "2020-09-11T11:12:54Z")

</div>

> [@sam](#):
>
> 如果启用了社交登录，要在何处显示此类复选框确实存在一些复杂情况。

谢谢。

是的，由于涉及行为追踪问题，社交登录一直不是“我们的重点”；因此，我的视角比你们支持社交登录这一更庞大、更复杂的需求要狭窄得多。

感谢你们团队的所有出色工作。做得很好。

---

<div class="post-metadata">

### Author: ![phntxx](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/phntxx/32/90816_2.png) [@phntxx](https://meta.discourse.org/u/phntxx)
#### Post date: [2020年九月13日 07:26 UTC](https://meta.discourse.org/t/session-timeout/34686/59 "2020-09-13T07:26:08Z")

</div>

首先，非常感谢你们迅速修复了问题。不过我还有一个问题：是否可以将此设为每个用户的独立设置，并指定一个默认值，以便用户可以在偏好设置中选择退出？

---

<div class="post-metadata">

### Author: ![riking](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/riking/32/170938_2.png) [@riking](https://meta.discourse.org/u/riking)
#### Post date: [2020年九月14日 13:40 UTC](https://meta.discourse.org/t/session-timeout/34686/60 "2020-09-14T13:40:34Z")

</div>

这正是上文讨论过的可能作为未来工作项的内容，因为两者都需要投入更多精力，并且存在一些棘手的 UI 设计问题。

此外，我们希望先让该功能上线运行一段时间，以观察是否有人发现我们在实现方式上存在的技术问题。

[上一頁](https://meta.discourse.org/t/session-timeout/34686.md?page=2)

[下一頁](https://meta.discourse.org/t/session-timeout/34686.md?page=4)
