[英]How to dynamically adding new roles with permissions in asp.net identity
我有自定义用户,角色,用户存储,角色存储。 我可以进行身份验证操作。 但是我要动态授权。 添加新角色和关系角色以及权限,并将此角色设置为用户。 我想要类似的东西https://imgur.com/jgl5xrs
用户模型
namespace App.Models
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("AppUsers")]
public class User
{
[Key, Required]
public Guid Id { get; set; }
[Required, MaxLength(128)]
public string UserName { get; set; }
[Required, MaxLength(1024)]
public string PasswordHash { get; set; }
[Required, MaxLength(128)]
public string Email { get; set; }
[MaxLength(32)]
public string EmployeeName { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
}
榜样
namespace App.Models
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Table("Role")]
public class Role
{
[Key, Required]
public Guid Id { get; set; }
[Required]
public string RoleName { get; set; }
public virtual ICollection<UserRole> UserRoles { get; set; }
}
}
UserStore
namespace App.Identity
{
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using App.Data;
using App.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore.Extensions.Internal;
public class UserStore : IUserStore<User>, IUserPasswordStore<User>
{
...
}
}
创建新角色时,需要发现所有控制器及其动作,然后选择角色可以访问哪些控制器和动作。
public class MvcControllerDiscovery : IMvcControllerDiscovery
{
private List<MvcControllerInfo> _mvcControllers;
private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider;
public MvcControllerDiscovery(IActionDescriptorCollectionProvider actionDescriptorCollectionProvider)
{
_actionDescriptorCollectionProvider = actionDescriptorCollectionProvider;
}
public IEnumerable<MvcControllerInfo> GetControllers()
{
if (_mvcControllers != null)
return _mvcControllers;
_mvcControllers = new List<MvcControllerInfo>();
var items = _actionDescriptorCollectionProvider
.ActionDescriptors.Items
.Where(descriptor => descriptor.GetType() == typeof(ControllerActionDescriptor))
.Select(descriptor => (ControllerActionDescriptor)descriptor)
.GroupBy(descriptor => descriptor.ControllerTypeInfo.FullName)
.ToList();
foreach (var actionDescriptors in items)
{
if (!actionDescriptors.Any())
continue;
var actionDescriptor = actionDescriptors.First();
var controllerTypeInfo = actionDescriptor.ControllerTypeInfo;
var currentController = new MvcControllerInfo
{
AreaName = controllerTypeInfo.GetCustomAttribute<AreaAttribute>()?.RouteValue,
DisplayName = controllerTypeInfo.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName,
Name = actionDescriptor.ControllerName,
};
var actions = new List<MvcActionInfo>();
foreach (var descriptor in actionDescriptors.GroupBy(a => a.ActionName).Select(g => g.First()))
{
var methodInfo = descriptor.MethodInfo;
actions.Add(new MvcActionInfo
{
ControllerId = currentController.Id,
Name = descriptor.ActionName,
DisplayName = methodInfo.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName,
});
}
currentController.Actions = actions;
_mvcControllers.Add(currentController);
}
return _mvcControllers;
}
}
在RoleController
和所有控制器的Create
action返回列表中:
public class RoleController : Controller
{
private readonly IMvcControllerDiscovery _mvcControllerDiscovery;
public RoleController(IMvcControllerDiscovery mvcControllerDiscovery)
{
_mvcControllerDiscovery = mvcControllerDiscovery;
}
// GET: Role/Create
public ActionResult Create()
{
ViewData["Controllers"] = _mvcControllerDiscovery.GetControllers();
return View();
}
}
有关发现剃须刀页面的信息,请阅读ASP.NET MVC Core中的发现控制器动作和剃须刀页面。
创建角色后,为用户分配角色并实施自定义授权过滤器,以检查天气用户是否可以访问请求的操作和控制器:
public class DynamicAuthorizationFilter : IAsyncAuthorizationFilter
{
private readonly ApplicationDbContext _dbContext;
public DynamicAuthorizationFilter(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (!IsProtectedAction(context))
return;
if (!IsUserAuthenticated(context))
{
context.Result = new UnauthorizedResult();
return;
}
var actionId = GetActionId(context);
var userName = context.HttpContext.User.Identity.Name;
var roles = await (
from user in _dbContext.Users
join userRole in _dbContext.UserRoles on user.Id equals userRole.UserId
join role in _dbContext.Roles on userRole.RoleId equals role.Id
where user.UserName == userName
select role
).ToListAsync();
foreach (var role in roles)
{
var accessList = JsonConvert.DeserializeObject<IEnumerable<MvcControllerInfo>>(role.Access);
if (accessList.SelectMany(c => c.Actions).Any(a => a.Id == actionId))
return;
}
context.Result = new ForbidResult();
}
我已经通过这种方式实现了基于角色的动态授权。 有关详细信息,请查看ASP.NET Core 2.0 github存储库中的基于动态角色的授权 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.