2017-06-28 4 views
1

J'ai une application Web ASP.NET (C#) qui se connecte à la base de données Informix 12.x. L'application Web utilise une chaîne de connexion à la base de données avec nom d'utilisateur et mot de passe. Les utilisateurs disposent de comptes de connexion pour utiliser l'application Web et peuvent supprimer des enregistrements dans la base de données.Informix - capture de l'ID utilisateur dans le déclencheur de suppression

Les tables de base de données ont "LastModifiedBy" qui contient l'ID utilisateur. Maintenant, j'ai besoin de mettre en œuvre l'audit en utilisant des déclencheurs de base de données. J'ai besoin de capturer quels enregistrements ont été mis à jour ou supprimés et qui l'a fait (c'est-à-dire, utilisateur connecté) et les enregistrer dans une table d'audit.

Pour le déclencheur de suppression, comment puis-je capturer l'ID utilisateur de l'utilisateur connecté et l'enregistrer dans la table d'audit?

+0

Mot-clé USER (une fonction sans argument qui ne prend pas de parenthèses)? 'SUR CHAQUE ROW INSERT DANS AuditInfo VALUES (..., USER, ...)'? Ou, plus probablement, 'ON CHAQUE ROW EXECUTE PROCEDURE audit_proc (...)' où le nom d'utilisateur est utilisé dans la procédure dans le cadre des données insérées dans la table du journal d'audit. –

Répondre

1

L'utilisateur de la base de données (disponible via le mot-clé USER) sera toujours le nom d'utilisateur associé aux informations d'identification de la base de données partagée. Votre question n'est pas très claire, mais dites-vous que l'attribut existant LastModifiedBy contient l'utilisateur nommé ou l'utilisateur de la base de données? Si c'est l'utilisateur nommé, je pense que vous devriez probablement regarder votre code ASP.NET pour voir comment cela est passé dans l'instruction UPDATE. Je ne suis pas un expert sur ASP.NET, mais en supposant qu'une requête de page unique utilise la même connexion de base de données tout au long de son cycle de traitement, vous pouvez gérer une table avec l'ID de session, disponible via DBINFO('sessionid'). l'utilisateur nommé en haut de la demande, et vous l'avez ensuite disponible à tout moment du processus pour être inclus dans votre audit. Mais si les processus du serveur Web utilisent un pool de connexions à la base de données et que toute déclaration pourrait passer à une autre connexion, même cela ne fonctionnera pas. En fin de compte, je ne pense pas que les déclencheurs de base de données soient la bonne solution ici, notamment parce que vous devrez écrire et maintenir un déclencheur pour chaque table de votre application. Si j'étais confronté à ce problème, je serais plus enclin à avoir une fonction d'audit commune au sein de l'application web, où l'utilisateur désigné est toujours disponible.


À la demande de l'OP, un peu plus de détails. L'ID de session est exactement le même concept que vous voyez dans SSMS - juste un nombre unique qui identifie la connexion.

Imaginez que vous avez la table et les procédures suivantes:

CREATE TABLE session_user (
    sessionid INTEGER NOT NULL, 
    username VARCHAR(20), 
    conn_date DATE, 
    PRIMARY KEY (sessionid) 
); 

CREATE PROCEDURE set_user(v_username VARCHAR(20)) 
    UPDATE session_user SET username = v_username, conn_date = TODAY 
     WHERE sessionid = DBINFO('sessionid'); 

    IF DBINFO('sqlca.sqlerrd2') = 0 THEN 
    INSERT INTO session_user VALUES (DBINFO('sessionid'), v_username, TODAY); 
END PROCEDURE; 

CREATE PROCEDURE get_user() 
    DEFINE v_username VARCHAR(20); 
    SELECT username INTO v_username 
     FROM session_user 
     WHERE sessionid = DBINFO('sessionid'); 

    IF v_username IS NULL THEN 
     LET v_username = USER; 
     -- return system user if no record found in session_user table 
    END IF; 
    RETURN v_username; 
END PROCEDURE; 

NB: Aucun de ce code est testé, il est juste de montrer le principe. Je n'ai pas d'instance Informix à tester pour le tester.

Au sommet de la demande, mais vous exécutez votre SQL, vous devez exécuter:

EXECUTE PROCEDURE set_user($the_web_user); 

vos déclencheurs pourraient alors utiliser get_user() partout où vous voulez capturer cette information. Vous obtiendrez l'utilisateur Web réel s'il a été enregistré dans la table session_user, sinon l'utilisateur de la base de données (qui sera l'identifiant de la base de données partagée si le DML déclencheur provient de l'application web ou l'utilisateur connecté physiquement si le trigger est via une session DB-Access). Je ne pense toujours pas que ce soit une solution particulièrement maintenable - chaque table a besoin de son propre déclenchement (s). Une méthode d'audit OO dans l'application Web serait une approche plus DRY, ou jetez un oeil aux capacités d'audit préexistantes d'Informix.Remarque: le champ de date a été inclus dans la table session_user afin que vous exécutiez un nettoyage dessus, car en fonction de la fréquence de création de nouvelles connexions par l'application Web, votre table session_user peut se développer de la même manière.

+0

LastModifiedBy est une colonne de table qui contient l'ID utilisateur de l'utilisateur connecté. Donc je suppose que c'est l'utilisateur nommé dans votre réponse. Selon le type de connexion, il s'agit d'une connexion par requête HTTP. Je vais faire quelques lectures sur l'ID de session. –

+0

Oui, j'essayais de faire la distinction entre la connexion à la base de données et la connexion de l'utilisateur avec cette nomenclature. J'envisagerais une paire de procédures stockées, une pour insérer/mettre à jour votre table de session utilisateur 'EXECUTE PROCEDURE set_user ($ userid)' en haut du cycle de requête, et une autre 'get_user()' qui renvoie la valeur de userid peut être utilisé dans les triggers, par exemple 'VALUES (..., get_user(), ...)'. – RET

+0

J'ai fait quelques lectures sur la session mais je ne comprends toujours pas. Pour être honnête, je ne sais pas grand-chose sur Informix et c'est la première fois que je l'utilise. Je suis plus familier avec SQL Server. Pouvez-vous donner quelques indications sur la façon dont '' '' set_user''' et '' 'get_user''' fonctionneraient? –