2017-01-24 21 views
0

ich einige Hinweise müssen auf die folgenden, wenn möglich, bitteApp_Code SQL Inject/Wählen Sie

Erklärung Ich habe eine Haupt project.cs Datei im App_Code, die Hauptfunktionen enthält. Eine dieser Funktionen ist ein SQL_Inject, das Daten in die Datenbank einfügt.

Ich habe dann mehrere Seiten, die diese Funktion von mehreren Client-Maschinen gleichzeitig verwenden.

Frage Die Antwort ich bin nach ist, ist dies eine sichere Methode der Wahl? Oder sollte ich eine neue Verbindung separat auf jeder .cs-Seite erstellen.

Grund/Problem Grund, dass dies ein Anliegen wird, sind wir derzeit ein kleines Unternehmen, aber wächst. Es ist passiert, dass eine Seite abstürzt, weil die SQL-Verbindung noch offen ist. Ich mache mir Sorgen, dass zwei Verbindungen gleichzeitig hergestellt werden müssen. Ich bin mir nicht sicher, ob dies das Problem ist oder ob es von etwas anderem kommt.

//GLOBAL DECLARATIONS 

//DB CONNECTIONS - retrieve from config file 

public static string ConProjectms = System.Configuration.ConfigurationManager.ConnectionStrings["conProject"].ConnectionString; 

//DB CONNECT TO SQL 
public static SqlConnection SqlConn = new SqlConnection(); 
public static SqlCommand SqlCmd = new SqlCommand(); 
public static SqlDataReader SqLdr; 
public static string SqlStr; 
public static string ConnString; 


public static void SqlInject(string query, string dataBase) 
{ 

    SqlConn.ConnectionString = ConProjectms; 
    //Set the Connection String 
    SqlConn.Open(); 
    //Open the connection 
    SqlCmd.Connection = SqlConn; 
    //Sets the Connection to use with the SQL Command 
    SqlCmd.CommandText = query; 
    //Sets the SQL String 
    SqlCmd.ExecuteNonQuery(); 
    //put Data 
    SqlClose(); 

} 


public static void SqlClose() 
{ 
    if (SqlConn.State != ConnectionState.Open) return; 
    SqlConn.Close(); 
    SqlCmd.Parameters.Clear(); 
} 
+1

Können Sie den Code zur Verfügung stellen, damit jeder ein besseres Verständnis bekommt – Izzy

+0

siehe Update – oldman

+0

Yeah. Versuchen Sie nicht, 'SqlConnection' * -Objekte * (oder andere Klassen wie diese) zu teilen/wiederzuverwenden. Sie können die Verbindung * string * in ein 'static'-Feld setzen, aber Ihre' SqlConnection' und 'SqlCommand' * innerhalb von *' SqlInject' erstellen und ihre Erstellung in 'using' Anweisungen einfügen. –

Antwort

0

SQL kann mehrere Verbindungen gleichzeitig verarbeiten. Ihr Code wird jedoch sehr wahrscheinlich von zwei Clients gleichzeitig ausgeführt, und sie verwenden die gleiche Verbindung nicht zwei separate Verbindungen. Das ist eine schlechte Sache # 1.

SQL Server macht eine fantastische Verbindung Connection - und ich nehme an, dass andere DBs ähnliche Funktionen haben. In einer solchen Welt sollten Sie nicht versuchen, irgendwelche Ihrer datenbezogenen Objekte zu behalten und wiederzuverwenden - sondern sie so zu erstellen, wie Sie sie benötigen, und wenn SQL sieht, dass Sie eine Verbindung verwenden, die sie zuvor erstellt und seitdem freigegeben hat werde das benutzen. Sie müssen nichts Seltsames tun, um diese Funktionalität zu erhalten.

Mit dem im Verstand, Ihre statische Objekte meist sollten weggehen, und Ihre SQLInject Methode wie folgt aussehen könnte:

public static void SqlInject(string query, string dataBase) 
{ 
    var connectionString = 
    System 
    .Configuration 
    .ConfigurationManager 
    .ConnectionStrings["conProject"] 
    .ConnectionString; 

    using (var connection = new SqlConnection(connectionString)) 
    { 
    connection.Open(); 
    using (var command = connection.CreateCommand()) 
    { 
     command.CommandText = query; 
     command.CommandType = CommandType.Text; 
     command.ExecuteNonQuery(); 
    } 
    } 
} 

Beachten Sie, dass Sie müssen nicht darum kümmern, die Verbindung geschlossen wird per se; Die using Blöcke behandeln die Anordnung Ihrer offenen, aktiven Objekte. Dies ist weitgehend, wie die Leute tun direkt SQL von c#. Übrigens verwenden weder Ihr Code noch meins das Argument dataBase. Vielleicht sollten Sie die Basisverbindungszeichenfolge damit bearbeiten?

Aber warten Sie - es gibt mehr!

alles, was gesagt haben, und da Sie eine Sorge um die Sicherheit erhöht, sollten Sie wissen, dass dies überhaupt nicht sicher Code ist - deine oder meine. SqlInject ist wahrscheinlich ein guter Name, weil es so ziemlich alles im query Argument erlaubt (was, BTW, wenn Sie ExecuteNonQuery tun, dann vielleicht query ist kein guter Name).

Sie sind weit besser zu erlauben, Argumente zu einer Bibliothek von bekannten Aussagen (möglicherweise gespeicherten Prozeduren), diese Argumente zu validieren und SQL Injection Angriffsminderung zu verwenden, um Ihre bekannten Aussagen zu parametrisieren (schauen Sie diese Phrase nach und Sie finden ein Fülle von Beispielen und Ratschlägen).

Just for yuks, hier ist ein Gerüst von dem, was Sie sich anschauen sollten:

public static void SqlInject(string commandName, params[] object commandArgs) 
{ 
    //--> no point in going on if we got no command... 
    if (string.IsNullOrEmpty(commandName)) 
    throw new ArgumentNullException(nameof(commandName)); 

    var connectionString = 
    System 
    .Configuration 
    .ConfigurationManager 
    .ConnectionStrings["conProject"] 
    .ConnectionString; 

    using (var connection = new SqlConnection(connectionString)) 
    { 
    connection.Open(); 
    using (var command = connection.CreateCommand()) 
    { 
     command.CommandType = CommandType.Text; 
     command.CommandText = "select commandText from dbo.StatementRepository where commandName = @commandName"; 
     command.Parameters.AddWithValue("@commandName", commandName); 
     var results = command.ExecuteScalar(); 
     if (results != null && results != DbNull.Value) 
     {    
     //--> calling a separate method to validate args, that returns 
     //--> an IDictionary<string,object> of parameter names 
     //--> and possibly modified arguments. 
     //--> Let this validation method throw exceptions. 
     var validatedArgs = ValidateArgs(commandName, commandArgs); 

     command.Parameters.Clear(); 
     command.CommandText = query; 
     foreach(var kvp in validatedArgs) 
     { 
      command.Parameters.AddWithValue(kvp.Key, kvp.Value); 
     } 
     command.ExecuteNonQuery(); 
     } 
     else 
     { 
     throw new InvalidOperationException("Invalid command"); 
     }   
    } 
    } 
} 

Ich versuchte nicht, ein tatsächliches Argument Validierung Methode zu schreiben, denn alles, was in der Anwendungslogik eingewickelt ... aber Ich wollte Ihnen eine Idee geben, wie Sie zu einem sichereren Zustand gelangen könnten.

+0

Vielen Dank dafür! hilft mir sehr! macht mir jetzt viel mehr Sinn. Dein Gerüst sieht beeindruckend aus! werde es definitiv berücksichtigen – oldman

0

Es gibt keinen Grund, warum Datenbankcode in App_Code nicht funktionieren sollte. Es klingt eher so, als würde Ihr Verbindungspooling nicht gut funktionieren. Sehen Sie sich die Verbindungszeichenfolge, IIS-Einstellungen und die Leistung Ihrer Datenbank an. Wenn aus irgendeinem Grund Verbindungspooling nicht möglich ist, wird die Laufzeit der Abfrage zum Problem.

Verwandte Themen