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.

Jeremy Pridemore
fonte
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.

RBarryYoung
fonte
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."

RLF
fonte
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.

Kenneth Fisher
fonte