【问题标题】:Get users last accessed time获取用户上次访问时间
【发布时间】:2018-07-20 22:07:59
【问题描述】:

我正在为我的 asp.net 核心 API 使用 IdentityServer 4(带有 sql 存储)。我想在数据库中的某处添加一个“上次访问”字段,该字段可用于在用户搜索端点中订购我的一种用户类型。理想情况下,这将显示他们上次在系统中执行操作的时间。

如果我在登录方法中执行此操作,它将不准确,因为它只会在最初生成令牌时更新。我可以为用户访问的每个端点添加一个方法,但这感觉不是正确的解决方案,因为它会重复我自己。

维护记录用户最后一次访问系统的数据库字段的正确位置和方法是什么?

【问题讨论】:

  • 为什么不在令牌刷新/验证端点上做呢?无论如何,访问令牌应该是短暂的(不到一个小时,最好是 5 到 10 分钟)
  • 如何将代码添加到 IdentityServer4 刷新端点?身份服务器和 api 在不同的项目中,我不负责初始 IDS4 设置,但我看不到任何更新端点,我认为这是 IDS4 自动添加的。
  • IDS4 公开了您可以为其实现处理程序的事件,因此可能值得研究一下。 EF 还支持“触发器”,允许您通过事件回调响应对特定实体的更改。我们在这两件事的背后实现了一个完整的审计日志解决方案,并将我们自己的许多事件添加到各种自定义位和 UI 中的登录
  • @mackie 太好了,我之前没有在文档中看到这些事件,但我只是找到了它们。我添加了自定义中间件,它在所有经过身份验证的请求上写入时间戳,但使用事件将是更高效的解决方案。谢谢
  • 为了避免必须在每个请求时写入数据库,您还可以更新内存中用户的时间戳,并且每次只将其写回数据库过一会儿。

标签: c# asp.net-core entity-framework-core identityserver4


【解决方案1】:

要记录用户的活动时间,您可以尝试每个请求都会调用的中间件。
以下是步骤。
1.向ApplicationUser添加字段,用于存储上次访问时间

public class ApplicationUser : IdentityUser
{       
    public DateTime LastAccessed { get; set; }
}

2.运行命令add-migration LastAccessedupdate-database
3.添加中间件,根据用户名更新上次访问时间

        app.UseAuthentication();
        app.Use(async (context, next) => {
            await next.Invoke();
            //handle response
            //you may also need to check the request path to check whether it requests image
            if (context.User.Identity.IsAuthenticated)
            {
                var userName = context.User.Identity.Name;
                //retrieve uer by userName
                using (var dbContext = context.RequestServices.GetRequiredService<ApplicationDbContext>())
                {
                    var user = dbContext.ApplicationUser.Where(u => u.UserName == userName).FirstOrDefault();
                    user.LastAccessed = DateTime.Now;
                    dbContext.Update(user);
                    dbContext.SaveChanges();
                }
            }
        });

【讨论】:

  • 我做了类似的事情,但我把 await next() 放在了方法的末尾。我应该把await next.Invoke() 放在开头吗?
  • await next() 得到了什么结果?您当前的代码是什么?您需要在if (context.User.Identity.IsAuthenticated) 之前致电await next()。您可以在if (context.User.Identity.IsAuthenticated)await next.Invoke 上设置断点来调试代码是否运行
  • 它似乎工作(访问时间出现在 db 中)。我的理解是代码调用管道中的下一个方法。一开始就调用它的原因是什么?
  • 这是在UseAuthentication之前使用这个中间件造成的,我已经更新了不管await next()的顺序都应该工作的顺序
  • 我认为它需要在身份验证后发生,否则用户的声明将无法在上下文中使用
【解决方案2】:

我为 identity server 项目中的集中式解决方案(使用 IEventSink)添加了一个类似问题的答案。我们有 30 多个 api,我发现最好只在一个地方做解决方案,而不是在每个 api 中做。所以我在这里添加了这个答案,以防万一有人遇到和我一样的要求。这是我的answer

【讨论】:

  • 正是我需要的!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-28
  • 1970-01-01
  • 2018-04-12
  • 1970-01-01
  • 2010-12-01
相关资源
最近更新 更多