6

Actualmente estoy escribiendo un sitio Admin MVC 3, y cada usuario solo tiene acceso a ciertas partes del sitio.asp.net MVC 3 aplicando AuthorizeAttribute a las áreas

Las áreas de mi sitio son las mismas que las Roles de usuario, entonces lo que me gustaría hacer es colocar el atributo Autorizar en cada área, usando el nombre del área como el parámetro en el Rol.

Hasta ahora lo he hecho funcionar cuando estoy codificando la verificación de cada área, pero me gustaría recorrer todas las áreas y aplicar el filtro Autorizar. (estoy usando esto como mi costumbre FilterProvider - http://www.dotnetcurry.com/ShowArticle.aspx?ID=578)

Mi código hasta el momento ("Gcm" es una de mis áreas, y es también un rol):

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new HandleErrorAttribute()); 
    // for all controllers, run AdminAuthorizeAttribute to make sure they're at least logged in 
    filters.Add(ObjectFactory.GetInstance<AdminAuthorizeAttribute>()); 

    AdminAuthorizeAttribute gcmAuthroizeAttribute = ObjectFactory.GetInstance<AdminAuthorizeAttribute>(); 
    gcmAuthroizeAttribute.Roles = "Gcm"; 

    var provider = new FilterProvider(); 
    provider.Add(
     x => 
     x.RouteData.DataTokens["area"] != null && x.RouteData.DataTokens["area"].ToString() == "Gcm" 
      ? gcmAuthroizeAttribute 
      : null); 
    FilterProviders.Providers.Add(provider); 
} 

¿alguien sabe cómo para obtener todas las áreas de mi aplicación, así que puedo recorrerlas, en lugar de codificar cada área?

O si alguien tiene una mejor idea de cómo Autorizar por área, se lo agradecería.

Gracias por su ayuda Saan

Respuesta

-1

Cuando estaba investigando un tema aparte, me encontré con How to pass parameters to a custom ActionFilter in ASP.NET MVC 2?

ese atributo ejemplo, se puede alterar para comprobar si el área actual del controlador.

public class CustomAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     RouteData routeData = filterContext.RouteData; 

     // check if user is allowed on this page 
     if (SessionFactory.GetSession().Contains(SessionKey.User)) 
     { 
      User user = (User)SessionFactory.GetSession().Get(SessionKey.User); 
      string thisArea = routeData.DataTokens["area"].ToString(); 

      // if the user doesn't have access to this area 
      if (!user.IsInRole(thisArea)) 
      { 
       HandleUnauthorizedRequest(filterContext); 
      } 
     } 

     // do normal OnAuthorization checks too 
     base.OnAuthorization(filterContext); 
    } 
} 

luego aplico mi atributo autorizar a medida para todos los controladores de este tipo en Global.asax:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new HandleErrorAttribute()); 
    // for all controllers, run CustomAuthorizeAttribute to make sure they're at logged in and have access to area 
    filters.Add(ObjectFactory.GetInstance<CustomAuthorizeAttribute>()); 
} 

Gracias por todos los que respondieron

Saan

+1

** Advertencia: esta no es una práctica segura. ** He estado mirando esta misma área, y encontré que esta no es una práctica recomendable. Las áreas son un concepto de enrutamiento, pero los controladores se pueden encontrar y recoger ** incluso si el área no está especificada **. [Levi lo explica aquí] (http://stackoverflow.com/questions/2319157/how-can-we-set-authorization-for-a-whole-area-in-asp-net-mvc/2320419#2320419) – Quango

0

He aquí un ejemplo de un atributo override Autorizar he creado. Necesitaba mi función autorizar para admitir tipos de nave miembro, por lo que es posible que no desee adentrarse demasiado en el funcionamiento interno de las funciones, pero AuthorizeCore es donde se desarrolla la lógica principal. En mi caso, lo estoy comprobando contra un contexto de datos de la entidad.

Uso:

[AjaxAuthorize(AjaxRole = "Administrators")] 
public JsonResult SaveAdministrativeUser(v....) 

Código:

public class AjaxAuthorizeAttribute : AuthorizeAttribute 
    { 
     private class HttpAuthorizeFailedResult : ActionResult 
     { 
      public override void ExecuteResult(ControllerContext context) 
      {     
       // Set the response code to 403. Membership.Provider.Name == "UnitArchiveMembershipProvider" 
       context.HttpContext.Response.StatusCode = context.HttpContext. User.Identity is WindowsIdentity ? 401 : 403; 
      } 
     } 

     public string AjaxRole { get; set;} 

     public AjaxAuthorizeAttribute() 
     { 
      AjaxRole = "Users"; 
     } 

     protected override bool AuthorizeCore(HttpContextBase httpContext) 
     { 
      if (string.IsNullOrEmpty(MvcApplication.Config.DBSettings.Database)) 
      { 
       return true; 
      } 

      //When authorize parameter is set to false, not authorization should be performed. 
      UnitArchiveData db = DataContextFactory.GetWebRequestScopedDataContext<UnitArchiveData>(MvcApplication.Config.DBSettings.GetConnectionString());    


      if (httpContext.User.Identity.IsAuthenticated) 
      { 
       login_data user = db.login_datas.Where(n => n.EmailAddress == httpContext.User.Identity.Name).FirstOrDefault(); 
       if (user != null) 
       { 
        return user.cd_login_role.RoleName == "Administrators" || user.cd_login_role.RoleName == AjaxRole; 
       } 
      } 

      return false; 

     } 

     protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
     { 
      if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest()) 
      { 
       //Ajax request doesn't return to login page, it just returns 403 error. 
       filterContext.Result = new HttpAuthorizeFailedResult(); 
      } 
      else 
       base.HandleUnauthorizedRequest(filterContext); 
     } 
    } 
+0

Hola Sergei. Gracias por la respuesta, pero ya creé mi atributo Autorizar personalizado y funciona bien. Solo necesito poder pasar los Roles apropiados en cada una de las áreas. No quiero tener que poner el atributo en cada controlador. Estoy buscando algo que pueda configurarse automáticamente cada vez que alguien agregue una nueva área. – Saan

+0

Sí, mire cómo lo estoy haciendo. La variable AjaxRole se pasa al CustomizeAttribte personalizado. Automáticamente puede ser difícil, pero agregar un [AjaxAuthorize (AjaxRole = "Administrators")] al encabezado de la función no es tan difícil y resuelve su problema. –

+0

Pero significa que cualquiera que agregue código al proyecto (y algunos serán desarrolladores terceros) deberá asegurarse de que se agrega el atributo Autorizar correcto al Controlador. Lo que estoy buscando es una forma de asegurarme de que se use la autorización correcta sin importar qué. – Saan

2

Usted podría hacer un controlador de base para cada área, y poner el atributo autorizar más de la clase base. De esa forma puede pasar el parámetro de área para el controlador base de cada área.

Cuestiones relacionadas