Ecco la mia versione, basata su @CalebHC e risposte di @Lee Harold.
Ho seguito lo stile di utilizzo dei parametri con nome nell'attributo e ho sovrascritto le proprietà di base Roles
.
@ risposta di CalebHC utilizza una nuova Is
proprietà che credo sia inutile, perché AuthorizeCore()
viene sostituita (che nella classe di base utilizza i ruoli) quindi ha senso usare la nostra Roles
pure. Usando il nostro Roles
si arriva a scrivere Roles = Roles.Admin
sul controller, che segue lo stile di altri attributi .Net.
Ho usato due costruttori per CustomAuthorizeAttribute
per mostrare i nomi dei gruppi directory reale attivi vengono passati Nella produzione io uso il costruttore parametrizzato per evitare le stringhe di magia nella classe:. I nomi dei gruppi sono tirati da web.config durante Application_Start()
e superato in sulla creazione utilizzando uno strumento DI.
Avrete bisogno di un NotAuthorized.cshtml
o simile nella vostra cartella Views\Shared
o gli utenti non autorizzati visualizzeranno una schermata di errore.
Questo è il codice per la classe base AuthorizationAttribute.cs.
Controller:
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;
}
}
Interessante. Come sei riuscito a far funzionare tutto questo anche con un solo ruolo in un enum? MyEnum.Admin restituisce una stringa? Sto cercando di fare la stessa cosa di te, e ho riscontrato un paio di problemi: - Non riesco a impostare un enum di tipo stringa. - Non riesco a chiamare ToString() sull'enumerazione, ad es. [Authorize (Roles = MyEnum.Admin.ToString())] Entrambi gli esempi precedenti mi danno errori del compilatore. Se puoi consigliare come funziona, sarebbe apprezzato. Grazie. –
@JohnnyO - Ho lo stesso problema, sei riuscito a scoprire cosa stiamo facendo male? @codette - potresti darci un consiglio qui? – UpTheCreek
Mi dispiace ma non sono mai andato con nessuna di queste soluzioni. Così ho cambiato il mio codice in modo che solo un ruolo debba essere controllato. Più è alto il loro ruolo e più possono fare. Ad esempio, un utente "normale" può fare alcune cose. Un "moderatore" può fare tutto ciò che un utente "normale" può e di più. Un "admin" può fare tutto ciò che un utente "normale" e "moderatore" possono e di più. – codette