【问题标题】:How to set runtime authentication in ASP.NET Core?如何在 ASP.NET Core 中设置运行时身份验证?
【发布时间】:2019-11-07 07:38:14
【问题描述】:

我正在创建一个应用程序,其中包含基于角色的模块管理,并且随时更改。 场景:

  • 如果用户有权创建和查看员工,则用户只能创建和查看员工,但将来管理员将用户的角色从创建和查看更改为查看和删除,则用户只能执行该活动。

我尝试使用 [Authorize(Roles ="Staff")],但如果管理员更改运行时而不是托管。

有人可以调查一下并回复我吗?

【问题讨论】:

  • Authorize(Roles ="Staff") 确保角色为Staff 的用户只能访问此操作...因此,如果用户从此角色中删除,用户将无法访问此操作.. 这不是吗发生了什么?
  • 据我所知这是不可能的,也许不是一个好主意。用户应注销并重新登录以应用新角色。您甚至可以以不同的方式呈现页面。
  • 假设您使用 cookie 或 jwt 不记名令牌:用户的声明/角色保存在 cookie/令牌中,您必须注销用户并再次登录用户以确保它得到一个新的 cookie/令牌。
  • 嗨,@itminus 目前,初始阶段正在运行,因此在登录用户时获取角色和可用角色列表,如 Create EmployeeView Employee 和 @Emad 是的,我需要及时更改登录 如果在实时会话期间有任何更改,则对角色没有影响。有可能吗?
  • @DeepSoni 我们可以实现自定义授权属性,以便我们可以实现此要求。请提出建议,以便我们继续前进。

标签: c# asp.net-mvc authentication asp.net-core


【解决方案1】:

这是一个复杂的问题,没有正确答案,但有几种方法可以做到。 首先,我假设您使用基于声明的 jwt 使用无状态身份验证,最简单的方法是编写您自己的 Policy,它将在每次请求之前读取用户角色,这是最简单的方法,也是最快的实现方法。

internal class DatabaseRoles : IAuthorizationRequirement
    {
        public string Role { get; }

        public DatabaseRoles(string role)
        {
            Role = role;
        }
    }

    internal class DatabaseRolesHandler : AuthorizationHandler<DatabaseRoles>
    {
        private readonly UserManager<IdentityUser> userManager;

        public DatabaseRolesHandler(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager)
        {
            this.userManager = userManager;
        }

        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, DatabaseRoles requirement)
        {
            //NOTE this is the out of the box implementation of roles and simple query to get the roles from the EF backed database. I would recoment makeing a custom privelages store for this and not using roles for this but access rights
            var user = await userManager.FindByIdAsync(userManager.GetUserId(context.User));
            if (await userManager.IsInRoleAsync(user, requirement.Role))
            {
                context.Succeed(requirement);
            }
        }

    }

但是这个解决方案的性能并不高,因为它需要在每个请求上调用数据库。这在小负载上很好,但可能会造成流量问题。 另一种方法是在角色更改时重新调用所有用户令牌,但这非常复杂。我敢肯定,如果您为 redis 之类的角色创建一些快速访问存储,那么每次调用都不会出现问题。此外,我不建议创建您自己的用户存储,因为维护和更新安全标准是一场噩梦。

【讨论】:

  • 您好,感谢您的回答。我已经尝试过您的解决方案,但是在每次处理索引、创建、编辑或此方法正在调用的任何其他操作时,一个问题是如果有一个仪表板有公共可用,那么该特定模块没有角色,那么它不是根据您的代码,任何人都可以看到。
  • @DeepSoni 如果演示不建议按原样使用代码,请指出代码。您应该自定义它以满足您的需要。这一点以resource based auth 为例。查询应使用自定义查询使用用户 ID 检查您的数据库。
  • 感谢您的回复。让我试试你的参考和解决方案。
  • 我目前尝试参考 Microsoft Doc 进行基于资源的授权,然后 IDocumentRepository 无法使用。它向我展示了安装 UmbracoCMS。你能弄清楚吗?
  • O 所以这是 UmbracoCMS 的具体问题,我真的不太熟悉它可能最好添加 UmbracoCMS 标记和您尝试这样做的代码,以便有经验的人来查看它。但据我所知,只要您对 UmbracoCMS 进行正确查询,它就应该可以在任何地方工作。
【解决方案2】:

如果您使用 Session/Cookie 来存储登录用户的详细信息,您可以在管理员更改角色时清空详细信息。在每个操作上,您都可以检查 Session/Cookie 中的角色并继续前进。 现在,只要用户点击屏幕上的任何位置,它就会碰到控制器。将检查条件并注销用户,因为 Session/Cookie 对象为空。

【讨论】:

  • 嗨@BansariSoni。感谢您的回答。每次都删除会话并要求登录用户是没有意义的。它只像应用程序中的补丁(固定),因此需要一些甚至可以接受的正确答案或一些提示来找出答案。
  • 如果角色在会话中,那么根据我的说法,我只能选择两个选项,要么更改会话变量,要么删除它。在这里,您可以做另一件事,例如当管理员更改角色时,您可以检查会话中是否存在该用户 ID,如果是,则在会话中设置标志。然后,您可以创建一个 cron 作业,仅当此特定标志为真时每 5 分钟刷新一次页面。
猜你喜欢
  • 2018-01-28
  • 2018-03-30
  • 1970-01-01
  • 2020-06-18
  • 2018-01-23
  • 1970-01-01
  • 2021-08-03
  • 2017-12-31
  • 2023-03-11
相关资源
最近更新 更多