Funcionalidade de Timeout com DataServer SQL – parte II

Escrito por Marcos Kirchner em 8 de junho de 2009, 08:16h

No post anterior desta série verificamos como implementar um sistema de timeout simples, que desconecta a sessão do usuário depois de um tempo de inatividade, quando se utiliza o DataServer SQL Server. No entanto, os usuários ainda conseguiam abrir várias sessões simultâneas de cada produto. O objetivo deste post é mostrar como é possível restringir o acesso dos usuários para apenas uma sessão por produto.

Neste nosso exemplo faremos toda a implementação no banco de dados, evitando qualquer alteração no produto e ambiente. O princípio que deveremos seguir é simples: sempre que uma conexão ao banco de dados for aberta, verificar se já existe alguma conexão para o mesmo produto e mesmo usuário, porém de outra sessão. Note que é necessário validar se a conexão existente é de outra sessão, pois o DataServer SQL usa várias conexões para cada banco de dados.

Para executar um código sempre que uma nova conexão é criada, podemos utilizar uma trigger de LOGON. Esta funcionalidade está disponível no SQL Server 2005 com Service Pack 2 e superiores e no SQL Server 2008. Estas triggers são executadas após a autenticação do usuário, em um contexto de transação. Se esta transação for abortada (rollback), o usuário recebe um erro e a conexão não é estabelecida.

A trigger de exemplo abaixo leva em conta que:

  • é utilizada autenticação integrada do Windows para autenticar no SQL Server;
  • cada produto informa um nome de aplicação diferente para o banco de dados no momento da conexão (ex: Datasul EMS 2, Datasul EMS 5, Datasul HCM, etc);
  • é utilizada a arquitetura de DataServer local.

 

ATENÇÃO: este código é uma ilustração dos conceitos abordados neste Post. Não há suporte para este código. Só utilize este código se entender exatamente o que ele faz e estiver satisfeito com o resultado.

CREATE TRIGGER TR_DatasulSingleUser
ON ALL SERVER
WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
    DECLARE @Event XML;
    SET @Event = EVENTDATA();

    IF EXISTS
        (SELECT *
        FROM sys.dm_exec_sessions s1 INNER JOIN sys.dm_exec_sessions s2
            ON s1.program_name = s2.program_name AND
            s1.original_login_name = s2.original_login_name AND
            (s1.host_name <> s2.host_name OR
            s1.host_process_id <> s2.host_process_id)
        WHERE s1.is_user_process = 1
            AND s2.is_user_process = 1
            AND s1.client_interface_name = 'ODBC'
            AND s2.client_interface_name = 'ODBC'
            AND s1.program_name LIKE 'Datasul%'
            AND s1.session_id = @Event.value('(/EVENT_INSTANCE/SPID)[1]', 'INT')
            AND s1.original_login_name = @Event.value('(/EVENT_INSTANCE/LoginName)[1]', 'SYSNAME'))
    BEGIN
        ROLLBACK;
    END;
END;

 

A função EVENTDATA() retorna um fragmento XML com as informações sobre o evento. Para um evento de LOGON, o fragmento tem este formato:

<EVENT_INSTANCE>
  <EventType>LOGON</EventType>
  <PostTime>2009-06-05T14:29:01.227</PostTime>
  <SPID>54</SPID>
  <ServerName>SERVER\instance</ServerName>
  <LoginName>DOMAIN\login</LoginName>
  <LoginType>Windows (NT) Login</LoginType>
  <SID>SID</SID>
  <ClientHost>10.20.30.40</ClientHost>
  <IsPooled>0</IsPooled>
</EVENT_INSTANCE>

Como o SQL Server tem suporte nativo para trabalhar com dados XML, podemos extrair as informações do fragmento facilmente e utilizá-las para validar se existem outras sessões para o mesmo usuário. Se for detectada outra sessão, abortamos a transação do usuário (ROLLBACK). Quando a transação de LOGON é abortada, a conexão não é estabelecida e o usuário recebe um erro.

Apesar desta implementação conseguir restringir o número de sessões por usuário, a mensagem de erro apresentada ao usuário é confusa e não deixa claro qual problema realmente ocorreu. No próximo post desta série verificaremos como realizar uma implementação semelhante com código 4GL / ABL, que permite apresentar mensagens de erro mais amigáveis para o usuário.

Categorias: Banco de dados | DataServer | SQL Server

Tags:

Comentar




biuquote
  • Comentário
  • Pré-visualização
Loading