我有一系列网页,对这些网页的授权是在自定义数据库表中定义的。例如,我有一个名为“ super 用户”的角色,并且允许该角色访问某些网页。我已将用户分配给该角色。
我不明白如何在 Controller 上放置授权属性并传入页面名称( View ),然后从我的数据库中读取某种类型的自定义处理程序以查看用户是否在组中有权限。我一直在这里阅读基于策略的授权:https://learn.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.2并尝试根据我的情况理解它。
我是否在基于策略的授权方面走在了正确的轨道上,或者是否有其他方法可以在允许用户访问页面之前对数据库进行权限检查?
最佳答案
Authorize
属性本身仅用于指定您在特定页面或 Controller 上需要的授权类型。此属性旨在作为身份框架的补充使用,并且可以包括角色、策略和身份验证方案。
您需要在 Identity 框架和您的数据库之间创建一个桥梁,这可以通过自定义 UserStore
和 RoleStore
来完成,这在 this page 中有详细描述.
总结一个相当复杂的过程:
Authorize
属性指示浏览器验证您的用户- 您的用户被重定向到身份验证页面
- 如果成功,您将获得一个
ClaimsPrincipal
实例,然后您需要通过自定义UserStore
将其映射到您的数据库用户
- 然后可以根据数据库角色检查您的用户
这是所有这些操作的一个简短示例(不完整,因为代码太多)。
Startup.cs
// This class is what allows you to use [Authorize(Roles="Role")] and check the roles with the custom logic implemented in the user store (by default, roles are checked against the ClaimsPrincipal roles claims)
public class CustomRoleChecker : AuthorizationHandler<RolesAuthorizationRequirement>
{
private readonly UserManager<User> _userManager;
public CustomRoleChecker(UserManager<User> userManager)
{
_userManager = userManager;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, RolesAuthorizationRequirement requirement)
{
var user = await _userManager.GetUserAsync(context.User);
// for simplicity, I use only one role at a time in the attribute
var singleRole = requirement.AllowedRoles.Single();
if (await _userManager.IsInRoleAsync(user, singleRole))
context.Succeed(requirement);
}
}
public void ConfigureServices(IServiceCollection services)
{
services
.AddIdentity<User, Role>()
.AddUserStore<MyUserStore>()
.AddRoleStore<MyRoleStore>();
// custom role checks, to check the roles in DB
services.AddScoped<IAuthorizationHandler, CustomRoleChecker>();
}
User
和 Role
是您的 EF Core 实体。
我的用户商店
public class MyUserStore : IUserStore<User>, IUserRoleStore<User>, IQueryableUserStore<User>
{
private Context _db;
private RoleManager<Role> _roleManager;
...
public async Task<User> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
// bridge your ClaimsPrincipal to your DB users
var user = db.Users.SingleOrDefault(_ => _.Email.ToUpper() == normalizedUserName);
return await Task.FromResult(user);
}
...
public async Task<bool> IsInRoleAsync(User user, string roleName, CancellationToken cancellationToken)
{
if (roleName == null)
return true;
// your custom logic to check role in DB
var result = user.Roles.Any(_ => _.RoleName == roleName);
return await Task.FromResult(result);
}
关于c# - 来自数据库表的 ASP.NET Core 2 授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53754778/