我有一个需要使用自定义数据库进行角色授权的应用程序。数据库使用tblUsers
表建立,该表引用了tblRoles
表。用户也已经分配了他们的角色。
我还想在每个操作上使用[Authorize(Role = "RoleName")]
属性,以检查是否将经过身份验证的用户分配给数据库中的"RoleName"
。我在弄清楚需要在何处对[Authorize]
属性进行修改以使其具有这种行为时遇到了很多麻烦。我只想看看用户名是否具有角色,就没有一个页面来管理数据库中的角色。
我已经尝试实现custom storage providers for ASP.NET Core Identity,但是它开始看起来并不是我所需要的,因为我不打算管理应用程序中的角色,而且我无法确定它如何影响[Authorize]
的行为属性。
[此外,我对[Authorize]
属性的工作原理可能有一个错误的假设。如果您注意到了,请指出。
当我的客户要求为每个角色提供精细权限时,我遇到了类似的问题。我找不到修改Authorize属性的方法,但是能够使用自定义属性实现解决方案。但这取决于一件事,即您可以获取主叫用户的userId吗?我使用Cookie身份验证,因此当有人登录时,我只在声明中包含userId,因此当请求到来时,我总是可以从那里获取它。我认为asp.net中的内置Session逻辑也可以完成任务,但是我不能肯定地说。无论如何,自定义授权的逻辑是这样的:
像这样修改您的程序类:
public class Program { public static async Task Main(string[] args) { IWebHost webHost = CreateWebHostBuilder(args).Build(); using (var scope = webHost.Services.CreateScope()) { //Get the DbContext instance. Replace MyDbContext with the //actual name of the context in your program var context = scope.ServiceProvider.GetRequiredService<MyDbContext>(); List<User> users = await context.User.ToListAsync(); List<Role> roles = await context.Role.ToListAsync(); //You may make getters and setters, this is just to give you an idea UserRoleCache.users = users; UserRoleCache.roles = roles; } webHost.Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); }
然后是检查用户是否具有角色的逻辑。注意,我使用了一系列角色,因为有时您希望允许访问多个角色。
public class RoleRequirementFilter : IAuthorizationFilter { private readonly string[] _roles; public PermissionRequirementFilter(string[] roles) { _roles = roles; } public void OnAuthorization(AuthorizationFilterContext context) { bool hasRole = false; //Assuming there's a way you can get the userId var userId = GetUserId(); User user = UserRoleCache.users.FirstOrDefault(x => x.Id == userId); //Where roleType is the name of the role like Admin, Manager etc List<Role> roles = UserRoleCache.roles.FindAll(x => _roles.Contains(x.RoleType)) foreach(var role in roles) { if(user.RoleId == role.Id) { hasRole = true; break; } } if (!hasRole) context.Result = new StatusCodeResult(403); } }
最后创建角色属性
public class RoleAttribute : TypeFilterAttribute { public RoleAttribute(params string[] roles) : base(typeof(RoleRequirementFilter)) { Arguments = new object[] { roles }; } }
现在您可以在控制器中使用Role属性:
public class SampleController : ControllerBase
{
[HttpGet]
[Role("Admin", "Manager")]
public async Task<ActionResult> Get()
{
}
[HttpPost]
[Role("Admin")]
public async Task<ActionResult> Post()
{
}
}