여러 역할이 컨트롤러 작업에 액세스하도록 허용


274

지금은 "멤버"가 내 컨트롤러 작업에 액세스 할 수 있도록 이와 같은 방법을 장식합니다.

[Authorize(Roles="members")]

둘 이상의 역할을 어떻게 허용합니까? 예를 들어 다음은 작동하지 않지만 수행하려는 작업 ( "멤버"및 "관리자"액세스 허용)을 보여줍니다.

[Authorize(Roles="members", "admin")] 

4
이 질문에 대한 답변을 변경하십시오. 현재 승인 된 답변을받은 사람이 자신이 틀렸다는 것을 표시하여 편집했습니다.
Eric J.

답변:


595

다른 옵션은 게시 할 때 단일 권한 부여 필터를 사용하지만 내부 견적을 제거하는 것입니다.

[Authorize(Roles="members,admin")]

5
MVC 5에서도 작동합니다. +1
gkonuralp

4
ASP.NET Core 1.0 (MVC 6) 및 Microsoft.AspNet.Identity v3. *에서 작동
Soren

3
권한이 필요한 컨트롤러가 하나만 있으면 괜찮습니다. 둘 이상인 경우 해당 문자열 상수를 복제합니다 (yuck). 역할 이름이있는 정적 클래스를 선호합니다. 내 애완 동물 증오 중복 문자열 ... 너무 나쁘다.
robnick

1
@kraeg 문제를 해결했다는 희소식. 이제 코멘트를 삭제하십시오.
Pablo Claus

1
왜? 이것을 해결하는 데는 오랜 시간이 걸렸습니다. 같은 문제가 발생하는 다른 사람에게 도움이 될 수 있습니다.
kraeg

129

사용자 정의 역할을 사용하려면 다음을 수행하십시오.

CustomRoles 수업:

public static class CustomRoles
{
    public const string Administrator = "Administrador";
    public const string User = "Usuario";
}

용법

[Authorize(Roles = CustomRoles.Administrator +","+ CustomRoles.User)]

역할이 거의 없다면 다음과 같이 명확하게 표현할 수 있습니다.

public static class CustomRoles
{
     public const string Administrator = "Administrador";
     public const string User = "Usuario";
     public const string AdministratorOrUser = Administrator + "," + User;  
}

용법

[Authorize(Roles = CustomRoles.AdministratorOrUser)]

7
CustomRoles의 배후를 모르는 사람들에게 설명하면 좋은 대답이 될 것입니다.
James Skemp

1
@JamesSkemp 알았어, 나는 대답을 확장했다. 매우 간단합니다. CustumRoles는 내 응용 프로그램 역할에 해당하는 상수를 포함하는 내가 만든 클래스입니다. 나는 몇 가지 이유로 그렇게했습니다 : 1) 철자를 사용하여 철자 실수를 피할 수 있습니다 2) 유지 보수를 단순화합니다. 역할이 변경되면 응용 프로그램 내에서 한 곳만 업데이트하면됩니다.
Pablo Claus

@Pabloker 또는 Flags 속성을 사용하여 열거 형을 만들 수 있습니다 (예 : Convert.ToString (CustomRoles.Administrator | CustomRoles.User); - 짜증나는 부분이 명시 적 변환을 필요로한다는 것이다
cstruter

39 개의 역할이 있다면?
Kiquenet

귀하의 문제는 .net으로 할 수있는 것 이상의 허가 모델링을 거치는 것 같습니다
Pablo Claus

82

하나의 가능한 단순화는 서브 클래스 일 것입니다 AuthorizeAttribute:

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

용법:

[Roles("members", "admin")]

의미 상 그것은 Jim Schmehil의 대답과 동일합니다.


3
이것은 나를 위해 작동하지 않았습니다. 로그인 한 사용자가 사용자에게 역할이 없어도 속성을 무시할 수있었습니다.
Urielzen

9
즉, [역할 (Constants.Admin, Constants.Owner)] :이 대답은 당신이 당신의 값으로 상수를 사용하는 경우 더 나은입니다
dalcam

3
이 최고의 답변입니다
IgorShch

18

MVC4의 경우 내 역할과 함께 Enum( UserRoles)를 사용하여 사용자 지정을 사용합니다.AuthorizeAttribute .

통제 된 행동에 대해 다음과 같이합니다.

[CustomAuthorize(UserRoles.Admin, UserRoles.User)]
public ActionResult ChangePassword()
{
    return View();
}

그리고 나는 그런 관습을 사용 AuthorizeAttribute합니다 :

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorize : AuthorizeAttribute
{
    private string[] UserProfilesRequired { get; set; }

    public CustomAuthorize(params object[] userProfilesRequired)
    {
        if (userProfilesRequired.Any(p => p.GetType().BaseType != typeof(Enum)))
            throw new ArgumentException("userProfilesRequired");

        this.UserProfilesRequired = userProfilesRequired.Select(p => Enum.GetName(p.GetType(), p)).ToArray();
    }

    public override void OnAuthorization(AuthorizationContext context)
    {
        bool authorized = false;

        foreach (var role in this.UserProfilesRequired)
            if (HttpContext.Current.User.IsInRole(role))
            {
                authorized = true;
                break;
            }

        if (!authorized)
        {
            var url = new UrlHelper(context.RequestContext);
            var logonUrl = url.Action("Http", "Error", new { Id = 401, Area = "" });
            context.Result = new RedirectResult(logonUrl);

            return;
        }
    }
}

이것은 Fabricio Martínez Tamayo https://github.com/fabriciomrtnz/FNHMVC/에 의해 수정 된 FNHMVC의 일부입니다.


1
OnAuthorization 방법을 사용하려면 사용자에게 열거 된 모든 역할 이 있어야 합니다. 의도적 이었습니까, 아니면 루프에서 휴식이 누락 되었습니까?
Tieson T.

@ Tieson : 나는 아주 밀접하게 검사했는데, 루프에서 휴식이 필요할 것 같습니다.
OcelotXL

@TiesonT. 그리고 @ madrush, 나는 당신의 수정에 감사합니다, 그것은 실제로 루프 안에서 휴식을 취할 수 있습니다. 위의 코드를 변경하겠습니다.
Bernardo Loureiro

열거 형 UserRoles 가 좋습니다. 수동으로 선언합니까, 아니면 DB의 내용에 따라 자동 생성됩니까?
Konrad Viltersten

@KonradViltersten 수동이지만 리플렉션과 동적 클래스를 통해 자동 생성이 가능하다고 생각합니다
Bernardo Loureiro

3

또 다른 명확한 해결책은 상수를 사용하여 규칙을 유지하고 여러 [Authorize] 특성을 추가 할 수 있습니다. 이것 좀 봐:

public static class RolesConvention
{
    public const string Administrator = "Administrator";
    public const string Guest = "Guest";
}

그런 다음 컨트롤러에서 :

[Authorize(Roles = RolesConvention.Administrator )]
[Authorize(Roles = RolesConvention.Guest)]
[Produces("application/json")]
[Route("api/[controller]")]
public class MyController : Controller

14
여러 Authorize특성은 AND 의미를 사용하며 모든 조건을 충족해야합니다 (예 : 사용자는 관리자 및 게스트 역할 모두에 있어야 함).
trousyt

3

이 두 가지 역할을 자주 적용하면 자신의 권한으로 래핑 할 수 있습니다. 이것은 실제로 허용되는 답변의 확장입니다.

using System.Web.Mvc;

public class AuthorizeAdminOrMember : AuthorizeAttribute
{
    public AuthorizeAdminOrMember()
    {
        Roles = "members, admin";
    }
}

그런 다음 새 권한을 조치에 적용하십시오. 나는 이것이 더 깨끗해 보이고 쉽게 읽힌다 고 생각합니다.

public class MyController : Controller
{
    [AuthorizeAdminOrMember]
    public ActionResult MyAction()
    {
        return null;
    }
}

1

서브 클래스 추가로 더 나은 코드 AuthorizeRole.cs

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
    class AuthorizeRoleAttribute : AuthorizeAttribute
    {
        public AuthorizeRoleAttribute(params Rolenames[] roles)
        {
            this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r)));
        }
        protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary {
                  { "action", "Unauthorized" },
                  { "controller", "Home" },
                  { "area", "" }
                  }
              );
                //base.HandleUnauthorizedRequest(filterContext);
            }
            else
            {
                filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary {
                  { "action", "Login" },
                  { "controller", "Account" },
                  { "area", "" },
                  { "returnUrl", HttpContext.Current.Request.Url }
                  }
              );
            }
        }
    }

이것을 사용하는 방법

[AuthorizeRole(Rolenames.Admin,Rolenames.Member)]

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

1

AspNetCore 2.x를 사용하면 약간 다른 방식으로 진행해야합니다.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AuthorizeRoleAttribute : AuthorizeAttribute
{
    public AuthorizeRoleAttribute(params YourEnum[] roles)
    {
        Policy = string.Join(",", roles.Select(r => r.GetDescription()));
    }
}

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

[Authorize(YourEnum.Role1, YourEnum.Role2)]

-2
Intent promptInstall = new Intent(android.content.Intent.ACTION_VIEW);
promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
promptInstall.setDataAndType(Uri.parse("http://10.0.2.2:8081/MyAPPStore/apk/Teflouki.apk"), "application/vnd.android.package-archive" );

startActivity(promptInstall);

1
코드를 포함한 답변에는 코드의 작동 방식과 질문에 대한 답변을 설명하는 최소한의 설명이 있어야합니다. 또한 코드 섹션 형식을 개선해야합니다.
로베르토 카 보니

응? @Orsit Moel, 잘못된 스레드에 복사하여 붙여 넣은 것 같습니다 ...
Cameron Forward
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.