asp.net-mvc - asp net identity claims




asp.net mvc 장식[권한()] 여러 enums 함께 (5)

컨트롤러가있어서 두 가지 역할을 통해 액세스 할 수 있어야합니다. 1-admin 또는 2-moderator

[권한 부여 (역할 = "관리자, 중재자")] 할 수 있음을 알고 있지만 열거 형에서 내 역할을 수행합니다. 열거 형에서는 하나의 역할 만 권한을 부여 할 수 있습니다. 나는 두 권을 인증하는 방법을 알 수 없다.

나는 [Authorize (Roles = MyEnum.Admin, MyEnum.Moderator)]와 같은 것을 시도했지만 컴파일이 안된다.

누군가 한 번이 제안 :

 [Authorize(Roles=MyEnum.Admin)]
 [Authorize(MyEnum.Moderator)]
 public ActionResult myAction()
 {
 }

하지만 OR로 작동하지는 않습니다. 나는이 경우 사용자가 두 역할의 일부가되어야한다고 생각한다. 나는 어떤 구문을 간과하고 있는가? 아니면 내 자신의 권한을 굴려야하는 경우입니까?


@CalebHC와 @Lee Harold의 답변에 기반한 나의 버전이 있습니다.

속성에서 명명 된 매개 변수를 사용하는 스타일을 따라 기본 클래스 인 Roles 속성을 재정의했습니다.

@ CalebHC의 대답은 AuthorizeCore() 가 재정의 (기본 클래스에서 역할을 사용하는)되므로 우리 고유의 Roles 을 사용하는 것이 타당하므로 새로운 Is 속성을 사용합니다. 우리 자신의 Roles 을 사용하여 컨트롤러에 Roles = Roles.AdminRoles = Roles.Admin 됩니다.이 속성은 다른 .Net 특성의 스타일을 따릅니다.

CustomAuthorizeAttribute 에 두 개의 생성자를 CustomAuthorizeAttribute 하여 전달되는 실제 활성 디렉토리 그룹 이름을 표시했습니다. 프로덕션에서는 클래스의 마술 문자열을 피하기 위해 매개 변수화 된 생성자를 사용합니다. Application_Start() 중에 그룹 이름을 web.config에서 가져 와서 전달합니다. DI 도구를 사용하여 생성.

Views\Shared 폴더에 NotAuthorized.cshtml 또는 유사 항목이 있어야합니다. NotAuthorized.cshtml 않으면 권한이없는 사용자에게 오류 화면이 표시됩니다.

다음은 AuthorizationAttribute.cs 기본 클래스의 코드입니다.

제어 장치:

public ActionResult Index()
{
  return this.View();
}

[CustomAuthorize(Roles = Roles.Admin)]
public ActionResult About()
{
  return this.View();
}

CustomAuthorizeAttribute :

// The left bit shifting gives the values 1, 2, 4, 8, 16 and so on.
[Flags]
public enum Roles
{
  Admin = 1,
  User = 1 << 1    
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
  private readonly string adminGroupName;

  private readonly string userGroupName;

  public CustomAuthorizeAttribute() : this("Domain Admins", "Domain Users")
  {      
  }

  private CustomAuthorizeAttribute(string adminGroupName, string userGroupName)
  {
    this.adminGroupName = adminGroupName;
    this.userGroupName = userGroupName;
  }

  /// <summary>
  /// Gets or sets the allowed roles.
  /// </summary>
  public new Roles Roles { get; set; }

  /// <summary>
  /// Checks to see if the user is authenticated and has the
  /// correct role to access a particular view.
  /// </summary>
  /// <param name="httpContext">The HTTP context.</param>
  /// <returns>[True] if the user is authenticated and has the correct role</returns>
  /// <remarks>
  /// This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method.
  /// </remarks>
  protected override bool AuthorizeCore(HttpContextBase httpContext)
  {
    if (httpContext == null)
    {
      throw new ArgumentNullException("httpContext");
    }

    if (!httpContext.User.Identity.IsAuthenticated)
    {
      return false;
    }

    var usersRoles = this.GetUsersRoles(httpContext.User);

    return this.Roles == 0 || usersRoles.Any(role => (this.Roles & role) == role);
  }

  protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
  {
    if (filterContext == null)
    {
      throw new ArgumentNullException("filterContext");
    }

    filterContext.Result = new ViewResult { ViewName = "NotAuthorized" };
  }

  private IEnumerable<Roles> GetUsersRoles(IPrincipal principal)
  {
    var roles = new List<Roles>();

    if (principal.IsInRole(this.adminGroupName))
    {
      roles.Add(Roles.Admin);
    }

    if (principal.IsInRole(this.userGroupName))
    {
      roles.Add(Roles.User);
    }

    return roles;
  }    
}

CalebHC의 코드에 추가하고 여러 역할을 가진 사용자를 처리하는 ssmith의 질문에 대답하려면 ...

사용자 지정 보안 주체는 사용자가 속한 모든 그룹 / 역할을 나타내는 문자열 배열을 반환합니다. 먼저 열의 항목과 일치하는 배열의 모든 문자열을 변환해야합니다. 마지막으로 일치하는 항목을 찾습니다. 일치하는 경우 사용자에게 권한이 부여됩니다.

권한이없는 사용자를 사용자 지정 "NotAuthorized"보기로 리디렉션합니다.

전체 클래스는 다음과 같습니다.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    /// <summary>
    /// Add the allowed roles to this property.
    /// </summary>
    public Roles Is { get; set; }

    /// <summary>
    /// Checks to see if the user is authenticated and has the
    /// correct role to access a particular view.
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
            throw new ArgumentNullException("httpContext");

        if (!httpContext.User.Identity.IsAuthenticated)
            return false;

        var iCustomPrincipal = (ICustomPrincipal) httpContext.User;

        var roles = iCustomPrincipal.CustomIdentity
                        .GetGroups()
                        .Select(s => Enum.Parse(typeof (Roles), s))
                        .ToArray();

        if (Is != 0 && !roles.Cast<Roles>().Any(role => ((Is & role) == role)))
        {
            return false;
        }

        return true;
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext == null)
            throw new ArgumentNullException("filterContext");

        filterContext.Result = new ViewResult { ViewName = "NotAuthorized" };
    } 
}

다음 구문을 사용하면 간단 하고 우아한 솔루션을 얻을 수 있습니다.

[AuthorizeRoles(MyEnum.Admin, MyEnum.Moderator)]

자신의 속성을 만들 때 생성자에서 params 키워드를 사용하십시오.

public class AuthorizeRoles : AuthorizeAttribute
{
    public AuthorizeRoles(params MyEnum[] roles)
    {
        ...
    }
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        ...
    }
}

이렇게하면 다음과 같이 속성을 사용할 수 있습니다.

[AuthorizeRoles(MyEnum.Admin, MyEnum.Moderator)]
public ActionResult myAction()
{
}

다음과 같이 비트 OR 연산자를 사용해보십시오.

[Authorize(Roles= MyEnum.Admin | MyEnum.Moderator)]
public ActionResult myAction()
{
}

그것이 작동하지 않으면, 당신은 자신의 롤 수 있습니다. 나는 현재 내 프로젝트에서이 작업을 수행했다. 여기 내가 한 일이있다.

public class AuthWhereRole : AuthorizeAttribute
{
    /// <summary>
    /// Add the allowed roles to this property.
    /// </summary>
    public UserRole Is;

    /// <summary>
    /// Checks to see if the user is authenticated and has the
    /// correct role to access a particular view.
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext == null)
            throw new ArgumentNullException("httpContext");

        // Make sure the user is authenticated.
        if (!httpContext.User.Identity.IsAuthenticated)
            return false;

        UserRole role = someUser.Role; // Load the user's role here

        // Perform a bitwise operation to see if the user's role
        // is in the passed in role values.
        if (Is != 0 && ((Is & role) != role))
            return false;

        return true;
    }
}

// Example Use
[AuthWhereRole(Is=MyEnum.Admin|MyEnum.Newbie)]
public ActionResult Test() {}

또한 열거 형에 flags 속성을 추가하고 값이 모두 1 이상이어야합니다. 이렇게 :

[Flags]
public enum Roles
{
    Admin = 1,
    Moderator = 1 << 1,
    Newbie = 1 << 2
    etc...
}

왼쪽 비트 시프 팅은 값 1, 2, 4, 8, 16 등을 제공합니다.

글쎄, 나는 이것이 조금 도움이되기를 바랍니다.


시험

public class CustomAuthorize : AuthorizeAttribute
{
    public enum Role
    {
        DomainName_My_Group_Name,
        DomainName_My_Other_Group_Name
    }

    public CustomAuthorize(params Role[] DomainRoles)
    {
        foreach (var domainRole in DomainRoles)
        {
            var domain = domainRole.ToString().Split('_')[0] + "_";
            var role = domainRole.ToString().Replace(domain, "").Replace("_", " ");
            domain=domain.Replace("_", "\\");
            Roles += ", " + domain + role;
        }
        Roles = Roles.Substring(2);
    }       
}

public class HomeController : Controller
{
    [CustomAuthorize(Role.DomainName_My_Group_Name, Role.DomainName_My_Other_Group_Name)]
    public ActionResult Index()
    {
        return View();
    }
}




roles