Jak? Parametry i instrukcja LIKE SQL


80

Piszę funkcję wyszukiwania i wymyśliłem to zapytanie przy użyciu parametrów, aby zapobiec lub przynajmniej ograniczyć ataki typu SQL injection. Jednak gdy uruchamiam go przez mój program, nic nie zwraca:

SELECT * FROM compliance_corner WHERE (body LIKE '%@query%') OR (title LIKE '%@query%')

Czy można używać parametrów w ten sposób? czy też są ważne tylko w takim przypadku, jak:

SELECT * FROM compliance_corner WHERE body LIKE '%<string>%'(gdzie <string>jest obiekt wyszukiwania).

EDYCJA: Konstruuję tę funkcję w VB.NET, czy ma to wpływ na składnię, którą wnieśliście?

Uruchomiłem również tę instrukcję w SQL Server: SELECT * FROM compliance_corner WHERE (body LIKE '%max%') OR (title LIKE% max% ') `i zwraca wyniki.

Odpowiedzi:


78

Twój podstawowy kod wizualny wyglądałby mniej więcej tak:

Dim cmd as New SqlCommand("SELECT * FROM compliance_corner WHERE (body LIKE '%' + @query + '%') OR (title LIKE '%' + @query + '%')")

cmd.Parameters.Add("@query", searchString)

3
Jak wskazał Adam w swojej odpowiedzi, nie chroni to przed wstrzyknięciem SQL. Zapytanie powinno być sparametryzowane.
DOK

6
Czy możesz podać przykład, w którym nie zapobiega to iniekcji SQL? Z moich testów działa dobrze
John

27
Nie jest otwarty do SQLwstrzyknięcia, tylko LIKEzastrzyk. Oznacza to, że użytkownik może wprowadzić znaki specjalne, takie jak % ^i, _które LIKEbędą specjalnie interpretowane. Oznacza to, że użytkownik może nie uzyskać tego, czego oczekuje w przypadku niektórych wyszukiwań. Na przykład wyszukiwanie 'less than 1% fat'może zwrócić wynik 'less than 1% of doctors recommend this - it's full of fat!'.
Alex Humphrey,

1
Zgadzam się, coś podobnego podlega zasadzie „Like Injection”, a szkoda polega tylko na tym, że użytkownik nie otrzymuje tego, czego oczekuje. Czyszczenie zapytań powinno być wykonywane przez cały czas, nawet jeśli jest sparametryzowana. Poleganie tylko na tej ochronie nie jest do końca bezpieczne.
Anthony Mason

1
searchString.Replace("[","[[]").Replace("%","[%]").Replace("_","[_]")Poleciłbym również zrobić , co pozwoli uniknąć iniekcji LIKE (o ile nie używasz klauzuli ucieczki).
8DX

114

Cóż, poszedłbym z:

 Dim cmd as New SqlCommand(
 "SELECT * FROM compliance_corner"_
  + " WHERE (body LIKE @query )"_ 
  + " OR (title LIKE @query)")

 cmd.Parameters.Add("@query", "%" +searchString +"%")

To prawda, zaakceptowana odpowiedź udzielona przez Johna ma nieprawidłową składnię!
Adam

3
Nie jestem pewien, dlaczego jego składnia jest nieprawidłowa, jego rozwiązanie działało dobrze. Mam funkcję, która konstruuje i zwraca instrukcję SQL do użycia w datatable lub czymkolwiek innym.
Anders

1
Dodatkowa uwaga: składnia języka C # przy użyciu MySQLDataAdapter = da = new MySQLDataAdapter ("SELECT * FROM tableA WHERE fieldA = @fieldA"); da.SelectCommand.Parameters.AddWithValue ("@ fieldA", "%" + someValue + "%");
John M

3
Druga odpowiedź (od Johna) też działa, ale rzeczywiście jest podatna na podobne zastrzyki, które MOGĄ dać dziwne wyniki, w zależności od celu twojego pola.
Steven Lemmens

1
Nie powinno być cmd.Parameters.Addsię cmdLoad.Parameters.AddWithValueczy jest jakiś problem? Rozumiem, że odpowiedź Jamesa pochodzi z 2008 roku :)
WTFZane

26

musisz zrobić:

LIKE '%' + @param + '%'


doskonałe rozwiązanie - dałoby więcej niż +1, jeśli to możliwe! Dzięki
BM,

2

Być może trzeba będzie połączyć znaki% z parametrem, np .:

LIKE '%' || @query || „%”

Edycja: Właściwie to może nie mieć żadnego sensu. Myślę, że mogłem źle zrozumieć twój problem.


1

Czasami symbol używany jako symbol zastępczy %nie jest taki sam, jeśli wykonujesz zapytanie z VB, jak podczas wykonywania go z MS SQL / Access. Spróbuj zmienić symbol zastępczy z %na *. To może zadziałać.
Jeśli jednak debugujesz i chcesz skopiować ciąg SQL bezpośrednio w MS SQL lub Access, aby go przetestować, może być konieczna zmiana symbolu z powrotem na %w MS SQL lub Access, aby faktycznie zwracać wartości.

Mam nadzieję że to pomoże


Nie wiem na pewno w 2012 roku, ale to% vs * jest specyficzne dla silników ADO vs DAO. Jeśli używasz DAO lub Current () w Access the Wildcard to *; jeśli używasz ADO z dowolnego kodu, w tym VBA wewnątrz Access, symbol wieloznaczny to%.
Marcelo Scofano Diniz

1

spróbuj też w ten sposób

Dim cmd as New SqlCommand("SELECT * FROM compliance_corner WHERE (body LIKE CONCAT('%',@query,'%')  OR  title LIKE CONCAT('%',@query,'%') )")
cmd.Parameters.Add("@query", searchString)
cmd.ExecuteNonQuery()

Użyto Concat zamiast +

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.