Το λάθος που έκανες είναι ότι αντί να χρησιμοποιήσεις stored procedures ή parameterized queries δοκίμασες να φτιάξεις ένα SQL statement με string concatenation. Κάπου θα ξέχασες κανένα ' με αποτέλεσμα το < να μεταφραστεί ως "μικρότερο".
Το πρόβλημα που έχεις όμως είναι ΠΟΛΥ ΠΙΟ ΣΟΒΑΡΟ από ένα ' που ξέχασες. Γράφοντας τέτοιο κώδικα επιτρέπεις σε οποιοδήποτε script kiddie να εκτελέσει κώδικα στην εφαρμογή σου, χρησιμοποιώντας SQL Injection. Ακόμα και αν βάλεις το ', κάποιος κακόβουλος χρήστης μπορεί να βάλει σε κάποιο text box εντολές οι οποίες θα εκτελεστούν από τον SQL server. Για παράδειγμα, θα μπορούσε να γράψει ';DROP TABLE users; και να σου σβήσει ένα ολόκληρο πίνακα. Ή κάτι σαν '123;EXEC master..xp_cmdshell dir-- και να εκτελέσει οποιοδήποτε κώδικα θέλει με τα δικαιώματα του SQL Server account.
Η λύση είναι απλούστατη. Αντί να χρησιμοποιήσεις string concatenation θα πρέπει να χρησιμοποιήσεις parameterized queries ή stored procedures στις οποίες θα περάσεις ως string parameters τις παραμέτρους σου. Με αυτό τον τρόπο δεν υπάρχει περίπτωση να μεταφραστεί ένα string ως SQL και εξαλείφεται ο κίνδυνος του SQL Injection. Επίσης αποφεύγεις λάθη σαν αυτό που αντιμετώπισες τώρα αλλά πετυχαίνεις και καλύτερες επιδόσεις επειδή ο SQL Server δεν χρειάζεται να ξανακάνει compile τις εντολές που του δίνεις.
Το παράδειγμα του Wikipedia δείχνει πόσο εύκολο είναι να χρησιμοποιήσεις parameterized queries. Ο κώδικας που πρέπει να γράψεις είναι ο παρακάτω:
using (SqlCommand myCommand = new SqlCommand("select * from Users where UserName=@username and Password=@password", myConnection))
{
myCommand.Parameters.AddWithValue("@username", user);
myCommand.Parameters.AddWithValue("@password", pass);
myConnection.Open();
SqlDataReader myReader = myCommand.ExecuteReader())
...................
}
Είναι σχεδόν ο ίδιος κώδικας που θα έγραφες για να φτιάξεις το statement με concatenation, μόνο που τώρα προσθέτεις και μία γραμμή ανά παράμετρο.
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos