with mvc enablewebsecurity java java-ee java-ee-6 multi-tenant

java - mvc - spring security web



Soporte multi tenancy en Java EE 6 (4)

Capa de persistencia

Comience con la capa de persistencia. Desplácese hacia arriba a través de su arquitectura una vez que tenga eso hecho.

El esquema que está proponiendo tendrá una identificación que identifica al inquilino (por ejemplo, TenantId). Cada mesa tendría esta ID. En todas sus consultas, debe asegurarse de que el TenantId coincida con el TenantId del usuario conectado.

La dificultad con esto es que es un proceso muy manual.

Si utiliza Hibernate como proveedor de JPA, existen algunas herramientas que lo ayudarán; a saber, filtros Hibernate .

Estos se utilizan comúnmente para restringir el acceso en esquemas de múltiples inquilinos (ver aquí y aquí para más )

No he usado EclipseLink, pero parece que también tiene un buen soporte para Multi-Tenancy . The DiscriminatorColumn se parece a un concepto muy similar a Hibernate Filters.

Capa de servicio

Supongo que está utilizando JAX-RS y JMS para una capa de servicio. Si es así, también tendrá que pensar en cómo va a pasar al inquilino y autenticar a sus inquilinos. ¿Cómo va a evitar que un inquilino acceda al servicio REST de otro inquilino? Lo mismo para JMS.

Capa de interfaz de usuario

Tendrá que conectar su inicio de sesión en su UI a un Bean (Hibernate o Eclipselink) que establece el TenantId para el filtro / discriminador.

Tengo una aplicación Java EE 6 existente (implementada en Glassfish v 3.1) y quiero admitir varios inquilinos. Las tecnologías / API que estoy usando actualmente en mi aplicación son

  • EJB (incluido el servicio de temporizador EJB)
  • JPA 2.0 (EclipseLink)
  • JSF 2.0
  • JMS
  • JAX-RS
  • Planeo usar CDI también

Por lo que sé, agregar soporte multi-tenancy solo afecta la capa de persistencia. Mi pregunta: ¿Alguien ha hecho esto antes? ¿Cuáles son los pasos para convertir la aplicación? ¿Esto afectará otras capas además de la persistencia?

Habrá un gran número de inquilinos, por lo tanto, todos los datos residirán en el mismo esquema de base de datos.


Cuéntenos sobre el número y el grado de separación y personalización necesarios para diferentes inquilinos.

Si tiene un pequeño número de inquilinos, me gustaría crear un producto personalizable de "etiqueta blanca". Esto le da la oportunidad de crear algunas cosas específicas para un inquilino sin complicar demasiado las cosas. Además, separar las aplicaciones por inquilino lo ayuda en el mantenimiento. Hicimos esto para un producto con un puñado de inquilinos diferentes.

Si tiene muchos inquilinos, esto ya no es práctico. Hicimos una versión genérica del mismo producto. Todo lo que hicimos entonces fue distinguir a los inquilinos por identificación después de iniciar sesión, separando así los datos de los demás. Pero aún así, no había nada que hacer en términos de cambiar la aplicación o una capa interna, la identificación era todo lo que se necesitaba para separar los datos y el flujo de trabajo se separa automáticamente al tener diferentes instancias de beans u otros objetos administrados.


Ir orientado a mensajes

Si elige los mensajes como el enfoque estratégico y refactoriza (si es necesario) la lógica empresarial en torno a JMS, entonces otras opciones siguen siendo viables y de aplicación local.

Con este enfoque, paga un costo fijo específico (refactor) en su sistema existente (inquilino único). A continuación, puede aplicar enfoques de diversos grados de complejidad, que van desde fragmentación simple (asociación basada en identificador de @ Geziefer) a un enfoque completo de esquema de núcleo compartido + esquemas específicos de inquilino ampliado, sin afectar la arquitectura del sistema ni la refactorización adicional.

Además, tendrá control ortogonal sobre los flujos de datos de su sistema a través de la capa de mensajería (aplicando enrutadores, filtros, rutas de procesamiento especiales, etc.)

[editar por solicitud]

No hay nada per se en MT que sugiera explícitamente la orientación del mensaje. Pero como problema general, estamos analizando interfaces de ampliación y flujos de datos enriquecidos . Según un enfoque basado en API, deberá inyectar cuidadosamente el discriminante de inquilino apropiado en todas las interfaces requeridas (por ejemplo, métodos). Un mensaje basado (o alternativamente un enfoque basado en contexto API) permite una interfaz normativa (estable) (por ejemplo, message.send ()) y al mismo permite flujos de datos especializados explícitos. Si no está sobre la mesa cambiar a una red troncal basada en mensajes, se recomienda encarecidamente que considere la posibilidad de inyectar un parámetro uniforme (por ejemplo, "RequestContext") en sus API. Esta única extensión debe cubrir todas sus futuras necesidades de especialización.


Hay varias maneras de hacerlo, dependiendo del nivel de separación que desee alcanzar y de la cantidad de inquilinos concurrentes que desee mantener. En un extremo, puede crear un nuevo esquema para cada inquilino y, por lo tanto, garantizar el aislamiento de datos a nivel de base de datos. Para la mayoría de los propósitos prácticos, generalmente es suficiente tener una partición lógica de sus datos asignando un tenant_id a cada entidad en su modelo de dominio y manteniendo las restricciones de clave externa. Por supuesto, esto significa que probablemente quiera pasar siempre el tenant_id su sesión actual a cada método de consulta / buscador para que pueda restringir el conjunto de datos en función de eso. Deberá asegurarse de que los usuarios no puedan acceder a los datos de otro inquilino ingresando un ID de inquilino (o un ID de entidad) que no les pertenece en la url.