Aquí está mi versión, basada en @CalebHC y respuestas de @Lee Harold.
He seguido el estilo del uso de parámetros con nombre en el atributo y he anulado la propiedad de las clases base Roles
.
@ respuesta de CalebHC utiliza un nuevo Is
propiedad que creo que es innecesario, porque se AuthorizeCore()
anulados (que en la clase base utiliza roles) por lo que tiene sentido usar nuestra propia Roles
también. Al usar nuestro propio Roles
, escribimos Roles = Roles.Admin
en el controlador, que sigue el estilo de otros atributos .Net.
He usado dos constructores a CustomAuthorizeAttribute
para mostrar los nombres de grupos de directorios activos reales que se pasa en la producción En utilizo el constructor parametrizado para evitar cadenas mágicas en la clase:. Nombres de grupo se extraen de web.config durante Application_Start()
y pasó en la creación usando una herramienta DI.
Necesitará un NotAuthorized.cshtml
o similar en su carpeta Views\Shared
o los usuarios no autorizados recibirán una pantalla de error.
Aquí está el código para la clase base AuthorizationAttribute.cs.
controlador:
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;
}
}
Interesante. ¿Cómo fue capaz de hacer que esto funcione incluso con un solo rol en una enumeración? ¿MyEnum.Admin devuelve una cadena? Estoy tratando de hacer lo mismo que tú, y me he encontrado con un par de problemas: - No puedo configurar una enumeración de tipo de cadena. - No puedo llamar a ToString() en la enumeración, p. [Autorizar (Roles = MyEnum.Admin.ToString())] Ambos ejemplos anteriores me dan errores de compilación. Si puede aconsejar cómo hizo que esto funcione, eso sería apreciado. Gracias. –
@JohnnyO - Tengo el mismo problema, ¿lograron descubrir lo que estamos haciendo mal? @codette - ¿podría darnos un consejo aquí? – UpTheCreek
Lo siento pero nunca fui con ninguna de estas soluciones. Así que cambié mi código para que solo se verifique una función. Cuanto mayor sea su función, más podrán hacer. Por ejemplo, un usuario "normal" puede hacer algunas cosas. Un "moderador" puede hacer todo lo que un usuario "normal" puede hacer y más. Un "administrador" puede hacer todo lo que un usuario "normal" y "moderador" pueden y más. – codette