如何从特定会话注销用户,使用Identity Server 4和.NET Core?

7

使用 Identity Serve 4.Net Core 3.1,razor页面。同时使用Cookie身份验证。

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)

问题 -

在一个 Web 应用程序中,约翰登录了两次:

  • 第一次使用 Chrome 登录
  • 第二次使用 Edge 登录

因此,如果约翰在未注销前两个浏览器的情况下尝试第三次在 Firefox 上登录,则我想要强制从 Chrome 上的第一次登录注销约翰。

我可以在 Session 表中跟踪登录信息,包括 Session Id、User Id 等。但我不知道如何使用 Session Id 从特定的会话注销用户。

请帮忙解决。

谢谢。


答案取决于您是否使用自包含的 access_token(即不使用引用令牌)。 - Dai
1
顺便提一下,通用术语不是“注销用户”,而是“会话撤销” - 您可以使用吊销终端来吊销访问令牌和刷新令牌,但您只能吊销引用令牌而非自包含令牌的访问令牌:https://identityserver4.readthedocs.io/en/latest/endpoints/revocation.html - Dai
@ Dai 感谢您的帮助,但我不确定它如何与 cookie 验证一起使用。我已更新我的问题,请再次检查。 - Ravi
IdentityServer并不涉及应用网站中的cookie身份验证 - 您可能会将其与托管IdentityServer的Web应用程序使用的cookie混淆。如果您只有一个网站(因此实际上并未使用OIDC),那么您真的不应该使用IdentityServer。 - Dai
不,我有多个网站。 - Ravi
3个回答

4

ASP.NET Core提供了一个ITicketStore接口,允许您控制存储用户会话。一旦您提供了实现该接口的类并注册它,当创建或验证会话时,它将调用您的类,然后您可以根据需要将其存储在数据库中,还可以附加任意的元数据,如浏览器ID等。

现在您已经在数据库中拥有了用户会话,您可以单独查询它们,并按需要撤销,在其他逻辑中,包括登录期间。由于您现在提供了会话数据,因此仅删除记录就能有效地注销该会话中的用户。请注意,如果您使用任何缓存层来减少存储请求,则需要删除任何缓存副本。

请注意,这与IdentityServer分开,是ASP.NET Core本身的功能。

这是一个很好的教程,帮助我在我的应用程序中实现了这个功能。

以下是在Startup中注册的示例代码,其中PersistentTicketStore是我的实现:

// Persistent ticket/cookie store to provide durable user sessions
services.AddSingleton<IUserSessionRepository, UserSessionRepository>();
services.AddSingleton<ITicketStore, PersistentTicketStore>();
services.AddOptions<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme)
    .Configure<ITicketStore>((options, store) => options.SessionStore = store);

感谢Naoh的帮助,你的答案给了正确的方向。我还从https://ml-software.ch/posts/implementing-a-custom-iticketstore-for-asp-net-core-identity获取了帮助来实现这个功能。 - Ravi

1
使用End Session Endpoint 使用结束会话终端点可结束会话并触发注销。 在登录过程中,您需要捕获从身份验证接收到的id_token以及它所属的用户,并将其存储在某个dbo.table上。您可以使用此表格来跟踪用户是否已经多次登录。
要注销用户或结束会话,您需要将保存的ID作为查询字符串参数传递,称为id_token_hint,如下所示的GET调用: GET /connect/endsession?id_token_hint={id_token} 有关详细信息,请参见此处的文档https://identityserver4.readthedocs.io/en/latest/endpoints/endsession.html#end-session-endpoint

这是让客户端告诉服务器结束用户会话的吗? - rdprado

1

既然您说您可以跟踪登录情况,也许您应该跟踪每个会话并在某处分配一个数字,指示何时登录(1表示Chrome,2表示edge,3表示Firefox)。

然后,每次发出请求时,您都要在表格中检查最低数字是什么(1,2,3等),如果会话与该数字匹配,则从该会话中注销用户。

await HttpContext.SignOutAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);

由于每个浏览器都有自己的cookie,您可以使用上述方法。

在注销某人后,下一次登录可以分配为4,如果2发出请求,则将客户端注销.....

还请查看此内容: https://github.com/IdentityServer/IdentityServer4/issues/736

我已经实现了这个功能。当用户登录时,会话ID(IUserSession.GetSessionIdAsync)会手动存储在我们的数据库中。该数据库字段的前一个值用于创建注销令牌,我会将其发送给我的客户端。您可以查看IdentityServer4.Infrastructure.BackChannelLogoutClient了解如何创建令牌并发布。所有这些都假定您已经实现了后台通道注销。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接