# SSO 凭据有效期/强制登出

**URL:** https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874
**Category:** WordPress
**Created:** [2019年八月26日 21:31 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874 "2019-08-26T21:31:23Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![markwill](https://avatars.discourse-cdn.com/v4/letter/m/90db22/32.png) [@markwill](https://meta.discourse.org/u/markwill)
#### Post date: [2019年八月26日 21:31 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/1 "2019-08-26T21:31:23Z")

</div>

用户在被要求重新登录之前，可以保持登录状态多久？

我已经在 functions.php 中实现了自己的检查功能，并与 WordPress 的 SSO 插件集成。我的逻辑看起来相当简单，但我刚注意到，一位信用卡被拒的用户（因此移除了我的逻辑所检查的用户标签）今天仍能访问我的论坛。进一步检查发现，她最后一次登录是在几天前，而且似乎仍然处于登录状态。她的 WordPress 最后登录日期也是几天前。

她的缓存凭据是否仍应有效？如果是，是否有任何方法可以控制令牌的有效期，和/或响应 webhook 以强制注销？

谢谢。

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [2019年八月26日 21:42 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/2 "2019-08-26T21:42:24Z")

</div>

> [@markwill](#):
>
> 用户在被再次提示登录之前，可以保持登录状态多长时间？

这由 Discourse 的“最大会话时长”（maximum session age）站点设置控制。该设置决定了用户将保持登录状态的小时数。默认值为 1440 小时（60 天）。您可以尝试将其设置为更低的值。如果设置得太低，用户可能会觉得这是一个漏洞。

> [@markwill](#):
>
> 我刚刚注意到，一位信用卡被拒付的成员（因此移除了我的逻辑所检查的用户标签）今天仍能访问我的论坛。进一步检查后发现，她几天前最后登录，并且似乎仍然处于登录状态。

这很合理。您可以手动注销用户：进入他们的 Discourse 管理页面，点击页面右上角附近的“注销”（Log Out）按钮。另一种控制方法是，在您的 WordPress 站点中添加一些代码，当会员资格过期时自动将用户从 Discourse 注销。

---

<div class="post-metadata">

### Author: ![markwill](https://avatars.discourse-cdn.com/v4/letter/m/90db22/32.png) [@markwill](https://meta.discourse.org/u/markwill)
#### Post date: [2019年八月26日 21:45 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/3 "2019-08-26T21:45:55Z")

</div>

非常感谢，Simon。虽然我认为 60 天对于我的场景来说太长了（这些是付费会员，他们期望我们会确认他们仍然是有效会员），但我确实同意，如果将其缩短太多也会带来麻烦。

最后的建议（在会员资格结束时找到一种方法将他们从 Discourse 登出）是我将去研究的方向。我之前看到过手动登出的选项，但我的目标是完全自动化这一切，所以这似乎是最正确的路径。

再次感谢。

---

<div class="post-metadata">

### Author: ![mcwumbly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mcwumbly/32/103861_2.png) [@mcwumbly](https://meta.discourse.org/u/mcwumbly)
#### Post date: [2019年九月20日 02:51 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/4 "2019-09-20T02:51:10Z")

</div>

> [@simon](#):
>
> 这由 Discourse 的“最大会话时长”站点设置控制。它设定用户将保持登录状态的小时数。

嗯……该站点设置的描述写道（ **我的强调** ）：

> 用户将在上次访问后的 n 小时内保持登录状态

如果我的理解正确，只要他们定期访问网站，即使丢失了 SSO 凭证，他们也可能永远保持登录状态。例如，如果该设置设为 72 小时，只要他们每隔一两天访问一次网站，就会一直登录。我的理解对吗？

---

<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: [2019年九月20日 04:17 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/5 "2019-09-20T04:17:01Z")

</div>

是的，根据我的经验确实如此。不存在一个绝对的超时机制，会在固定时间后强制将用户登出。

---

<div class="post-metadata">

### Author: ![markwill](https://avatars.discourse-cdn.com/v4/letter/m/90db22/32.png) [@markwill](https://meta.discourse.org/u/markwill)
#### Post date: [2019年九月20日 12:36 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/6 "2019-09-20T12:36:44Z")

</div>

那么，这是否意味着，如果有人取消了我的会员资格，而我想确保他们无法访问我的论坛，我就需要强制将他们注销（手动或通过 API 调用）？

---

<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: [2019年九月30日 11:04 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/7 "2019-09-30T11:04:32Z")

</div>

是的，这是建议。

---

<div class="post-metadata">

### Author: ![markwill](https://avatars.discourse-cdn.com/v4/letter/m/90db22/32.png) [@markwill](https://meta.discourse.org/u/markwill)
#### Post date: [2019年九月30日 13:51 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/8 "2019-09-30T13:51:59Z")

</div>

谢谢。我刚从 Facebook 群组切换过来（在那里需要手动移除取消订阅的成员），很遗憾在 Discourse 中，我仍然需要一个手动流程来确保已取消订阅的成员无法访问我的论坛。这就引出了一个问题。

是否存在任何非手动的机制——无论多么有创意——可以确保没有有效账户的用户（即无法登录的用户）被强制登出 Discourse？

从逻辑上看，SSO 机制阻止用户登录（识别出他们没有有效账户）似乎有些奇怪，但如果他们只是定期访问论坛（在超时时间内），他们就可以无限期地访问论坛，直到我手动将他们登出。

我想我最后的潜在方案是编写一个插件，在用户取消订阅时调用 Discourse API 将他们登出。

欢迎提出任何想法。如你所见，我真的非常不想手动处理这个问题 🙂

谢谢。

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [2019年九月30日 16:25 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/9 "2019-09-30T16:25:18Z")

</div>

> [@markwill](#):
>
> 我想我最后的潜在方案是编写一个插件，在用户取消订阅时调用 Discourse API 将其登出。

您可以向 `/admin/users/<discourse_user_id>/log_out` 发送 API 请求。[WP Discourse](https://github.com/discourse/wp-discourse) 插件使用此路由来同步 WordPress 与 Discourse 的登出操作。您可能可以复制此函数中的大部分代码：[wp-discourse/lib/sso-provider/discourse-sso.php at main · discourse/wp-discourse · GitHub](https://github.com/discourse/wp-discourse/blob/master/lib/sso-provider/discourse-sso.php#L205%E3%80%82)

---

<div class="post-metadata">

### Author: ![markwill](https://avatars.discourse-cdn.com/v4/letter/m/90db22/32.png) [@markwill](https://meta.discourse.org/u/markwill)
#### Post date: [2019年九月30日 16:35 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/10 "2019-09-30T16:35:38Z")

</div>

非常感谢，Simon。我会仔细查看。

不过退一步说，这难道不像是个问题吗？我猜我们可以争论其重要性，但拥有一个平台，让用户即使在没有有效账户的情况下也能无限期地访问论坛，这在我见过的其他地方是未曾出现的。

我或许可以接受这样的观点：在这里，WordPress 而非 Discourse 才是权威来源。因此，问题可能出在 SSO 插件上，那里或许是添加相关逻辑的最佳位置。

很想知道这里的整体思路。我认为这种情况是合理的（例如在一定时间后强制登出，或基于 WordPress 账户变为“无效”而登出），对吧？

我只是在 brainstorming，因为我想避免手动操作，但如果可能的话，我也不想写代码 🙂

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [2019年九月30日 16:48 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/11 "2019-09-30T16:48:19Z")

</div>

> [@markwill](#):
>
> 我或许可以接受这样的观点：在这里，WordPress 而非 Discourse 才是权威数据源。因此，问题很可能出在 SSO 插件上，相关逻辑应放在那里。

是的，这需要在 WordPress 端处理。我认为，当用户在 WordPress 上被删除时，[WP Discourse](https://github.com/discourse/wp-discourse) 插件将其从 Discourse 登出是合理的，但这可能无法解决你的问题。我的假设是，当用户的会员资格在你的网站上过期时，该用户并不会从你的 WordPress 站点中被删除。要处理用户会员资格过期时将其从 Discourse 登出的情况，你可能需要在你的站点中添加一些代码，挂钩到会员插件在会员过期时触发的相应操作上。

---

<div class="post-metadata">

### Author: ![markwill](https://avatars.discourse-cdn.com/v4/letter/m/90db22/32.png) [@markwill](https://meta.discourse.org/u/markwill)
#### Post date: [2019年九月30日 17:03 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/12 "2019-09-30T17:03:09Z")

</div>

再次感谢，@simon。你的观点很有道理，但请原谅我再补充一点想法 🙂

看起来这里有两个因素在起作用——账户的有效性（即用户是否为活跃成员）以及 Discourse 中令牌的有效性。

对于前者，我完全同意 WordPress 应负责管理，我会根据时间安排进一步调查。

然而，Discourse 端也存在活跃/有效令牌的问题。我理解这可能不是高优先级事项，但我认为设置一个“强制登录”时间范围（可能默认关闭）是有其合理性的，即无论用户最近是否登录，经过 x 天后其登录令牌都会过期。

再次说明，我目前只是在头脑风暴，但认为强制登出作为一个独立选项（与用户是否拥有有效账户无关）具有一定的价值。

---

<div class="post-metadata">

### Author: ![Cardinalflyer](https://avatars.discourse-cdn.com/v4/letter/c/f14d63/32.png) [@Cardinalflyer](https://meta.discourse.org/u/Cardinalflyer)
#### Post date: [2019年十一月26日 17:40 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/13 "2019-11-26T17:40:31Z")

</div>

> [@simon](#):
>
> `/admin/users/<discourse_user_id>/log_out`

我试图通过网页链接实现此功能，因为我并未使用 WordPress。我是否可以使用类似下面的方式？

`https://community.mysite.com/admin/users/100004/log_out`

对我而言，这会返回 404 错误，且用户并未退出登录。

如果我能让 URL 正常工作，我希望能通过 PHP 中的 curl 或 file\_get\_contents 命令强制用户退出登录…

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [2019年十一月26日 17:48 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/14 "2019-11-26T17:48:10Z")

</div>

> [@Cardinalflyer](#):
>
> 对我来说显示的是 404 错误，而且用户并未登出。

您需要向该路由发起一个经过身份验证的 POST 请求。您可以将其设置为在用户点击链接时登出，但您必须在服务器端处理该请求。

---

<div class="post-metadata">

### Author: ![Cardinalflyer](https://avatars.discourse-cdn.com/v4/letter/c/f14d63/32.png) [@Cardinalflyer](https://meta.discourse.org/u/Cardinalflyer)
#### Post date: [2019年十一月26日 20:21 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/15 "2019-11-26T20:21:11Z")

</div>

谢谢！已认证，嗯？正在研究这个问题，看起来来自 PHP 的已认证帖子会在请求头中发送类似这样的内容：

```plaintext
'Authorization: OAuth '.$accesstoken;

```

网上有一些线索，我会继续研究。

但如果有人能提供一段可运行的 PHP 代码片段就太好了！[https://docs.discourse.org/](https://docs.discourse.org/) 认证部分中的示例对我来说返回了语法错误……哦，等等，那是一个 Unix 命令！

欢迎提供任何有助于 PHP 的线索！

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [2019年十一月26日 20:29 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/16 "2019-11-26T20:29:52Z")

</div>

> [@Cardinalflyer](#):
>
> 但如果有人能提供一段可用的 PHP 代码片段，那就太好了！

我上一篇文章中的链接应该足以帮助你入门：[wp-discourse/lib/sso-provider/discourse-sso.php at main · discourse/wp-discourse · GitHub](https://github.com/discourse/wp-discourse/blob/master/lib/sso-provider/discourse-sso.php#L205%E3%80%82%E5%81%87%E8%AE%BE%E4%BD%A0%E4%B8%8D%E6%98%AF%E5%9C%A8) WordPress 站点中发起请求，你需要找到另一种方式来执行 `wp_remote_post` 请求。

---

<div class="post-metadata">

### Author: ![Cardinalflyer](https://avatars.discourse-cdn.com/v4/letter/c/f14d63/32.png) [@Cardinalflyer](https://meta.discourse.org/u/Cardinalflyer)
#### Post date: [2019年十一月26日 22:47 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/17 "2019-11-26T22:47:13Z")

</div>

我觉得我快接近了，使用的是简单的 PHP 命令。代码如下。用户名选择来自[这篇帖子](https://meta.discourse.org/t/api-username-query/60227/6?u=cardinalflyer)。

我收到了这个响应……这对大家来说有什么含义吗？看起来像是 SSL 协议版本的问题？

`error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version`

这是我的代码：

```
    $url = "https://community.mysite.com/admin/users/100004/log_out";
    $headers = array( 'Api-Key' => 'd412mylongadminkeyaadcd',
                    'Api-Username' => 'system',
                    );

	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);

[编辑：也添加了这些行，但没有变化：]
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
[/编辑]

	curl_setopt($ch, CURLOPT_POST, true);
	curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    $data = curl_exec($ch);
    if (curl_errno($ch)) {
        echo curl_error($ch);
    }
    curl_close($ch);

```

---

<div class="post-metadata">

### Author: ![simon](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/simon/32/339122_2.png) [@simon](https://meta.discourse.org/u/simon)
#### Post date: [2019年十一月27日 17:49 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/18 "2019-11-27T17:49:59Z")

</div>

> [@Cardinalflyer](#):
>
> 我收到了这个响应……这对大家来说意味着什么吗？看起来像是 SSL 协议版本的问题？

既然你使用的是 WordPress，可以尝试使用 `wp_remote_post` 函数来发起请求。这样你就不必处理 `curl` 选项了。

---

<div class="post-metadata">

### Author: ![Cardinalflyer](https://avatars.discourse-cdn.com/v4/letter/c/f14d63/32.png) [@Cardinalflyer](https://meta.discourse.org/u/Cardinalflyer)
#### Post date: [2019年十一月27日 19:55 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/19 "2019-11-27T19:55:26Z")

</div>

谢谢，但我没有使用 WordPress。我过去十年一直在自己开发的会员管理系统中用 PHP 实现这个功能。

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2019年十一月27日 22:44 UTC](https://meta.discourse.org/t/sso-credentials-validity-forced-logout/126874/20 "2019-11-27T22:44:58Z")

</div>

看起来您的 PHP 库不认可您的 Discourse HTTPS 证书。建议您搜索该错误。
