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:
-
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.
-
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.