여러 역할이있는 속성 권한 부여


97

한 번에 여러 역할에 대한 권한을 컨트롤러에 추가하고 싶습니다.

일반적으로 다음과 같습니다.

[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}

하지만 특정 시점에서 변경되거나 확장 될 수 있으므로 내 역할을 const에 저장했습니다.

public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";

컴파일 타임에 문자열을 알아야하기 때문에이 작업을 수행 할 수 없습니다.

[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}

문제를 피할 수있는 방법이 있습니까?

나는 단순히 "RoleA, RoleB, RoleC"를 포함하는 const를 작성할 수있다. 그러나 나는 마법의 문자열을 싫어하고 이것은 마법의 문자열이다. 역할 이름을 변경하고 결합 된 문자열을 변경하는 것을 잊는 것은 재앙이 될 것입니다.

MVC5를 사용하고 있습니다. ASP.NET ID와 역할은 컴파일 타임에 알려집니다.


public const string RoleA = "RoleA"를 사용하고 있습니까? 또는 당신이 질문에서 쓴대로?
— Mukesh Modhvadiya 2014-06-12

답변:


188

같은 사용자 지정 권한 부여 특성을 만들어보십시오 이 .

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = string.Join(",", roles);
    }
}

여러 컨트롤러에서 역할이 동일하다고 가정하고 도우미 클래스를 만듭니다.

public static class Role
{
    public const string Administrator = "Administrator";
    public const string Assistant = "Assistant";
}

그런 다음 다음과 같이 사용하십시오.

public class MyController : Controller
{
    [AuthorizeRoles(Role.Administrator, Role.Assistant)]
    public ActionResult AdminOrAssistant()
    {                       
        return View();
    }
}

12
이제 맥 Gyver의 가치 아이디어입니다)
— 기독교 사우어

2
아주 좋은 해결책 :)
— aup

1
또한이 솔루션을 많이 좋아합니다. 특히 내 역할을 문자열이 아닌 열거 형으로 만들 수 있기 때문입니다. 이 사용자 지정 권한 부여 특성을 배치하기위한 프로젝트 계층 구조에서 좋은 네임 스페이스와 위치는 무엇입니까?
— Simon Shine

4
나는 여기서 무슨 일이 일어나고 있는지 잘 모르겠지만 이것은 도움이되지 않았으며 역할에 관계없이 모든 사용자가 메소드에 액세스 할 수있었습니다.
— Urielzen

2
@Urielzen과 동일한 문제이지만 Jerry Finegan ( "System.Web.Mvc.AuthorizeAttribute 및 Not System.Web.Http.AuthorizeAttribute 사용"사용)의 아래 답변에 의해 해결되었습니다
— RJB

13

사용자 정의 속성 클래스를 파생 System.Web.Mvc.AuthorizeAttribute시키지 않고 파생하고 있는지 확인하십시오 System.Web.Http.AuthorizeAttribute.

나는 같은 문제에 부딪쳤다. 일단 변경하면 모든 것이 작동했습니다.

사용자 정의 속성 클래스에 다음을 추가 할 수도 있습니다.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 

나는 방금 이것을 시도하고 도서관 System.Web.Http.AuthorizeAttributeINSTEAD OFSystem.Web.Mvc.AuthorizeAttribute
— fraser jordan을

10

이 문제를 해결하기 위해 찾은 가장 좋고 간단한 방법은 Authorize 속성에서 역할을 연결하는 것입니다.

[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]

CustomRole을 사용하여 다음과 같은 상수 문자열을 가진 클래스 :

public static class CustomRoles
{
    public const string Admin = "Admin";
    // and so on..
}

2
가치있는; 그러나 이것은 주석이어야합니다. 대답이 아닙니다.
— GhostCat

1
간단하고 우아한 솔루션!
— Iosif Bancioiu

귀하의 답변과 수락 된 답변 모두 올바르게 구현되면 승인이 트리거됩니다 (프로덕션 웹 앱에서 수락 된 것을 사용하고 있습니다). 수락 된 답변에 대한 주석을 제거하기위한 편집을 제안합니다.
— Eric Eskildsen

3

내가 한 것은 @Tieson의 대답입니다.

나는 그의 대답을 약간 조정했습니다. string.Join 대신 목록으로 변환하지 않으시겠습니까?

내 대답은 다음과 같습니다.

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    private new List<string> Roles;
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = roles.toList()
    }
}

그런 다음 OnAuthorization을 재정 의하여 역할이 유효한지 확인하십시오.

public override void OnAuthorization(HttpActionContext actionContext)
{
            if (Roles == null)
                HandleUnauthorizedRequest(actionContext);
            else
            {
                ClaimsIdentity claimsIdentity = HttpContext.Current.User.Identity as ClaimsIdentity;
                string _role = claimsIdentity.FindFirst(ClaimTypes.Role).Value;
                bool isAuthorize = Roles.Any(role => role == _role);

                if(!isAuthorize)
                    HandleUnauthorizedRequest(actionContext);
            }
        }

이제 역할이 리소스에 액세스 할 수있는 권한이 있는지 확인하고 있습니다.


1

역할이 많지 않으면 사용자 지정 권한 부여 속성이이 문제에 대해 과도하다고 생각합니다.

문자열은 컴파일 타임에 알려야하므로 정의한 역할의 공용 문자열이 포함 된 정적 Role 클래스를 만든 다음 권한을 부여하려는 특정 역할과 함께 쉼표로 구분 된 문자열을 추가하는 것이 좋습니다.

public static class Roles
{
    public const string ADMIN = "Admin";
    public const string VIEWER = "Viewer";

    public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER;
}

그런 다음 컨트롤러 클래스 또는 컨트롤러 메서드 (또는 둘 다)에서 권한 부여 속성을 사용할 수 있습니다.

[Authorize(Roles = Roles.ADMIN]
public class ExampleController : Controller
{
    [Authorize(Roles = Roles.ADMIN_OR_VIEWER)
    public ActionResult Create()
    {
        ..code here...
    }
}

1
이 예는 작동하지 않거나 적어도 생각하는 방식이 아닙니다. 예를 들어, 새롭지 만 ADMIN_OR_VIEWER작업에 대한 역할은 중복됩니다 . 역할이 Create아직 없으면 메서드에 액세스 할 수 없기 때문 ADMIN입니다. 이 경우 메서드 VIEWER를 호출 할 수 없습니다 Create.
— 존 Leidegren

이 솔루션도 확장 가능하지 않습니다. 거기 당신은 다른 작업에 너무 많은 역할을 어디에 포인트가 될 것입니다 그리고 당신은 모든 조합을 만들 야해
— EduLopez
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.