A veces, puede interesarnos limitar la cantidad de usuarios que se conectan a una Base de Datos usando nuestra aplicación. Por ejemplo, si le vendimos 5 licencias a un cliente queremos que solamente puedan conectarse desde 5 computadoras.

Fíjate que no le podemos limitar las conexiones a la Base de Datos a nuestro cliente, porque los datos son suyos, no nuestros. O sea que si él quiere conectarse usando ISQL.EXE, EMS SQL Manager, IBExpert, Flame Robin, o cualquier otro programa puede hacerlo, no se lo podemos impedir a no ser que él haya firmado un contrato donde está claramente establecido que tiene prohibido hacerlo.

En otras palabras, no le podemos impedir que se conecte, 10, 20, ó 590 veces concurrentemente desde afuera de nuestra aplicación.

Pero lo que sí podemos hacer es limitar la cantidad de usuarios que se conectan usando nuestra aplicación. Por ejemplo, podemos impedirle que se conecten más de 5 usuarios usando nuestro sistema de Contabilidad.

Para conseguir nuestro objetivo usaremos excepciones y triggers de la Base de Datos.

Ejemplo:

Tenemos una aplicación cuyo ejecutable se llama MIAPLICACION.EXE y queremos limitar a un máximo de 5 conexiones simultáneas.

CREATE EXCEPTION E_ACCESO_NO_PERMITIDO 'La cantidad de licencias ya alcanzó el límite';

Método 1

CREATE TRIGGER DB_TRIGGER_CONNECT_1
   ACTIVE ON CONNECT
   POSITION 0
AS
   DECLARE VARIABLE lnCantidadConexiones SMALLINT;
BEGIN

   lnCantidadConexiones = (SELECT
                              COUNT(*)
                           FROM
                              MON$ATTACHMENTS
                           WHERE
                              MON$REMOTE_PROCESS LIKE '%MIAPLICACION.EXE%');

   IF (lnCantidadConexiones > 5) THEN
      EXCEPTION E_ACCESO_NO_PERMITIDO;

END;

Esto funcionará perfectamente … siempre y cuando alguien no le cambie el nombre al archivo .EXE porque la verificación se hace tomando en cuenta el nombre del archivo .EXE

Método 2

En este caso creamos una tabla llamada CONEXIONES y cada vez que alguien se conecta a la Base de Datos usando nuestro programa le agregamos una fila a esa tabla  y cuando se desconecta le borramos esa fila. La tabla CONEXIONES tiene esta estructura:

CONEXION1

Captura 1. Si haces clic en la imagen la verás más grande

donde como puedes ver tres columnas tienen valores por defecto, eso significa que si no se especifican en el INSERT los valores de los campos CON_FECHOR,  CON_USUARI y CON_CONEXI el Firebird automáticamente colocará en esas columnas la fecha y hora actuales, el nombre del usuario, y la conexión, respectivamente. Desde luego que puedes agregarle más columnas a esta tabla si lo deseas.

En nuestra Base de Datos creamos un trigger de Base de Datos, como éste:

CREATE TRIGGER DB_TRIGGER_CONNECT_2
   ACTIVE ON CONNECT
   POSITION 1
AS
   DECLARE VARIABLE lnCantidadConexiones SMALLINT;
BEGIN

   lnCantidadConexiones = (SELECT COUNT(*) FROM CONEXIONES);

   IF (lnCantidadConexiones > 4) THEN
      EXCEPTION E_ACCESO_NO_PERMITIDO;

END

donde lo que hacemos es verificar que la cantidad de conexiones no sobrepase el límite que habíamos determinado. ¿Pero por qué ponemos 4 y no 5? Porque la inserción en la tabla CONEXIONES se hace después de haberse conectado a la Base de Datos y por lo tanto en la variable lnCantidadConexiones no se está contando la conexión actual, por ese motivo hay que colocar el número anterior al del límite. Si la cantidad de conexiones supera a 5 entonces se lanzará una excepción y se desconectará automáticamente de la Base de Datos.

Y cuando alguien ejecuta nuestro programa lo primero que hacemos es insertarle una fila a la tabla CONEXIONES, de esta manera:

INSERT INTO CONEXIONES
   (CON_IPXXXX)
   SELECT
      MON$REMOTE_ADDRESS
   FROM
      MON$ATTACHMENTS
   WHERE
      MON$ATTACHMENT_ID = CURRENT_CONNECTION

Y cuando alguien sale de nuestra aplicación eliminamos una fila de la tabla CONEXIONES, así:

DELETE FROM
   CONEXIONES
WHERE
   CON_CONEXI = CURRENT_CONNECTION
END

Entonces, lo que sucede es lo siguiente:

  • Usando nuestra aplicación se conectan a la Base de Datos
  • Verificamos si se sobrepasó el límite de conexiones permitidas. Si así fue, se desconecta de la Base de Datos
  • Desde nuestra aplicación le insertamos una fila a la tabla CONEXIONES
  • Cuando salen de nuestra aplicación borramos una fila de la tabla CONEXIONES

De esta manera conseguimos el objetivo que nos habíamos propuesto: que jamás usen nuestra aplicación más de 5 computadoras a la vez.

Sin embargo este método tiene un pequeño problema: si ocurre un corte de la energía eléctrica varias computadoras podrían haberse desconectado de la Base de Datos pero en la tabla CONEXIONES continuarán sus datos, como si estuvieran conectadas.

En el peor de los casos podríamos tener 5 computadoras desconectadas pero la tabla CONEXIONES nos dirá que las 5 están conectadas.

Para solucionar el problema podemos usar el método 3.

Método 3

En nuestro programa, antes de insertar la fila en la tabla CONEXIONES, borramos todas las filas de la tabla CONEXIONES cuyos datos no se encuentren en la tabla MON$ATTACHMENT.

De esa manera en la tabla CONEXIONES siempre tendremos conexiones actuales y nunca tendremos conexiones «fantasmas».

¿Por qué?

Porque en la tabla MON$ATTACHMENT siempre tenemos los datos de todas las conexiones actuales. Si en la tabla CONEXIONES tenemos una conexión que no existe en la tabla MON$ATTACHMENT entonces está mal y debemos borrarla.

DELETE FROM
   CONEXIONES
WHERE
   CON_CONEXI NOT IN (SELECT MON$ATTACHMENT_ID FROM MON$ATTACHMENTS)

Entonces, lo que sucedería es lo siguiente:

  • Usando nuestra aplicación se conectan a la Base de Datos
  • Verificamos si se sobrepasó el límite de conexiones permitidas. Si así fue, se desconecta de la Base de Datos
  • Desde nuestra aplicación borramos todas las filas de la tabla CONEXIONES que no se encuentren también en la tabla MON$ATTACHMENTS
  • Desde nuestra aplicación le insertamos una fila a la tabla CONEXIONES
  • Cuando salen de nuestra aplicación borramos una fila de la tabla CONEXIONES

Conclusión:

Si limitamos la cantidad de conexiones a la Base de Datos entonces tenemos una protección contra la piratería pues aunque consigan copiar nuestra aplicación en otra computadora no podrán realizar la conexión y de nada les servirá. Además, tenemos la posibilidad de instalar nuestra aplicación en muchas computadoras para que la revisen y la evalúen pero nos aseguramos que no la usen más usuarios de los que determinemos nosotros.

Artículos relacionados:

Los triggers de la Base de Datos

El índice del blog Firebird21