На първо място, трябва НИКОГА направете композиции на SQL команди в клиентско приложение като това, това е какво е SQL инжекция. (Добре е за администраторски инструмент, който няма собствени привилегии, но не и за приложение за споделена употреба).
На второ място, да, параметризираното извикване на съхранена процедура е едновременно по-чисто и по-безопасно.
Въпреки това , тъй като ще трябва да използвате Dynamic SQL, за да направите това, все още не искате да включите предадения низ в текста на изпълнената заявка. Вместо това искате да използвате предадения низ, за да търсите имената на действителните таблици, които потребителят трябва да има право да прави заявки по пътя.
Ето един прост наивен пример:
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
Някои справедливо попитаха защо това е по-безопасно. Да се надяваме, че малките Боби Таблици могат да направят това по-ясно:0
Отговори на още въпроси:
-
QUOTENAME само по себе си не е гарантирано, че е в безопасност. MS ни насърчава да го използваме, но не са дали гаранция, че не може да бъде надминат от хакери. FYI, истинската сигурност е свързана с гаранциите. Търсенето в таблицата с QUOTENAME е друга история, тя е неразбиваема.
-
QUOTENAME не е строго необходимо за този пример, само преводът за търсене на INFORMATION_SCHEMA обикновено е достатъчен. QUOTENAME е тук, защото е добра форма за сигурност да включва пълно и правилно решение. QUOTENAME тук всъщност защитава срещу отделен, но подобен потенциален проблем, известен като латентно инжектиране .
Трябва да отбележа, че можете да направите същото с динамични имена на колони и INFORMATION_SCHEMA.COLUMNS
маса.
Можете също така да заобиколите необходимостта от съхранени процедури, като вместо това използвате параметризирана SQL заявка (вижте тук:https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=мрежова рамка-4.8). Но мисля, че съхранените процедури осигуряват по-управляемо и по-малко податливо на грешки средство за сигурност за случаи като този.