asp.net core 프로젝트 mvc 권한 제어:할당 권한

10254 단어 coremvc권한 제어
앞의 글 은 권한 제어,즉 컨트롤 러 나 방법 에 접근 할 때 현재 사용자 에 게 특정한 권한 을 가 져 야 하지만 프로그램 에서 권한 분 배 를 어떻게 하 는 지 소개 했다.Microsoft.AspNetCore.Identity.EntityFrameworkCore 프레임 워 크 를 이용 하여 권한 분 배 를 하 는 방법 을 소개 한다.
분배 방법 을 소개 하기 전에 우 리 는 권한 관 계 를 이해 해 야 한다.이 안 에는 세 가지 대상 이 포함 되 어 있다.사용자,역할,권한,권한 은 역할 에 분배 되 고 역할 은 사용자 에 게 분배 된다.특정한 사용자 가 특정한 역할 에 속 하면 이 사용 자 는 역할 에 포 함 된 권한 목록 을 가진다.예 를 들 어 현재 정보 관리자 역할 이 있다.이 역할 은 정보 삭제 권한 을 포함 하고 있 습 니 다.장 삼 이라는 사용자 가 정보 관리자 역할 을 가 진 후에 장 삼 은 정보 삭제 권한 을 가 집 니 다.일부 특수 한 장면 에서 권한 도 사용자 에 게 직접 분배 할 수 있다.즉,특정한 권한 을 캐릭터 를 돌아 서 사용자 에 게 직접 분배 할 수 있다.Microsoft.AspNetCore.Identity.Entity Framework Core 프레임 워 크 에서 이러한 지원 을 제공 합 니 다.
먼저 프레임 워 크 의 주요 업무 대상 류 를 소개 합 니 다.
Identity User:사용자 정보 표시
Identity Role:캐릭터 정보 표시
Identity RoleClaim:캐릭터 가 가 진 권한 표시
Identity UserClaim:사용자 가 가 진 권한 표시
IdentityUserRole:사용자 역할 관계 표시
기본 개념 을 이해 한 뒤 권한 분 배 를 어떻게 하 는 지 살 펴 보 자.
1.역할 할당 권한:Microsoft.AspNetCore.Identity.EntityFramework Core 에서 RoleManager 클래스 를 제공 하고 클래스 에서 역할 에 권한 을 배분 하 는 방법 을 제공 합 니 다.
  Task AddClaimAsync(TRole role, Claim claim)
첫 번 째 매개 변 수 는 해당 하 는 캐릭터 대상 을 나타 내 고 두 번 째 매개 변 수 는 권한 정 보 를 나타 낸다.
2.사용자 에 게 권한 할당:Microsoft.AspNetCore.Identity.Entity Framework Core 에서 UserManager 클래스 를 제공 합 니 다.클래스 에서 사용자 에 게 권한 을 할당 하 는 방법 을 제공 합 니 다.
  Task AddClaimAsync(TUser user, Claim claim)
첫 번 째 매개 변 수 는 해당 하 는 사용자 대상 을 표시 하고 두 번 째 매개 변 수 는 권한 정 보 를 표시 합 니 다.
3.사용자 역할 할당:UserManager 클래스 를 사용 하고 사용 하 는 방법:
  AddToRoleAsync(TUser user, string role)
첫 번 째 매개 변 수 는 사용자 대상 을 나타 내 고 두 번 째 는 캐릭터 의 이름 입 니 다.
4,캐릭터 가 현재 가지 고 있 는 권한 목록 가 져 오기:
 Task> RoleManager.GetClaimsAsync(TRole role)
5,사용자 가 현재 가지 고 있 는 권한 목록 가 져 오기:
 Task> UserManager.GetClaimsAsync(TUser user)
이러한 방식 을 통 해 권한 분배 전 과정 을 완성 할 수 있 고 앞의 권한 제어 방법 과 결합 하면 시스템 은 완 성 된 권한 제어 논 리 를 실현 할 수 있다.
그럼 지금 문제 가 왔 습 니 다.권한 목록 은 어디에서 옵 니까?일반적으로 하나의 업무 시스템 기능 이 확 정 된 후에 대응 하 는 권한 목록 도 자 연 스 럽 게 확정 되 었 다.그 다음 에 역할 에 대한 배분 권한 을 실현 하고 사용자 의 기능 에 권한 을 분배 할 때 페이지 에서 모든 권한 을 열거 하여 선택 하면 된다.효과 도 는 다음 과 같다
선택 한 데 이 터 를 대응 하 는 방법 으로 저장 하면 됩 니 다.
이 문 제 는 해결 되 었 지만 새로운 문제 가 또 왔 다.만약 에 하나의 업무 기능 점 이 특히 많 으 면 권한 도 많 을 것 이다.만약 에 완전히 수공 으로 페이지 에 쓰 면 자연 작업량 이 많 을 것 이다.게다가 업무 시스템 이 계속 변화 할 수도 있다.이 럴 때 권한 배분 페이지 를 계속 수정 하 는 것 도 좋 은 방법 이 아니다.다음은 제 가 여러분 께 제 가 생각 하 는 방법 중 하 나 를 말씀 드 리 겠 습 니 다.꼭 가장 좋 은 것 은 아니 지만 큰 일 을 절약 할 수 있 습 니 다.
첫 번 째 쇼 에서 우리 가 해결 해 야 할 문 제 는 이 권한 설정 목록 을 어떻게 빨리 만 드 느 냐 하 는 것 입 니 다.
아 이 디 어 는 Authorize Attribute 를 개조 하여 이 특성 을 바탕 으로 권한 설명 정 보 를 추가 하고 권한 설명 정 보 를 Policy 로 하 는 것 입 니 다.아래 코드 바로 올 리 기:

[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;
        }
      }
    }
  }
클래스 가 정의 되 었 습 니 다.그러면 우 리 는 어떻게 사용 하 는 지 보 겠 습 니 다.특성 정의 이기 때문에 컨트롤 러 클래스 나 방법 에 따라 아래 구조 에 따라 사용 할 수 있 습 니 다.
[리 소스("조직 구조",Action="부서 추가")]
여기까지 기초 작업 이 끝 났 으 니 다음 에 해결 해 야 할 두 가지 문제 가 있다.
1.Policy 는 현재 이름 만 설정 되 어 있 지만 구체 적 인 검증 규칙 은 정의 되 지 않 았 습 니 다.
2,모든 권한 목록 을 가 져 오 는 방법
먼저 첫 번 째 문 제 를 살 펴 보 겠 습 니 다.앞의 글 은 Policy 가 startup 에서 AddAuthorization 을 통 해 미리 설정 해 야 한다 고 소 개 했 습 니 다.하지만 지금 은 이러한 절 차 를 밟 지 않 았 기 때문에 아직 권한 이 작 동 하지 않 습 니 다.프레임 워 크 는 권한 검증 을 할 때 IAuthorization Policy Provider 에 의존 하여 Policy 이름 에 따라 구체 적 인 규칙 을 가 져 옵 니 다.자 연 스 럽 게 IAuthorization Policy Provider 를 사용자 정의 하여 실현 할 생각 입 니 다.코드 는 다음 과 같 습 니 다.

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[] { '-' }, 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>
IAuthorization Policy Provider 를 실현 하면 startup.cs 의 Configure Services(IServiceCollection services)방법 에 등록 해 야 합 니 다.다음 과 같이 조작 해 야 합 니 다.
services.TryAdd(ServiceDescriptor.Transient());
두 번 째 문 제 를 살 펴 보면 우 리 는 컨트롤 러 나 방법 에 권한 정 보 를 정 의 했 습 니 다.관건 은 우리 가 이러한 특성 에서 권한 목록 을 어떻게 얻 느 냐 하 는 것 입 니 다.앞으로 권한 배분 에 사용 할 때 사용 하 는 것 입 니 다.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());
그리고 권한 분배 페이지 에서 리 소스 데이터.Resources 를 통 해 모든 권한 정 보 를 얻 은 다음 순환 을 통 해 페이지 에 직접 표시 하면 됩 니 다. 
드디어 다 썼어 요.하하~~

좋은 웹페이지 즐겨찾기