>백엔드 개발 >C#.Net 튜토리얼 >asp.net 핵심 프로젝트 mvc 권한 제어 할당된 권한의 그래픽 세부 정보

asp.net 핵심 프로젝트 mvc 권한 제어 할당된 권한의 그래픽 세부 정보

黄舟
黄舟원래의
2017-03-06 11:05:182437검색

배우는 가장 좋은 방법은 직접 해보는 것입니다. 여기서는 Asp.net Core를 처음부터 경험하고 학습할 수 있는 공통 권한 관리 시스템을 개발하겠습니다. 프로젝트의 전반적인 계획은 대략 다음과 같습니다

이전 글에서는 권한을 제어하는 ​​방법, 즉 컨트롤러나 메소드에 접근할 때 현재 사용자가 특정 권한을 가지고 있어야 하는데, 권한을 할당하는 방법에 대해 소개했습니다. 프로그램? 다음은 Microsoft.AspNetCore.Identity.EntityFrameworkCore 프레임워크를 사용하여 권한을 할당하는 방법을 소개합니다.

할당 방법을 소개하기 전에 사용자, 역할, 권한이라는 세 가지 개체가 포함된 권한 관계를 이해해야 합니다. 권한은 역할에 할당되고, 역할은 사용자에게 할당됩니다. 특정 역할을 추가한 후 사용자는 역할에 포함된 권한 목록을 갖게 됩니다. 예를 들어, 사용자 Zhang San이 정보 관리자 역할을 갖고 있는 경우 정보 관리자 역할이 있습니다. 정보 삭제 권한이 있습니다. 일부 특수한 시나리오에서는 권한을 사용자에게 직접 할당할 수도 있습니다. 즉, 역할을 우회하고 특정 권한을 사용자에게 직접 할당할 수 있습니다. 이러한 지원은 Microsoft.AspNetCore.Identity.EntityFrameworkCore 프레임워크에서 제공됩니다.

먼저 프레임워크의 주요 비즈니스 객체 클래스를 소개합니다.

IdentityUser: 사용자 정보를 나타냅니다.

IdentityRole: 역할 정보를 나타냅니다.

IdentityRoleClaim69607a3a292fbf48652d49af055eb41e: 사용자의 권한을 나타냅니다

IdentityUserRole7c013bef549e108856916cfbe0707d60: 사용자 역할 관계를 나타냅니다


기본 개념을 이해한 후, 권한 할당 방법을 살펴보겠습니다.

1. 역할에 권한 할당: Microsoft.AspNetCore.Identity.EntityFrameworkCore는 역할에 권한을 할당하는 메서드를 제공하는 RoleManager 클래스를 제공합니다.

Task9b1f9e47eb1620cf27a98765de10fb89 클레임)

 첫 번째 매개변수는 해당 역할 개체를 나타내고, 두 번째 매개변수는 권한 정보를 나타냅니다

2. 사용자에게 권한 할당: Microsoft.AspNetCore.Identity.EntityFrameworkCore UserManager 클래스가 제공됩니다. 사용자에게 권한을 할당하기 위한 메서드를 제공하는 클래스에서:

Task9b1f9e47eb1620cf27a98765de10fb89 AddClaimAsync(TUser user, Claim Claim)

첫 번째 매개변수는 해당 사용자 개체를 나타내고, 두 번째 매개변수는 권한 정보

3, 사용자에게 역할 할당: UserManager 클래스도 사용되며, 사용된 메소드:

 AddToRoleAsync(TUser user, string role)

첫 번째 매개변수 사용자 개체를 나타내며 두 ​​번째 매개 변수는 역할의 이름입니다.

4. 현재 역할이 소유한 권한 목록을 가져옵니다.

Taskfebce605adaafd9dd572348f5a5bf2a8 GetClaimsAsync(TRole 역할)

5, 사용자가 현재 가지고 있는 권한 목록을 가져옵니다.

Taskfebce605adaafd9dd572348f5a5bf2a8> UserManager.GetClaimsAsync(TUser user)

이러한 방식으로 전체 권한 할당 프로세스를 완료할 수 있으며, 이전 권한 제어 방법과 결합하여 시스템은 완전한 권한 제어 논리를 실현할 수 있습니다.

이제 질문은 권한 목록이 어디에서 오는가입니다. 일반적으로 비즈니스 시스템 기능이 결정되면 해당 권한 목록이 자연스럽게 결정됩니다. 역할에 권한을 할당하고 사용자에게 권한을 할당할 때 선택을 위해 페이지에 모든 권한을 나열하기만 하면 됩니다. 예, 렌더링은 다음과 같습니다.

해당 메소드를 호출하면 선택한 데이터가 저장됩니다.

이 문제는 해결되었지만 새로운 문제가 발생합니다. 비즈니스 기능에 포인트가 너무 많으면 자연스럽게 많은 권한이 발생하고, 페이지에 완전히 수동으로 작성하면 작업량도 당연히 매우 커질 수 있습니다. , 권한 할당 페이지도 지속적으로 수정하겠습니다. 이는 당연히 좋은 방법이 아니지만 최선은 아닐 수도 있지만 많은 수고를 덜 수 있습니다.

첫 번째 쇼에서 해결해야 할 문제는 이 권한 구성 목록을 빠르게 생성하는 방법입니다.

AuthorizeAttribute를 변환하고, 이 기능을 기반으로 권한 설명 정보를 추가하고, 권한 설명 정보를 정책으로 사용하는 것이 아이디어입니다. 바로 코드로 가보겠습니다:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited =true)]  //类名称可以改,因为我把系统操作当作资源来管理
  public class ResourceAttribute:AuthorizeAttribute
  {
    private string _resouceName;
    private string _action;
    public ResourceAttribute(string name)
    {
      if (string.IsNullOrEmpty(name))
      {
        throw new ArgumentNullException(nameof(name));
      }
      _resouceName = name;
       //把资源名称设置成Policy名称
      Policy = _resouceName;
    }
 
    public string GetResource()
    {
      return _resouceName;
    }
    public string Action
    {
      get
      {
        return _action;
      }
      set
      {
        _action = value;
        if (!string.IsNullOrEmpty(value))
        {            //把资源名称跟操作名称组装成Policy
          Policy = _resouceName + "-" + value;
        }
      }
    }
  }

클래스가 정의되었으니 어떻게 사용하는지 살펴보겠습니다. 컨트롤러 클래스에서 또는 다음 구조에 따라 메소드를 사용합니다.

[Resource("Organizational Structure", Action = "Add Department")]

이제 기본 작업은 완료되었는데 아직 두 가지 질문이 있습니다. 해결 방법:

1. 정책은 이름으로만 구성되어 있지만 구체적인 확인 규칙은 정의되어 있지 않습니다.

2. 모든 권한 목록 획득


先来看第一个问题,前面的文章介绍了,Policy需要提前在startup里通过AddAuthorization进行配置,但是现在我们并没有做这样的步骤,所以目前权限还不会起作用。框架在权限验证的时候,会依赖一个IAuthorizationPolicyProvider来根据Policy名称获取具体的规则,自然我们会想到自定义一个IAuthorizationPolicyProvider实现,代码如下:

public class ResourceAuthorizationPolicyProvider : IAuthorizationPolicyProvider
  {
    private AuthorizationOptions _options;
    public ResourceAuthorizationPolicyProvider(IOptions<authorizationoptions> options)
    {
      if (options == null)
      {
        throw new ArgumentNullException(nameof(options));
      }
 
      _options = options.Value;
    }
    public Task<authorizationpolicy> GetDefaultPolicyAsync()
    {
      return Task.FromResult(_options.DefaultPolicy);
    }
  
    public Task<authorizationpolicy> GetPolicyAsync(string policyName)
    {
      AuthorizationPolicy policy = _options.GetPolicy(policyName);       //因为我们policy的名称其实就是对应的权限名称,所以可以用下列逻辑返回需要的验证规则
      if (policy == null)
      {
        string[] resourceValues = policyName.Split(new char[] { &#39;-&#39; }, StringSplitOptions.None);
        if (resourceValues.Length == 1)
        {
          _options.AddPolicy(policyName, builder =>
          {
            builder.AddRequirements(new ClaimsAuthorizationRequirement(resourceValues[0], null));
          });
        }
        else
        {
          _options.AddPolicy(policyName, builder =>
          {
            builder.AddRequirements(new ClaimsAuthorizationRequirement(resourceValues[0], new string[] { resourceValues[1] }));
          });
        }
      }
      return Task.FromResult(_options.GetPolicy(policyName));
    }
  }
</authorizationpolicy></authorizationpolicy></authorizationoptions>


实现了IAuthorizationPolicyProvider,我们就需要在startup.cs的ConfigureServices(IServiceCollection services)方法中进行注册,操作如下:


复制代码 代码如下:

services.TryAdd(ServiceDescriptor.Transientd35cc227e13486608ede2963927abb51());

再来看第二个问题,我们已经在控制器或者方法上定义了权限信息,关键是我们如何从这些特性里获取到权限列表,将来用于权限分配的时候使用。在asp.net core mvc中提供了一个类解析机制,IApplicationModelProvider,这个依赖信息比较多,这里就不过多介绍,后续我会单独开一个系列,介绍asp.net core mvc的内部机制。

直接上代码

public class ResourceApplicationModelProvider : IApplicationModelProvider
  {
    private readonly IAuthorizationPolicyProvider _policyProvider;
 
    public ResourceApplicationModelProvider(IAuthorizationPolicyProvider policyProvider)
    {
      _policyProvider = policyProvider;
    }
     
 
    public void OnProvidersExecuted(ApplicationModelProviderContext context)
    {
      
    }
 
    public void OnProvidersExecuting(ApplicationModelProviderContext context)
    {
      if (context == null)
      {
        throw new ArgumentNullException(nameof(context));
      }
 
      List<resourceattribute> attributeData = new List<resourceattribute>();        //循环获取所有的控制器
      foreach (var controllerModel in context.Result.Controllers)
      {        //得到ResourceAttribute
        var resourceData = controllerModel.Attributes.OfType<resourceattribute>().ToArray();
        if (resourceData.Length > 0)
        {
          attributeData.AddRange(resourceData);
        }
          //循环控制器方法
        foreach (var actionModel in controllerModel.Actions)
        {          //得到方法的ResourceAttribute
          var actionResourceData = actionModel.Attributes.OfType<resourceattribute>().ToArray();
          if (actionResourceData.Length > 0)
          {
            attributeData.AddRange(actionResourceData);
          }
        }
      }
       //把所有的resourceattribute的信息写到一个全局的resourcedata中,resourcedata就可以在其他地方进行使用,resourcedata定义后面补充 
      foreach (var item in attributeData)
      {
        ResourceData.AddResource(item.GetResource(), item.Action);
      }
    }
 
    public int Order { get { return -1000 + 11; } }
  }
</resourceattribute></resourceattribute></resourceattribute></resourceattribute>

resourcedata定义如下

public class ResourceData
  {
    static ResourceData()
    {
      Resources = new Dictionary<string, List<string>>();
    }
 
    public static void AddResource(string name)
    {
      AddResource(name, "");
    }
 
    public static void AddResource(string name,string action)
    {
      if (string.IsNullOrEmpty(name))
      {
        return;
      }
      if (!Resources.ContainsKey(name))
      {
        Resources.Add(name, new List<string>());
      }
 
      if (!string.IsNullOrEmpty(action) && !Resources[name].Contains(action))
      {
        Resources[name].Add(action);
      }
    }
 
    public static Dictionary<string, List<string>> Resources { get; set; }
  }

 然后在startup中注册我们刚刚定义的IApplicationModelProvider:


复制代码 代码如下:

services.TryAddEnumerable(ServiceDescriptor.Transient<IApplicationModelProvider, ResourceApplicationModelProvider>());

 然后在权限分配页面通过ResourceData.Resources就获取到了所有的权限信息,然后通过循环的方式直接显示到页面上即可。 

终于写完了,哈哈~~

以上就是asp.net core项目mvc权限控制 分配权限的图文详情的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.