Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment dois-je passer un nom de table dans un proc stocké ?

Tout d'abord, vous ne devriez JAMAIS faire des compositions de commandes SQL sur une application cliente comme celle-ci, c'est ce qu'est l'injection SQL. (C'est OK pour un outil d'administration qui n'a pas de privilèges propres, mais pas pour une application à usage partagé).

Deuxièmement, oui, un appel paramétré à une procédure stockée est à la fois plus propre et plus sûr.

Cependant , comme vous devrez utiliser Dynamic SQL pour ce faire, vous ne souhaitez toujours pas inclure la chaîne transmise dans le texte de la requête exécutée. Au lieu de cela, vous souhaitez utiliser la chaîne transmise pour rechercher les noms du réel tables que l'utilisateur devrait être autorisé à interroger de la manière.

Voici un exemple naïf simple :

CREATE PROC spCountAnyTableRows( @PassedTableName as NVarchar(255) ) AS
-- Counts the number of rows from any non-system Table, *SAFELY*
BEGIN
    DECLARE @ActualTableName AS NVarchar(255)

    SELECT @ActualTableName = QUOTENAME( TABLE_NAME )
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_NAME = @PassedTableName

    DECLARE @sql AS NVARCHAR(MAX)
    SELECT @sql = 'SELECT COUNT(*) FROM ' + @ActualTableName + ';'

    EXEC(@SQL)
END

Certains ont assez demandé pourquoi c'est plus sûr. Espérons que les petites tables Bobby puissent rendre cela plus clair :0

Réponses à d'autres questions :

  1. QUOTENAME seul n'est pas garanti d'être sûr. MS nous encourage à l'utiliser, mais ils n'ont pas garanti qu'il ne puisse pas être déjoué par les pirates. Pour votre information, la vraie sécurité est une question de garanties. La recherche de table avec QUOTENAME, c'est une autre histoire, c'est incassable.

  2. QUOTENAME n'est pas strictement nécessaire pour cet exemple, la traduction Lookup sur INFORMATION_SCHEMA seule est normalement suffisante. QUOTENAME est ici car il est de bonne forme en matière de sécurité d'inclure une solution complète et correcte. QUOTENAME ici protège en fait contre un problème potentiel distinct, mais similaire, connu sous le nom d'injection latente .

Je dois noter que vous pouvez faire la même chose avec les noms de colonnes dynamiques et le INFORMATION_SCHEMA.COLUMNS table.

Vous pouvez également contourner le besoin de procédures stockées en utilisant une requête SQL paramétrée à la place (voir ici :https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=réseau-4.8). Mais je pense que les procédures stockées fournissent une installation de sécurité plus gérable et moins sujette aux erreurs pour des cas comme celui-ci.