Przede wszystkim NIGDY rób kompozycje poleceń SQL w aplikacji klienckiej takiej jak ta, to czym jest wstrzykiwanie SQL. (Jest OK w przypadku narzędzia administracyjnego, które nie ma własnych uprawnień, ale nie w przypadku aplikacji do wspólnego użytku).
Po drugie, tak, sparametryzowane wywołanie procedury składowanej jest zarówno czystsze, jak i bezpieczniejsze.
Jednak , ponieważ będziesz musiał użyć do tego dynamicznego SQL, nadal nie chcesz uwzględniać przekazanego ciągu w tekście wykonywanego zapytania. Zamiast tego chcesz użyć przekazanego ciągu do wyszukania nazw rzeczywistych tabele, do których użytkownik powinien mieć możliwość wykonywania zapytań.
Oto prosty naiwny przykład:
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
Niektórzy uczciwie pytali, dlaczego jest to bezpieczniejsze. Mam nadzieję, że małe stoliki Bobby sprawią, że będzie to jaśniejsze:0
Odpowiedzi na więcej pytań:
-
Samo QUOTENAME nie gwarantuje bezpieczeństwa. MS zachęca nas do korzystania z niego, ale nie daje gwarancji, że nie da się go przechytrzyć przez hakerów. FYI, prawdziwe bezpieczeństwo to gwarancja. Wyszukiwanie tabeli za pomocą QUOTENAME to inna historia, jest nie do złamania.
-
QUOTENAME nie jest bezwzględnie konieczne w tym przykładzie, samo tłumaczenie wyszukiwania w INFORMATION_SCHEMA jest zwykle wystarczające. QUOTENAME jest tutaj, ponieważ w bezpieczeństwie dobrze jest podać kompletne i poprawne rozwiązanie. QUOTENAME tutaj w rzeczywistości chroni przed odrębnym, ale podobnym potencjalnym problemem znanym jako utajone wstrzyknięcie .
Powinienem zauważyć, że możesz zrobić to samo z dynamicznymi nazwami kolumn i INFORMATION_SCHEMA.COLUMNS
stół.
Możesz również ominąć potrzebę stosowania procedur składowanych, używając zamiast tego sparametryzowanego zapytania SQL (zobacz tutaj:https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=netframework-4.8). Myślę jednak, że procedury składowane zapewniają łatwiejszą w zarządzaniu i mniej podatną na błędy funkcję bezpieczeństwa w takich przypadkach.