【问题标题】:How to handle idle session timeout across client apps and Identityserver4如何跨客户端应用程序和 Identityserver4 处理空闲会话超时
【发布时间】:2023-03-22 15:38:01
【问题描述】:

我遇到了困难,需要一些建议或指向解决方案的指针。对于我们的单点登录实现,我有一个相当简单的 IdentityServer4 设置。

三个应用程序

IdentityServer4 与 asp.net 核心身份(ID 服务器)

ASP.NET Core 2.2 MVC(客户端1)

ASP.NET Core 2.2 MVC (client2) MVC 客户端是使用 Hybrid Grant 设置的

两种情况:

  1. 如果用户在任一客户端(例如客户端 1)中处于活动状态,则在该应用(客户端 2)中达到空闲超时后,用户不应在客户端 2 中注销。
  2. 如果用户在两个客户端(client1 和 client2)中都处于非活动状态,则系统应在空闲超时时间超过时从所有客户端(client1 和 client2)中注销用户。

场景 1:用户活跃于任一客户端。 用户在客户端 1 中处于活动状态,在客户端 2 中处于空闲状态 预期行为: 超过空闲超时时,系统不应从 client2 注销。 当前的身份行为: 可以在client1中继续工作,但是client2和ID server在空闲时间超过后导航到登录页面。

场景 2: 用户在所有 2 个客户端(客户端 1 和客户端 2)中均处于非活动状态 预期行为: 当空闲超时超过时,系统应该从所有 2 个客户端和 ID 服务器中注销用户。

如果我仅在 ID 服务器中设置 cookie 过期时间(删除了sliderexpiration 为 true 并且 client1 和 client2 中的 cookie 过期时间),那么客户端应用程序将连续工作而没有过期时间,即使两个客户端都处于空闲状态直到 ID 服务器过期时间超过,客户端应用程序正在持续运行。

我想知道是否可以实现预期的行为

客户:

 .AddCookie(options =>
                {
                    // Configure the client application to use sliding sessions
                    options.SlidingExpiration = true;
                    // Expire the session of 15 minutes of inactivity
                    options.ExpireTimeSpan = TimeSpan.FromMinutes(15);
                })

ID 服务器:

services.AddIdentityServer(options =>
            {
                options.Authentication.CookieLifetime = TimeSpan.FromMinutes(15);
                options.Authentication.CookieSlidingExpiration = true;
            })

【问题讨论】:

    标签: asp.net asp.net-core single-sign-on identityserver4 user-inactivity


    【解决方案1】:

    我们采用的方法以及我认为符合 OIDC 规范精神的方法是 IDP 会话是主会话并且可以长期存在。 IDP 不关心客户端会话,但客户端应监控 IDP 会话(会话监控规范),并且当 IDP 注销时,客户端会话也应注销(前通道或后通道)。从客户端显式退出也应该让您退出 IDP 会话。

    此外,由于该协议支持prompt=loginmax_age=n,因此即使 IDP 上已存在活动会话,您也可以强制执行交互式身份验证。这允许客户端实施他们自己的用户必须多久进行一次身份验证的策略 - 例如。要访问管理功能,您必须在过去 5 分钟内或类似的时间内进行身份验证。

    如果在 IDP auth cookie 过期时启动会话监控,但开箱即用的情况下,IDS4 不会发生这种情况。但是,应该可以创建一个自定义的 IUserSession 实现,将会话 ID cookie 与主身份验证 cookie 正确对齐。

    【讨论】:

      【解决方案2】:

      首先需要回答的问题是:什么系统,在哪里?

      浏览器客户端不可信任且不应干扰。我认为最好恢复 cookie 设置。不要让前台尝试触发注销。

      最好在后端跟踪用户。您可以通过在 Mvc 客户端中添加一项服务来完成此操作,该服务 1. 通过 IdentityServer 将用户注册为活动,2. 跟踪活动,以及 3. 当用户看起来太长时间不活动时,通过 IdentityServer 取消注册用户。查看 IdentityServer 附带的token cleanup 服务,了解如何使用间隔更新列表。

      在启动两个 Mvc 客户端时,为 cookie 添加一个处理程序:

      Services
          .AddAuthentication(options =>
          {
              options.DefaultScheme = "Cookies";
              options.DefaultChallengeScheme = "oidc";
          })
          .AddCookie("Cookies", options =>
          {
              // you'll need to create your own handler
              options.EventsType = typeof(MyCookieEventHandler);
          })
      

      我不会在这里添加代码,而是解释一下目的:每次用户需要访问安全源时都会调用 cookiehandler。这意味着您可以在此处更新用户活动时间戳(用于跟踪用户),这意味着您不必一直联系 IdentityServer。只有当状态发生变化时,服务才应该联系 IdentityServer:用户变为活动或不活动。

      现在您需要向 IdentityServer 添加一项服务,以便在一个中心位置跟踪用户。您可以将用户的状态保留在商店中。当用户变为活动时添加用户(每个客户端),当用户不再活动时删除用户。当用户的最后一个会话从此列表中删除时,触发backchannel logout

      反向通道注销可以向 mvc 客户端发出用户已注销的信号。然后使用 CookieEventHandler 拒绝用户访问。这不会在注销时更新前台,但在用户联系 mvc 客户端时有效。它会发现自己从所有应用程序和身份服务器中注销。

      当您点击链接时,您将看到 CookieEventHandler 的实现。并在互联网上搜索 backchannel logout,您可能会找到可以使用的示例。

      【讨论】:

      • 几个问题 1. 我是否必须删除 Options.Authentication.CookieLifetime = TimeSpan.FromMinutes(15); options.Authentication.CookieSlidingExpiration = true;在身份服务器中? 2. 只有当状态发生变化时,服务才应该联系 IdentityServer:用户变为活动或不活动。 - MVC 中的服务如何联系 IdentityServer ? 3. 当用户的最后一个会话从此列表中删除时- 我需要在何时何地检查此列表?
      • 1.我不知道默认值,但你可以使用长寿命的 cookie,因为 CookieEventHandler 现在负责 cookie 的生命周期。 2. 使用可以更新状态的新端点扩展 Ids4,例如与httpclient。 3. 创建一个新表(用于 ids4),用于存储用户/客户端 - 时间戳。客户端更新状态,而清理服务删除所有超过时间戳的条目。一旦从存储中删除最后一条记录(通过 ids4/client),通过通知所有活动客户端(可通过 Usersession 获得)执行完全注销。这有帮助吗?
      • 嗯,这是有道理的。但这里的问题是,如果用户在不同的浏览器(chrome/firefox)中登录。我们必须存储用户/客户端/浏览器。有没有办法识别浏览器?如何在 Angular 应用程序中添加 cookiehandler?
      • 您可以通过 sessionId (sid) 来识别会话。问题是 id 不是跨浏览器共享的。反向通道注销示例只会从同一浏览器中的所有应用程序中注销用户。如果您想要这个跨浏览器,那么您不能使用 cookie,但您必须以另一种方式跟踪用户。我真的不喜欢 javascript 框架,但也许 this article and website 可以帮助你。
      • 我试过 sessionId,它对所有应用程序都不同。在我的情况下,我需要在超时后从在该特定浏览器中打开的所有应用程序中注销用户。例如,用户在 chrome 中处于活动状态,而在 Firefox 中处于非活动状态,那么我需要仅在 Firefox 中从所有应用程序中注销用户。可以实现吗?
      猜你喜欢
      • 2012-04-17
      • 1970-01-01
      • 2021-12-28
      • 2013-06-18
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 2016-04-10
      • 1970-01-01
      相关资源
      最近更新 更多