Como conhecer o usuário executando uma ação de exclusão em uma tabela de auditoria, ao usar um login compartilhado?


8

Informações básicas:

  • Estou criando uma coleção de tabelas de auditoria para acompanhar as atualizações e exclusões em um conjunto de tabelas de dados para o meu aplicativo.
  • Os registros de auditoria são criados por meio de gatilhos.
  • O DML no banco de dados do meu aplicativo geralmente vem de um logon que um serviço usa para entrar no banco de dados. Por isso, acho que o resultado de SYSTEM_USERsempre será o mesmo quando chamado em um gatilho.
  • Meu aplicativo não armazena dados do usuário atualmente, embora uma string UserIdseja fornecida toda vez que o DML for executado (feito exclusivamente em procedimentos armazenados).

O problema que encontrei é que, quando um usuário exclui um registro, quero saber quem o fez. Como será feito pelo mesmo login, não quero ver que todas as ações foram executadas pelo serviço, quero ver qual usuário fez. Esse não é um problema em uma atualização, porque temos ModifiedBycolunas que serão atualizadas por meio de atualizações enviadas UserId.

A pergunta é: existe uma maneira de definir SYSTEM_USERou colocar as informações do usuário no gatilho quando uma exclusão é executada?

A "melhor" ideia que tenho agora, embora ainda não tenha certeza se é uma boa ideia, é que, no serviço, verifico se a corrente UserIdestá no banco de dados como usuário e, se não, crie um usuário objeto para eles. Em seguida, execute os procedimentos armazenados com EXECUTE AS User = @UserId. Então, quando o DML for concluído no procedimento armazenado e o gatilho for disparado, SYSTEM_USERo usuário deverá retornar o EXECUTE AS.


2
@RBarryYoung E esse mecanismo é o assunto da pergunta. Meu serviço está entrando no meu banco de dados executando ações para quem o chamou e eu tenho o UserId disponível. Eu preciso descobrir como gravar esse UserId no caso de uma exclusão.
— Jeremy Pridemore

Justo, eu deveria ter lido sua pergunta mais detalhadamente. Acho que tenho uma resposta para isso, mas talvez não seja possível postá-la até tarde da noite.
— usar o seguinte código

Respostas:


4

Embora o uso EXECUTE AS User = @UserIdseja a melhor opção (dependendo de outros problemas), eis uma abordagem alternativa:

Nos procedimentos armazenados, ou a qualquer momento na sua sessão SQL, você deve DELETEexecutar o seguinte comando:

SET CONTEXT_INFO @UserId

Em seu gatilho, você pode recuperar esse valor com

SELECT @var = CAST(CAST(CONTEXT_INFO() As Varbinary(4)) As Int)

Isso tem algumas desvantagens, a mais importante delas é que você não pode usar prontamente CONTEXT_INFO para mais de uma coisa por vez.


Decidimos não ter as informações por enquanto. Se decidirmos que devemos tê-lo, tentarei este primeiro. Obrigado pela ideia.
— Jeremy Pridemore

2

Dependendo de como você altera o contexto do usuário do logon individual para o logon do serviço, você pode achar que ORIGINAL_LOGIN () é útil.

http://technet.microsoft.com/en-us/library/ms189492.aspx

"Esta função pode ser útil na auditoria da identidade do contexto de conexão original. Enquanto funções como SESSION_USER e CURRENT_USER retornam o contexto de execução atual, ORIGINAL_LOGIN retorna a identidade do logon que primeiro foi conectado à instância do SQL Server nessa sessão."


Essa é uma função interessante, obrigado por mencioná-la. Tenho certeza de que, quando tenho um serviço executando e acessando o banco de dados com o mesmo login do servidor todas as vezes, ORIGINAL_LOGIN () sempre retornará o usuário que o serviço está usando. Isso soa correto para você?
— Jeremy Pridemore

Sim, se você estiver passando pela conta de serviço para fazer a conexão com o banco de dados, o ORIGINAL_LOGIN () seria o serviço. Se você alterar o contexto depois de se conectar ao banco de dados como você mesmo, o ORIGINAL_LOGIN () deverá ser seu login.
— RLF 19/09/2013

0

Você também pode tentar adicionar Host_Nameàs suas tabelas. Constatei que em situações em que tenho um login compartilhado, geralmente consigo rastrear uma pessoa pelo nome de sua máquina, já que 95% do tempo em que uma pessoa está trabalhando em sua própria máquina. Nem sempre funciona, mas pode ser uma informação secundária útil.

SELECT host_name FROM sys.dm_exec_sessions WHERE session_id = @@SPID

Infelizmente, isso não funcionará se você estiver trabalhando com um aplicativo Web no qual o host sempre será o próprio aplicativo Web, mas pode valer a pena tentar.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.