【问题标题】:In JWT Authorization, check if user has role Admin在 JWT 授权中,检查用户是否具有角色 Admin
【发布时间】:2017-08-15 20:37:44
【问题描述】:

我正在开发一个 .Net Core API,在我的控制器中,我有以下代码:

if (User.Identity.IsAuthenticated)
{
    var username = HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
    var user = await _userManager.FindByNameAsync(username);
    artistCardDtoCollection = _artistsService.GetAllArtists(user.Id, User.IsInRole("Admin"));
}

上面的代码是因为我希望将User.Id(如果已登录)和IsAdmin 标志传递给我的GetAllArtists 方法。

上面的代码在User.IsInRole("Admin") 上失败了。当我 100% 知道相关用户是 Admin 时,我会收到 false。我通过 SQL Management Studio仔细检查了数据库。

这让我觉得在使用 JWT 时不能使用User.IsInRole()。如果是这样,那么正确的方法是什么?谢谢

【问题讨论】:

    标签: asp.net-core jwt


    【解决方案1】:

    可能是User.IsInRole()的缓存问题,如果我们检查documentation,我们会发现:

    IsInRole 首先检查 IsRoleListCached 属性以确定 当前用户的角色名称缓存列表是否可用。 如果 IsRoleListCached 属性为 true,则检查缓存列表 对于指定的角色。如果 IsInRole 方法找到指定的 缓存列表中的角色,它返回true。如果 IsInRole 未找到 指定角色,调用默认的GetRolesForUser方法 Provider实例判断用户名是否关联 具有来自已配置 ApplicationName 的数据源的角色 价值。

    在您的情况下,您可以尝试使用GetRolesAsync,如下所示:

    var user = await _userManager.FindByNameAsync(username);
    var roles = await _userManager.GetRolesAsync(user);
    artistCardDtoCollection = _artistsService.GetAllArtists(user.Id, roles.Contains("Admin"));
    

    【讨论】:

    • _userManager.FindByNameAsync(username);_userManager.GetRolesAsync(user); 都会调用数据库吗?所以两次调用 Db。如果我停止并启动应用程序,缓存是否也不会被清除?
    • 您的代码有效。 IsAdmin 标志现在设置为 true。
    • @Ciwan 是的,2 个查询。为了通过 1 个查询获取角色名称,我们应该进行 2 次连接,第一次获取角色,第二次通过 id 获取角色名称。在这里,我们有 1 个简单的 User 查询和 1 个 RoleName 的连接,所以它在时间上应该几乎相同(我测量了它)。 GetRolesAsync 生成下一个 SQL:SELECT [role].[Name] FROM [AspNetUserRoles] AS [userRole] INNER JOIN [AspNetRoles] AS [role] ON [userRole].[RoleId] = [role].[Id] WHERE [userRole].[UserId] = @userId,所以你可以只传递 new ApplicationUser { id = userid} 与 ID,而不是整个用户对象,它对我来说很好。
    • @Ciwan 没问题,很高兴能帮到你:)
    猜你喜欢
    • 1970-01-01
    • 2018-03-06
    • 2014-06-09
    • 2010-12-22
    • 2019-06-16
    • 2021-03-31
    • 1970-01-01
    • 2021-10-10
    相关资源
    最近更新 更多