繁体   English   中英

如何动态添加具有asp.net身份权限的新角色

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM