2010-03-29 2 views
6

J'ai une procédure stockée qui fait beaucoup de supprimer. Des centaines de milliers de dossiers. Il ne va pas être exécutable à partir de l'application, mais je suis inquiet qu'un de mes clients l'exécute accidentellement (j'ai eu des problèmes plus tôt en raison de leur "curiosité"): DY a-t-il un "êtes-vous sûr" pour l'exécution de la procédure stockée? :)

Oui. il y a des sauvegardes et des trucs comme ça, mais je pensais ... pas pour les effrayer ... est-il possible de demander à l'utilisateur "êtes-vous sûr?" avant de l'exécuter? :) merci

+10

De cette façon, seuls les utilisateurs autorisés peuvent l'exécuter. –

+0

@The Elite Gentleman: Je ne dis pas que les utilisateurs autorisés peuvent parfois vouloir se sentir comme des êtres humains plutôt que des machines. Ce cas particulier montre plutôt que certains développeurs ne voient pas d'inconvénient à percevoir les utilisateurs comme de simples mortels. :) –

Répondre

7

Je suppose que vous pourriez avoir un paramètre appelé "confirmation" qui nécessite une chaîne spécifique (e, g, "Je sais ce que je fais") à passer, si elle n'est pas définie, ou est mal défini, revenez juste de la procédure sans exécuter le code principal. Pas exactement ce que tu voulais, mais c'est une option.

par exemple - (syntaxe non testé et probablement terribles)

CREATE PROCEDURE dbo.mySproc (
@Confirmation Varchar(100) 
) AS 
BEGIN 
    if(@Confirmation <> 'I know what I am doing') 
    BEGIN 
     return; 
    END 
    DELETE from table_name where condition 
END 
+0

Il pourrait fonctionner, mais je pense qu'il deviendra rapidement un "Copier & Coller & Ignorer le paramètre" –

+4

D'accord, mais il n'y a rien pour les empêcher de contourner quoi que ce soit s'ils ont accès au sproc directement de toute façon. Il vaut mieux ajouter un accès approprié/exécuter la sécurité autour de tout cela. – ZombieSheep

+0

+1 Je suis complètement d'accord, c'est une question de discipline –

6

En bref, non.

La théorie veut que toute personne ayant des autorisations pour trouver et être capable d'exécuter une procédure stockée devrait être autorisée. Il serait préférable de restreindre les permissions afin que ceux qui ont un excès de curiosité n'aient pas les permissions pour l'exécuter.

L'autre, moins sûr, l'option serait d'exiger un secret prédéfini qui doit être passé en paramètre - bien sûr, ils pourraient tout scénario de la procédure stockée loin pour trouver le secret si ...

Bien sûr, l'autre point serait: Si ce n'est pas appelable, pourquoi l'inclure? Après tout, quand vous venez de faire des tâches de type admin, vous pouvez avoir les scripts scriptés comme un fichier que vous pouvez garder en sécurité sur votre propre machine

1

Vous pouvez utiliser une entrée de bit appelée @UserKnowsWhatTheyAreDoing et vérifiez si elle est vrai avant l'exécution. Si c'est faux, imprimez un message amical et retournez gracieusement de la procédure

2

Vous pouvez ajouter un paramètre @reallyReallyReallyDelete au sproc qui servira de mesure de sécurité: s'il est défini sur YesYesYes, la transaction sera validée.

1

La procédure peut nécessiter un argument avec une valeur spécifique, par exemple 'Yes I know what I'm doing'. Ou il peut chercher une ligne et une table spéciale avec une confirmation similaire et un horodatage récent.

3

utiliser une approche à volets à plusieurs niveaux:

1) contrôle exécuter la sécurité, comme:

GRANT EXECUTE ON [dbo].[yourProcedure] TO [userxyz] 

2) utiliser un nom de procédure vraiment descriptive/effrayant, comme

CREATE PROCEDURE Will_Delete_All_Your_Data ... 

3) mettre un grand commentaire accrocheur au début de la procédure stockée

--NOTE, will delete all of your data-- 
--NOTE, will delete all of your data-- 
--NOTE, will delete all of your data-- 
--NOTE, will delete all of your data-- 
--NOTE, will delete all of your data-- 

4) faire passer l'utilisateur dans un code d'accès spécial obscurcie:

CREATE PROCEDURE Will_Delete_All_Your_Data 
(
    @SpecialCode varchar(30) 
) 

IF @SpecialCode!=CHAR(83)+CHAR(112)+CHAR(101)+CHAR(99)+CHAR(105)+CHAR(97)+CHAR(108)+CHAR(67)+CHAR(111)+CHAR(100)+CHAR(101) 
BEGIN 
    RETURN 999 
END 
... 

Pour votre information, le code spécial doit être 'SpecialCode' ou RETOUR 999 est touché.

0

Avez-vous vraiment besoin de les supprimer de la base de données? Si je peux me permettre l'espace supplémentaire je mettrai un drapeau 'Deleted' dans mes tables et une dernière colonne mise à jour. De cette façon, si un enregistrement est accidentellement supprimé au moins, je peux généralement le retrouver et le restaurer assez facilement. Juste une pensée.

1

Voici encore une autre approche, qui selon moi est adaptée au cas particulier où une procédure doit être appelée directement par un utilisateur plutôt que par une application. Je dois dire, il propose moins de problèmes pour l'utilisateur alors que plus (peut-être, de façon disproportionnée) pour le développeur par rapport à la plupart des autres suggestions. Vous décidez si cela vous convient.

De toute façon, c'est parti.

D'abord, vous créez une table spéciale, CriticalCalls, pour enregistrer les appels aux procédures critiques. Le tableau aurait une structure comme celle-ci:

SPID int, 
ProcName sysname, 
CallTime datetime 

Fondamentalement, l'idée est qu'une SP critique doit être appelé deux fois: d'abord, il enregistre son appel et informe l'utilisateur de répéter l'appel dans un certain intervalle de temps une confirmation de leur intention, et avec le second appel, s'il est fait en conséquence, il procède réellement à l'achèvement de sa tâche.

Ainsi, la partie de départ de toute procédure critique aurait cette logique:

IF NOT EXISTS (
    SELECT * 
    FROM CriticalCalls 
    WHERE SPID = @@SPID AND ProcName = @ThisProcName 
    AND GETDATE() - CallTime BETWEEN @LowerCallTimeLimit AND @UpperCallTimeLimit 
    /* the actual test for the time interval might be somewhat different */ 
) BEGIN 
    ... /* upsert CriticalCalls with the current time stamp */ 
    PRINT 'To proceed, please call this procedure again within...'; 
    RETURN; 
END; 

DELETE FROM CriticalCalls WHERE SPID = @@SPID AND ProcName = @ThisProcName; 

... /* proceed with your critical task */ 

En fait, je pense, il serait préférable d'utiliser un SP dédié (du nom CheckCriticalCalls ci-dessous) pour toutes les manipulations avec CriticalCalls, y compris toutes les modifications nécessaires. CheckCriticalCalls recevrait le nom de la procédure à vérifier et renverrait une sorte d'indicateur indiquant si la procédure spécifiée devrait effectuer son opération réelle.

Il peut sembler un peu comme ceci:

EXECUTE @result = CheckCriticalCalls 'ThisProcedureName'; 
IF @result = -1 BEGIN 
    PRINT 'Call me again'; 
    RETURN; 
END; 

... /* go on with the task */ 

L'idée derrière le réglage de la limite inférieure de l'intervalle est simplement d'empêcher l'utilisateur d'appeler une procédure critique deux fois automatiquement, soit en exécutant deux lignes EXECUTE... identiques en un lot. La limite supérieure, bien sûr, est nécessaire pour 1) s'assurer que l'utilisateur confirme son intention très récente d'effectuer l'opération critique; 2) empêcher l'exécution si l'enregistrement existant dans CriticalCalls est réellement laissé là d'une session passée avec le même SPID. Donc, en gros, un intervalle de 1-2 secondes à une demi-minute me semble tout à fait naturel. Vous pourriez choisir des chiffres différents à la place. Pourquoi ne configurez-vous pas d'autorisations pour vos process stockés?