Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie soll ich einen Tabellennamen an eine gespeicherte Prozedur übergeben?

Zunächst einmal sollten Sie NIEMALS Erstellen Sie SQL-Befehlskompositionen auf einer Client-App wie dieser, das ist was SQL-Injection ist. (Es ist in Ordnung für ein Admin-Tool, das keine eigenen Privilegien hat, aber nicht für eine gemeinsam genutzte Anwendung).

Zweitens, ja, ein parametrisierter Aufruf einer gespeicherten Prozedur ist sauberer und sicherer.

Allerdings , da Sie hierfür Dynamic SQL verwenden müssen, möchten Sie die übergebene Zeichenfolge trotzdem nicht in den Text der ausgeführten Abfrage einschließen. Stattdessen möchten Sie den übergebenen String verwenden, um die Namen des tatsächlichen nachzuschlagen Tabellen, die der Benutzer so abfragen dürfen soll.

Hier ist ein einfaches naives Beispiel:

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

Einige haben ziemlich gefragt, warum dies sicherer ist. Hoffentlich können kleine Bobby Tables dies klarer machen:0

Antworten auf weitere Fragen:

  1. QUOTENAME allein ist nicht garantiert sicher. MS ermutigt uns, es zu verwenden, aber sie haben keine Garantie gegeben, dass es nicht von Hackern ausgetrickst werden kann. Zu Ihrer Information, bei echter Sicherheit dreht sich alles um die Garantien. Die Tabellensuche mit QUOTENAME ist eine andere Geschichte, sie ist unzerbrechlich.

  2. QUOTENAME ist für dieses Beispiel nicht unbedingt erforderlich, die Lookup-Übersetzung auf INFORMATION_SCHEMA allein ist normalerweise ausreichend. QUOTENAME ist hier, weil es aus Sicherheitsgründen zum guten Ton gehört, eine vollständige und korrekte Lösung beizufügen. QUOTENAME hierin schützt tatsächlich vor einem bestimmten, aber ähnlichen potenziellen Problem, das als latente Injektion bekannt ist .

Ich sollte beachten, dass Sie dasselbe mit dynamischen Spaltennamen und INFORMATION_SCHEMA.COLUMNS tun können Tisch.

Sie können die Notwendigkeit gespeicherter Prozeduren auch umgehen, indem Sie stattdessen eine parametrisierte SQL-Abfrage verwenden (siehe hier:https://docs.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlcommand.parameters?view=Netzwerkframework-4.8). Aber ich denke, dass gespeicherte Prozeduren eine besser handhabbare und weniger fehleranfällige Sicherheitseinrichtung für Fälle wie diesen bieten.