Jestem bardzo nowy w pracy z bazami danych. Teraz mogę napisać SELECT
, UPDATE
, DELETE
i INSERT
poleceń. Ale widziałem wiele forów, na których wolimy pisać:
SELECT empSalary from employee where salary = @salary
...zamiast:
SELECT empSalary from employee where salary = txtSalary.Text
Dlaczego zawsze wolimy używać parametrów i jak ich używać?
Chciałem poznać zastosowanie i zalety pierwszej metody. Słyszałem nawet o iniekcji SQL, ale nie do końca to rozumiem. Nie wiem nawet, czy wstrzyknięcie SQL jest związane z moim pytaniem.
sql
sql-server
sql-injection
Piaszczysty
źródło
źródło
Odpowiedzi:
Używanie parametrów pomaga zapobiegać atakom typu SQL Injection gdy baza danych jest używana w połączeniu z interfejsem programu, takim jak program komputerowy lub witryna internetowa.
W Twoim przykładzie użytkownik może bezpośrednio uruchomić kod SQL w bazie danych, tworząc instrukcje w programie
txtSalary
.Na przykład, gdyby mieli pisać
0 OR 1=1
, wykonywany SQL byłbyprzy czym wszystkie empSalary zostaną zwrócone.
Ponadto użytkownik może wykonać znacznie gorsze polecenia względem bazy danych, w tym usunąć ją, jeśli napisał
0; Drop Table employee
:Tabela
employee
zostanie wówczas usunięta.W Twoim przypadku wygląda na to, że używasz platformy .NET. Korzystanie z parametrów jest tak proste, jak:
DO#
VB.NET
Edycja 2016-4-25:
Zgodnie z komentarzem George'a Stockera, zmieniłem przykładowy kod na nieużywany
AddWithValue
. Generalnie zaleca się również zawijanie instrukcjiIDisposable
wusing
instrukcje.źródło
Insert Into table (Col1, Col2) Values (@Col1, @Col2)
. W swoim kodzie dodałbyś wieleAddWithValue
s.parameter.Value = someValue
.Masz rację, jest to związane z iniekcją SQL , która jest luką umożliwiającą malicioius użytkownikowi wykonanie dowolnych instrukcji w Twojej bazie danych. Ten ulubiony komiks XKCD z dawnych czasów ilustruje koncepcję:
W twoim przykładzie, jeśli użyjesz tylko:
Jesteś otwarty na iniekcje SQL. Na przykład załóżmy, że ktoś wchodzi do txtSalary:
Po wykonaniu tego zapytania wykona on
SELECT
iUPDATE
lubDROP
, lub cokolwiek chcieli. Na--
końcu po prostu komentuje resztę twojego zapytania, co byłoby przydatne w ataku, gdybyś później cokolwiek konkatenowałtxtSalary.Text
.Poprawnym sposobem jest użycie sparametryzowanych zapytań, np. (C #):
Dzięki temu możesz bezpiecznie wykonać zapytanie.
Aby dowiedzieć się, jak uniknąć wstrzykiwania SQL w kilku innych językach, odwiedź bobby-tables.com , witrynę utrzymywaną przez użytkownika SO .
źródło
Oprócz innych odpowiedzi należy dodać, że parametry nie tylko pomagają zapobiegać wstrzykiwaniu sql, ale mogą poprawiać wydajność zapytań . Sql Server buforuje sparametryzowane plany zapytań i ponownie wykorzystuj je podczas wykonywania powtarzających się zapytań. Jeśli nie sparametryzowałeś zapytania, serwer sql kompilowałby nowy plan przy każdym wykonaniu zapytania (z pewnymi wyjątkami), jeśli tekst zapytania byłby inny.
Więcej informacji na temat buforowania planu zapytania
źródło
Dwa lata po moim pierwszym wyjeździe recydywa ...
Dlaczego preferujemy parametry? Wstrzyknięcie SQL to oczywiście duży powód, ale może być tak, że potajemnie pragniemy wrócić do SQL jako języka . SQL w literałach łańcuchowych jest już dziwną praktyką kulturową, ale przynajmniej możesz skopiować i wkleić swoje żądanie do studia zarządzania. SQL skonstruowany dynamicznie z warunkami warunkowymi i strukturami kontrolnymi języka hosta, gdy SQL ma warunki warunkowe i struktury kontrolne, jest po prostu barbarzyństwem poziomu 0. Musisz uruchomić aplikację w trybie debugowania lub ze śladem, aby zobaczyć, jaki SQL generuje.
Nie poprzestawaj tylko na parametrach. Idź na całość i użyj QueryFirst (zastrzeżenie: które napisałem). Twój SQL żyje w pliku .sql. Edytujesz go w fantastycznym oknie edytora TSQL, z walidacją składni i Intellisense dla tabel i kolumn. Możesz przypisać dane testowe w specjalnej sekcji komentarzy i kliknąć „odtwórz”, aby uruchomić zapytanie bezpośrednio w oknie. Tworzenie parametru jest tak proste, jak umieszczenie „@myParam” w kodzie SQL. Następnie za każdym razem, gdy zapisujesz, QueryFirst generuje otokę C # dla zapytania. Twoje parametry pojawiają się, silnie wpisane, jako argumenty metod Execute (). Twoje wyniki są zwracane w IEnumerable lub liście POCO o jednoznacznie określonym typie, typach wygenerowanych na podstawie rzeczywistego schematu zwróconego przez zapytanie. Jeśli zapytanie nie zostanie uruchomione, aplikacja nie zostanie skompilowana. Jeśli schemat bazy danych ulegnie zmianie, a zapytanie zostanie uruchomione, ale niektóre kolumny znikną, błąd kompilacji wskazuje na na wiersz w kodziektóry próbuje uzyskać dostęp do brakujących danych. Jest też wiele innych zalet. Dlaczego chcesz uzyskać dostęp do danych w inny sposób?
źródło
W Sql, gdy dowolne słowo zawiera znak @, oznacza to, że jest zmienne i używamy tej zmiennej do ustawiania w niej wartości i używamy jej w obszarze liczbowym w tym samym skrypcie sql, ponieważ jest ograniczone tylko do pojedynczego skryptu, podczas gdy możesz zadeklarować wiele zmiennych tego samego typu i nazwy w wielu skryptach. Używamy tej zmiennej w partii procedur składowanych, ponieważ procedury składowane są wstępnie skompilowanymi zapytaniami i możemy przekazywać wartości w tych zmiennych ze skryptu, pulpitu i stron internetowych, aby uzyskać dalsze informacje, przeczytaj artykuł Deklaracja zmiennej lokalnej , procedura składowana SQL i wstrzyknięcia sql .
Przeczytaj również artykuł Ochrona przed wstrzyknięciem sql, który zawiera wskazówki, jak chronić bazę danych.
Mam nadzieję, że pomoże ci to zrozumieć również każde pytanie, które komentuję.
źródło
Inne odpowiedzi wyjaśniają, dlaczego parametry są ważne, ale ma też wadę! W .net istnieje kilka metod tworzenia parametrów (Add, AddWithValue), ale wszystkie one wymagają niepotrzebnej troski o nazwę parametru i wszystkie zmniejszają czytelność kodu SQL w kodzie. Kiedy próbujesz medytować nad kodem SQL, musisz przeszukać okolice powyżej lub poniżej, aby zobaczyć, jaka wartość została użyta w parametrze.
Pokornie twierdzę, że moja mała klasa SqlBuilder jest najbardziej eleganckim sposobem pisania zapytań parametrycznych . Twój kod będzie wyglądał następująco ...
DO#
Twój kod będzie krótszy i znacznie bardziej czytelny. Nie potrzebujesz nawet dodatkowych wierszy, a kiedy czytasz, nie musisz szukać wartości parametrów. Klasa, której potrzebujesz, jest tutaj ...
źródło
AddWithValue
może powodować niejawne problemy z konwersją.Stary post, ale chciałem upewnić się, że nowicjusze są świadomi procedur przechowywanych .
Moja warta 10 centów jest taka, że jeśli jesteś w stanie napisać instrukcję SQL jako procedurę składowaną , moim zdaniem jest to optymalne podejście. I ZAWSZE używać przechowywanych procs i nigdy Przelotowe zapisów w moim głównym kodu. Na przykład
SQL Table > SQL Stored Procedures > IIS/Dot.NET > Class
.Korzystając z procedur składowanych, można ograniczyć użytkownika tylko do uprawnień EXECUTE , zmniejszając w ten sposób zagrożenia bezpieczeństwa .
Twoja procedura składowana jest z natury parameryzowana i można określić parametry wejściowe i wyjściowe.
Procedura składowana (jeśli zwraca dane za pośrednictwem
SELECT
instrukcji) jest dostępna i odczytywana w taki sam sposób, jak zwykłaSELECT
instrukcja w kodzie.Działa również szybciej, ponieważ jest kompilowany na serwerze SQL.
Czy wspomniałem też, że możesz wykonać wiele kroków, np.
update
Tabelę, sprawdzić wartości na innym serwerze DB, a po zakończeniu, zwrócić dane do klienta, wszystko na tym samym serwerze i bez interakcji z klientem. Jest to więc DUŻO szybsze niż zakodowanie tej logiki w kodzie.źródło