关于 ASP.NET Core 中的授权

Posted

技术标签:

【中文标题】关于 ASP.NET Core 中的授权【英文标题】:About authorization in ASP.NET Core 【发布时间】:2021-10-27 18:12:12 【问题描述】:

我正在尝试为 Asp.net Core 构建基于权限的授权,同时我正在从 .net 框架迁移到核心。我根据自己的需要(使用身份)构建了一个授权系统。基本上我正在向角色添加声明,并且用户具有角色。我构建了用于将角色分配给用户并将声明分配给角色的复选框。一切正常,但这是我的问题:

当系统运行时,假设 user1 具有“管理员角色”。 user1 可以根据使用他的角色->声明的策略访问页面。问题从这里开始。当 user1 登录时,如果我更改“Admin”角色的声明,user1 将在他/她注销并重新登录之前生效。

有人有解决这个问题的想法吗?

【问题讨论】:

当用户登录时,您似乎正在生成一个令牌,其中包含该用户在登录时的角色和/或声明,因此您需要重新生成该令牌(如果这更有意义,请再次登录)并将其发送回用户。如果您使用 cookie,这应该不会太难(您可以在没有密码的情况下登录已经登录的用户) 实际上我没有在 Asp.net Core 身份系统上添加任何新内容。使用 .net 框架,我使用会话和自定义授权类来处理会话。有了核心,我想在构建项目时尝试个人帐户身份验证(内置)。我从身份用户派生了 ApplicationUser 。我只对页面进行编码以向角色添加声明并向用户添加角色(使用 UserManager 和 RoleManager)。我在 startup.cs 上添加了策略。老实说,我不知道授权是如何工作的。这是我的存储库链接。如果你教我,我将不胜感激。 【参考方案1】:

该解决方案似乎有效...但让我提一点警告...

性能问题

因为您必须检查每个客户端请求的数据库权限(这会给系统带来真正的负担)。我知道您似乎正在构建经典的单声道应用程序。但是服务器还是会受到来回数据库的困扰。

用户不知道发生了什么。

假设您显示了一个用户通常经常访问的报告部分,但在某个美好的一天......浏览器空白,或者弹出一些她没有权限再使用它的对话框。这可能会导致真正的问题,因为用户目前只使用他们需要的东西。如果距离会议还有 10 分钟,并且需要帮助打印一些报告和弹出窗口,会发生什么? (来自我的经验教训(XD))。

所以我强烈建议,在应用部署和用户登录时,从数据库中获取他们所有的角色和声明一次并将它们缓存在某处(例如 IMemoryCache,因为我们针对的是经典单声道应用程序),然后检查缓存声明之后。

每当用户权限发生变化时,更新缓存,并在那个时刻立即注销用户。如果有不好的事情发生。用户会对设置权限的人大喊大叫,而不是我们作为开发人员。

自上次以来,您似乎已经连续花费了几个小时来完成自己的体面解决方案。

好朋友

【讨论】:

感谢您的回答。老实说,我只是在考虑性能问题。我不知道如何使用缓存和IMemoryStore,我将看看这些主题。再次感谢,祝您有美好的一天! 糟糕……抱歉……这是IMemoryCache,而不是IMemoryStore……我也修复了答案……感谢提及(XD) 顺便说一句,你能解决你的 VS Code 问题吗?我搜索但找不到任何好的扩展 不幸的是我不知道怎么做。但是因为我在 reactjs 和 .net 核心上工作,跨 Windows,Ubuntu(我猜 mac 会是一样的)。我敢打赌,你会很高兴将 Rider 用于 .net 事物,将 VsCode 用于其他事物。从那以后我的生活轻松了很多。 从你那里学到了很多,谢谢你所做的一切。现在是我开始学习这些的时候了。再次感谢,祝您有美好的一天!希望我们能再见面^-^【参考方案2】:

好的。我想出了一个解决方案。

internal class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>

    UserManager<User> _userManager;
    RoleManager<IdentityRole> _roleManager;

    public PermissionAuthorizationHandler(UserManager<User> userManager, RoleManager<IdentityRole> roleManager)
    
        _userManager = userManager;
        _roleManager = roleManager;
    

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
    
        if (context.User.Identity.Name == null)
        
            return;
        

        // Get all the roles the user belongs to and check if any of the roles has the permission required
        // for the authorization to succeed.
        var user = await _userManager.GetUserAsync(context.User);
        var userRoleNames = await _userManager.GetRolesAsync(user);
        var userRoles = _roleManager.Roles.Where(x => userRoleNames.Contains(x.Name));

        foreach (var role in userRoles)
        
            var roleClaims = await _roleManager.GetClaimsAsync(role);
            var permissions = roleClaims.Where(x => x.Type == CustomClaimTypes.Permission &&
                                                    x.Value == requirement.Permission)
                                        .Select(x => x.Value);

            if (permissions.Any())
            
                context.Succeed(requirement);
                return;
            
        
    

然后我们在 startup.cs 中调用它

services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();

更详细的答案请查看:https://www.zehntec.com/blog/permission-based-authorization-in-asp-net-core/

【讨论】:

以上是关于关于 ASP.NET Core 中的授权的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Core 应用程序中使用多个 HttpClient 对象

ASP.NET Core - AddJwtBearer - 授权 URL,它是如何工作的?

ASP.NET Core与ASP.NET区别

ASP.NET Core 中的 OAuth 授权服务

ASP .NET Core Razor 页面中的授权

[Core]Asp.Net Core中的各种过滤器(授权资源操作结果异常)