关于 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 对象