Chciałbym dodać uprawnienia do kontrolera dla wielu ról jednocześnie.
Zwykle wyglądałoby to tak:
[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}
Ale zapisałem swoje role w stałych, ponieważ w pewnym momencie mogą się zmienić lub rozszerzyć.
public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";
Nie mogę tego zrobić, ponieważ ciąg znaków musi być znany w czasie kompilacji:
[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}
Czy istnieje sposób na obejście problemu?
Mógłbym napisać stałą, która po prostu zawiera „RoleA, RoleB, RoleC” - ale nie lubię magicznych ciągów, a to jest magiczny ciąg. Zmiana nazwy roli i zapomnienie o zmianie połączonego ciągu byłoby katastrofą.
Używam MVC5. Tożsamość ASP.NET i rola są znane w czasie kompilacji.
c#
asp.net-mvc
authorization
Christian Sauer
źródło
źródło
Odpowiedzi:
Spróbuj utworzyć niestandardowy atrybut autoryzacji, taki jak ten .
public class AuthorizeRolesAttribute : AuthorizeAttribute { public AuthorizeRolesAttribute(params string[] roles) : base() { Roles = string.Join(",", roles); } }
Zakładając, że twoje role będą takie same dla wielu kontrolerów, utwórz klasę pomocniczą:
public static class Role { public const string Administrator = "Administrator"; public const string Assistant = "Assistant"; }
Następnie użyj tego w ten sposób:
public class MyController : Controller { [AuthorizeRoles(Role.Administrator, Role.Assistant)] public ActionResult AdminOrAssistant() { return View(); } }
źródło
Upewnij się, że wyprowadzasz niestandardową klasę atrybutów
System.Web.Mvc.AuthorizeAttribute
i NIESystem.Web.Http.AuthorizeAttribute
.Napotkałem ten sam problem. Kiedy to zmieniłem, wszystko działało.
Możesz również dodać następujące elementy do swojej klasy atrybutów niestandardowych:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
źródło
System.Web.Http.AuthorizeAttribute
ZAMIASTSystem.Web.Mvc.AuthorizeAttribute
Najlepszym i najprostszym sposobem rozwiązania tego problemu jest po prostu połączenie ról w atrybucie Autoryzuj.
[Authorize(Roles = CustomRoles.Admin + "," + CustomRoles.OtherRole)]
z CustomRole klasa ze stałymi ciągami, takimi jak ta:
public static class CustomRoles { public const string Admin = "Admin"; // and so on.. }
źródło
To, co zrobiłem, to odpowiedź w @Tieson
Trochę poprawiam jego odpowiedź. Zamiast stringów, dlaczego by nie przekonwertować go na listę?
Oto moja odpowiedź:
public class AuthorizeRolesAttribute : AuthorizeAttribute { private new List<string> Roles; public AuthorizeRolesAttribute(params string[] roles) : base() { Roles = roles.toList() } }
Następnie sprawdź, czy rola jest prawidłowa, zastępując 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); } }
I masz to, teraz sprawdza, czy rola ma uprawnienia dostępu do zasobu
źródło
Wydaje mi się, że niestandardowy atrybut autoryzacji jest przesadą w przypadku tego problemu, chyba że masz dużą liczbę ról.
Ponieważ ciąg musi być znany w czasie kompilacji, dlaczego nie utworzyć statycznej klasy Role, która zawiera publiczne ciągi znaków zdefiniowanych ról, a następnie dodać ciągi oddzielone przecinkami z określonymi rolami, które chcesz autoryzować:
public static class Roles { public const string ADMIN = "Admin"; public const string VIEWER = "Viewer"; public const string ADMIN_OR_VIEWER = ADMIN + "," + VIEWER; }
Następnie możesz użyć atrybutu autoryzacji, tak jak w klasie kontrolera lub metodzie kontrolera (lub obu):
[Authorize(Roles = Roles.ADMIN] public class ExampleController : Controller { [Authorize(Roles = Roles.ADMIN_OR_VIEWER) public ActionResult Create() { ..code here... } }
źródło
ADMIN_OR_VIEWER
rola w akcji jest zbędna, ponieważ nie będziesz mógł dostać się doCreate
metody, jeśli jeszcze jej nie maszADMIN
. W takim przypadkuVIEWER
nigdy nie będzie można wywołaćCreate
metody.