Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come devo passare il nome di una tabella in un processo memorizzato?

Prima di tutto, dovresti MAI esegui composizioni di comandi SQL su un'app client come questa, questo è cos'è l'iniezione SQL. (Va bene per uno strumento di amministrazione che non ha privilegi propri, ma non per un'applicazione ad uso condiviso).

In secondo luogo, sì, una chiamata parametrizzata a una procedura memorizzata è sia più pulita che più sicura.

Comunque , poiché a tale scopo sarà necessario utilizzare Dynamic SQL, non si desidera comunque includere la stringa passata nel testo della query eseguita. Invece, vuoi usare la stringa passata per cercare i nomi del effettivo tabelle che l'utente dovrebbe essere autorizzato a interrogare nel modo.

Ecco un semplice esempio ingenuo:

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

Alcuni hanno giustamente chiesto perché questo è più sicuro. Si spera che i piccoli tavoli di Bobby possano renderlo più chiaro:0

Risposte ad altre domande:

  1. QUOTENAME da solo non è garantito per essere sicuro. MS ci incoraggia a usarlo, ma non hanno dato alcuna garanzia che non possa essere ingannato dagli hacker. Cordiali saluti, la vera sicurezza riguarda le garanzie. La ricerca nella tabella con QUOTENAME è un'altra storia, è indistruttibile.

  2. QUOTENAME non è strettamente necessario per questo esempio, la sola traduzione di ricerca su INFORMATION_SCHEMA è normalmente sufficiente. QUOTENAME è qui perché è una buona forma in sicurezza includere una soluzione completa e corretta. QUOTENAME qui in realtà sta proteggendo da un potenziale problema distinto ma simile noto come iniezione latente .

Devo notare che puoi fare la stessa cosa con i nomi di colonna dinamici e INFORMATION_SCHEMA.COLUMNS tavolo.

Puoi anche ignorare la necessità di stored procedure utilizzando invece una query SQL con parametri (vedi qui:https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=network-4.8). Ma penso che le procedure memorizzate forniscano una struttura di sicurezza più gestibile e meno soggetta a errori per casi come questo.