Pregunta

Digamos que tengo una aplicación MVC de ASP.Net y esta aplicación (UI) hace referencia a una capa lógica empresarial (BLL) y la BLL hace referencia a mi capa de acceso a datos (DAL).

Estoy utilizando un proveedor de roles y membresía personalizados para la autorización.

Estoy tratando de determinar qué capas deben hacer referencia a mi proveedor de Membresía.

En MVC puede realizar verificaciones de autorización de la siguiente manera:

[Authorize(Roles = "SomeRoleName")]
public ActionResult Index()
{
//do something
}

Y en mi BLL es posible que desee verificar si un usuario también está en un rol:

public static bool IsRoleEditor(User user, Role userRole)
  {
   bool retValue = false;

   if (user.Application.AppID == UserRole.Application.AppID)
   {
        if (Roles.IsUserInRole("ModifyRoles"))
        {
           retValue = true;
        }


    return retValue;
   }

Tendría que hacer referencia e instanciar las clases de Membresía en ambas capas si hago esto. ¿Es esta la forma correcta de diseñar una aplicación como esta? Parece mucha redundancia.

Dado que tengo un BLL, ¿evito usar el " [Autorizar (Roles = " SomeRoleName ")] " atributos y en su lugar, llamar a una función BLL desde el código MVC para verificar si el usuario está en un rol? Si hago esto, el MVC todavía necesita una referencia al proveedor de membresía para la autenticación y, de todos modos, aprovechar el inicio de sesión y otros controles ASP, ¿no?

¿Estoy fuera de la base y me dirijo en la dirección equivocada?

¿Fue útil?

Solución

En mi opinión, esto es una debilidad del diseño de Membresía / Rol.

La forma en la que evitaría esto, por ejemplo, para tener una autorización basada en roles en los niveles UI y BLL en una aplicación distribuida de n niveles, sería exponer un servicio en el nivel BLL que expone los bits relevantes (GetRolesForUser etc) y se implementa llamando al RoleProvider en el servidor.

Luego, implemente un RoleProvider personalizado en el cliente que se implementa llamando al servicio expuesto por el BLL.

De esta manera, el nivel de UI y el nivel de BLL comparten el mismo RoleProvider. El nivel de la interfaz de usuario puede usar el conocimiento de las funciones del usuario actual para mejorar la interfaz de usuario (por ejemplo, ocultar / desactivar los controles de la interfaz de usuario correspondientes a características no autorizadas), y el BLL puede garantizar que los usuarios no puedan ejecutar Lógica de negocio para la cual no están autorizados.

Otros consejos

Excelente pregunta, me pregunté lo mismo hoy. Una de las ideas que tuve (pero no estoy seguro de si es la mejor manera de hacerlo) es utilizar una interfaz (por ejemplo, IRoleProvider) que pueda pasar a su BLL para probar su acceso.

public static bool IsRoleEditor(User user, IRoleProvider rp)
{
     return (rp.IsUserInRole(user,"ModifyRoles"));
}

Con esto, aún verificas tu acceso en tu BLL, puedes usar un simulacro en tus pruebas unitarias para verificar tu lógica y solo necesitas crear una clase (o implementar esto en una clase baseController) en tu sitio web de MVC eso implementará IRoleProvider y realizará la comprobación adecuada utilizando la API de autorización de ASP.NET.

Espero que esto ayude.

Obtenga su objeto Usuario para implementar la interfaz IPrincipal y lanzarla alrededor de las capas. Entonces aún puedes usar el atributo incorporado en [Autorizar].

Aunque escrito hace más de 3 años y sobre castle, este artículo puede ayudar. Comienza a meterse en la materia de IPrincipal a mitad de camino.

HTHS
Charles

¿Por qué no pasar los roles a su BLL para que no tenga ninguna dependencia en la membresía? O usa una interfaz como MartinB sugirió.

¿Qué sucede en el futuro cuando su (s) tenedor (es) de estaca (s) decide utilizar una forma de autenticación diferente y ya no trabaja con un objeto Role ?

Ejemplo:

IsRoleEditor(User user, string[] roles)
{
  return roles.Contains("ModifyRoles");
}

¿No te falta el punto de MVC? MVC se divide naturalmente en niveles. Modelo (DAL), controlador (BLL), Vista (Presentación). Si lo desea, pueden incluirse en diferentes proyectos, pero como el controlador tiene toda la lógica empresarial, solo necesita acceder al RoleProvider allí.

Luego, aplique patrones como el repositorio, el patrón, etc. para dividir más si quiere.

Davy

Llamar al controlador de MVC 'UI' está fuera de lugar. La 'C' en MVC es parte de su BLL, incluso si hace referencia a clases que usted llamaría el BLL. Sin embargo, ese no es el punto de su pregunta.

Creo que resolvería este problema haciendo la pregunta, "¿existe un requisito real para una separación del 100% de tu aplicación 'UI' y tu 'BLL'?". Si ambos componentes comparten una dependencia con respecto a los proveedores miembros / roles, entonces déjelo y empiece a trabajar.

En el caso de que desenchufe su BLL y conecte uno nuevo, tal vez pueda vivir con una dependencia compartida de un proveedor .NET. Sabes que probablemente está bien y que tu aplicación podría no desmoronarse.

Creo que la respuesta de Joe anterior tiene mucho sentido, sin embargo ...

Creo que lo que estás haciendo está bien.

La autorización y la autenticación deben residir dentro de una capa de servicios, que quizás se transfiera a sus controladores.

Si el controlador establece el Principal y la Identidad y luego lo usa en el controlador mediante el uso de los atributos MVC, entonces suena como una buena idea.

Sería bueno ocultar su proveedor de membresía de MVC detrás de una interfaz, de esa manera puede intercambiarla por un proveedor de membresía de WinForms (por ejemplo) y podría probar sus controladores por unidad.

El acceso a roles normalmente no debería estar en el BLL. El acceso es una responsabilidad de la interfaz de usuario.

Dicho esto, aproveche la interfaz de IPrinciple como lo han indicado los carteles anteriores. Tienes acceso a IPrinciple en el nivel Thread.

Thread.CurrentPrincipal
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top