2009-09-10 17 views
10

Digamos que tengo una aplicación ASP.Net MVC 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).Membresía .NET en la aplicación nTier

Estoy utilizando un proveedor personalizado de Membresía y Roles para la Autorización.

Estoy tratando de determinar qué capas necesitan hacer referencia a mi proveedor de membresía.

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

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

Y en mi BLL que puede que desee comprobar para ver si un usuario está en un papel así:

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 y crear instancias de 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.

Como tengo un BLL, evito usar los atributos "[Authorize (Roles =" SomeRoleName ")]" y, en su lugar, invoco una función BLL dentro del código MVC para verificar si el usuario tiene un rol? Si hago esto, el MVC aún 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, ¿verdad?

¿Estoy lejos de la base y voy en la dirección incorrecta?

Respuesta

4

En mi opinión, esto es una debilidad del diseño de afiliación/papel.

La forma en que lo solucionaría, por ejemplo, para tener autorización basada en roles en 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 UI y el nivel BLL comparten el mismo RoleProvider. El nivel UI puede usar el conocimiento de las funciones actuales del usuario para mejorar la UI (por ejemplo, ocultar/deshabilitar los controles UI correspondientes a funciones no autorizadas) y BLL puede garantizar que los usuarios no puedan ejecutar la lógica comercial para la que no están autorizados.

0

Obtenga su objeto Usuario para implementar la interfaz IPrincipal y lance alrededor de las capas. Entonces todavía puede usar el atributo incorporado [Autorizar].

Athough escrito hace más de 3 años y sobre castle, this article puede ayudar. Comienza a introducirse en el IPrincipal a mitad de camino.

HTHS
Charles

+0

Definitivamente use el atributo Autorizar en MVC. No es necesario que compruebe manualmente IsInRoles. –

+0

El problema es que necesito procesar lógica de negocios adicional además de "IsInRole" o "Authorize", que pensé que debería estar siempre en el BLL. Podría pasar el objeto de usuario a todas partes, pero ¿por qué no dejar de lado el Autorizar y usar solo el BLL? – Jay

1

excelente pregunta, me hice la misma cosa hoy. Una de las ideas que tenía (pero no estoy seguro de si es la mejor manera de hacerlo) es usar 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, usted todavía verificar su acceso en su BLL, puede utilizar una maqueta en las pruebas unitarias para comprobar su lógica y sólo tiene que crear una clase (o implementen esto de una clase BaseController) en su sitio web de MVC que implementará IRoleProvider y realizará la comprobación adecuada con la API de autorización de ASP.NET.

Espero que esto ayude.

-1

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

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

Thread.CurrentPrincipal 
+0

Charles, thx por la respuesta. Como puede ver, debo procesar cierta lógica de negocios, aparte de la verificación de roles básicos, para determinar con el fin de determinar la verdadera seguridad de los usuarios. Pensé que todo BL debería estar en el BLL y por eso estaba planeando encapsular la seguridad allí también. ¿Está diciendo que es preferible que el "IsRoleEditor" anterior resida en mi capa de interfaz de usuario y no en un BLL? – Jay

+1

-1 Estoy en desacuerdo: la autorización (ya sea de acceso de roles o algún otro mecanismo) es definitivamente una responsabilidad de BLL. El nivel UI puede estar ejecutándose en el cliente (por ejemplo, Winforms), por lo que puede verse comprometido. – Joe

+0

Realmente todo depende de cómo esté diseñando esta aplicación. Danos un ejemplo de tu solución, algo simple, solo nombres de proyectos y cómo se referencian entre sí. – dmportella

0

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

¿Qué sucederá en el futuro cuando su (s) interesado (s) decida ir con una forma diferente de autenticación y ya no trabaje con un objeto Rol?

Ejemplo:

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

¿No te estás perdiendo el sentido de MVC? MVC se divide naturalmente en niveles. Modelo (DAL), controlador (BLL), vista (presentación). Estos pueden ir en diferentes proyectos si lo desea, pero como el controlador tiene toda la lógica comercial, solo necesita acceder al RoleProvider allí.

A continuación, aplique patrones como el repositorio, el patrón, etc. para dividirlos más si lo desea.

Davy

+0

Entiendo el concepto de MVC pero luego, si configuro el BLL para que contenga la validación de Role, ¿por qué la función "[Autorizar (Roles =" SomeRoleName ")]" dentro de la UI? – Jay

+0

@jay el atributo Autorizar se utiliza en el controlador, según Davy dijo que sería la capa empresarial. Creo que lo que él está manejando es que parece estar ignorando el hecho de que las "capas" ya han sido divididas por el patrón MVC. Creo que todo depende de cómo estés reestructurando esta solución Jay, ¿podrías hacer un diagrama para mostrarnos cómo estás diseñando esto? – dmportella

+0

Un diagrama ayudaría. ¿Te refieres a la capacidad de UI como en la vista? Si lo hace, creo que es bueno tener un HTML estúpido, pero puede ver dónde desea mostrar algo en función de roles como una "casilla de verificación autorizada" que solo los supervisores pueden ver en una vista compartida de otra manera. Así que poder acceder a los roles aquí es útil en mi opinión. – Davy

0

Para llamar el controlador MVC 'IU' está muy lejos de la marca .. La 'C' en MVC es parte de su BLL, incluso si se hace referencia a las clases que se llamarían la BLL. Sin embargo, ese no es el punto de tu pregunta.

Creo que resolvería este problema haciendo la pregunta, "¿existe un requisito real de separación del 100% de su aplicación 'UI' y su 'BLL'?". Si ambos componentes comparten una dependencia en los proveedores miembro/rol, entonces déjalo así y ponte a trabajar.

En el caso en que desenchufe su BLL y conecte uno nuevo, quizás tener una dependencia compartida de un proveedor de .NET es algo con lo que puede vivir. Sabes que probablemente esté bien y que tu aplicación simplemente no se rompa.

creo que la respuesta de Joe anterior tiene mucho sentido, aunque ...

+1

No estoy seguro de que el controlador sea parte de su BLL, de hecho, creo que no debe contener ninguna lógica comercial, solo una orquestación entre los objetos de su dominio. –

+0

WTF es la lógica de negocios de todos modos? Toda la aplicación es lógica de negocios, compuesta por varios componentes de lógica de negocios ... la parte de la interfaz de usuario de la lógica, la parte MVC de la lógica ... tener el código correctamente diseñado y abstraído es el objetivo, no aplicar nombres genéricos para componentes complejos . La idea de estas capas lineales hacia arriba y hacia abajo es estúpida. Un diagrama de solución es un mapa complejo de objetos, y tratar con el cruce es nuestro trabajo. El problema de Jay es bueno, lidiar con el cruce en dependencias será una tarea divertida. Sigo pensando que la respuesta de Joe tuvo más sentido y ahora Solo estoy despotricando. – misteraidan

0

creo que lo que está haciendo está bien.

La autorización y la autenticación deben vivir dentro de una capa de servicios, que tal vez se transmita 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 de MVC, entonces parece una buena idea.

Sería bueno esconder su proveedor de Membresía MVC detrás de una interfaz, de esa manera usted puede cambiarlo por un proveedor de Membresía WinForms (por ejemplo) y podría probar sus controladores en una unidad.

Cuestiones relacionadas