Lekce 6 - SqlDataReader a připojená databáze ve VB.NET
V předchozím kvízu, Kvíz - Databáze, přístupy, připojená aplikace ve VB-ADO.NET , jsme si ověřili nabyté zkušenosti z předchozích lekcí.
V dnešním Databáze - ADO.NET tutoriálu, v jazyce VB.NET,
se naučíme číst řádky z databáze pomocí třídy
SqlDataReader
a používat parametrizované
dotazy, které znemožňují útok SQL injection.
Pracujeme s databází z lekce Vytvoření lokální databáze ve Visual Studio ve VB.NET, kterou v jednotlivých lekcích upravujeme.
Čtení dat
Pokud potřebujeme spustit nad databází dotaz, který vrací více
záznamů (ten náš poslední vracel jen jedno číslo), musíme ke
zpracování výsledku dotazu využít třídu SqlDataReader
.
Instanci této třídy jako výsledek vrátí metoda
ExecuteReader()
třídy SqlCommand
.
Třída SqlDataReader
umožňuje procházet výslednou množinu
dat po jednotlivých záznamech. K tomu slouží metoda Read()
.
Přístup k jednotlivým atributům záznamu můžeme získat pomocí
indexu nebo názvu sloupce uvedeného v
kulatých závorkách.
Výpis slovíček
Napíšeme si kód pro vypsání všech slovíček z naší databáze:
Using pripojeni As SqlConnection = New SqlConnection(connectionString) pripojeni.Open() Dim prikaz As SqlCommand = New SqlCommand("SELECT Id, Czech, English FROM Word", pripojeni) Dim dataReader As SqlDataReader = prikaz.ExecuteReader() While dataReader.Read() ' dokud neprojdeme všechny záznamy Console.WriteLine("{0} {1} {2}", dataReader(0), dataReader("Czech"), dataReader(2)) End While pripojeni.Close() End Using
Připojíme se k databázi metodou Open()
a do proměnné
prikaz
sestavíme SQL dotaz. V cyklu While
, na
instanci dataReader
typu SqlDataReader
, postupně
načítáme slovíčka metodou Read()
a vypisujeme pro každý
sloupec jeho:
- index (Id)
dataReader(0)
, - název
dataReader("Czech")
, - index (English)
dataReader(2)
.
Výsledek:
Konzolová aplikace
1 počítač computer
2 míč ball
3 pes dog
4 já I
5 mít rád like
6 devbook devbook
Předávání parametrů
Udělejme z aplikace opravdový slovníček a nechme uživatele zadat slovíčko, které mu následně přeložíme.
SQL injekce
Nejprve si ukažme, jak se to nemá dělat. Naivně bychom si mohli nechat zadat slovíčko, a to potom přímo vložit jako vyhledávanou frázi do dotazu. Zdrojový kód aplikace by vypadal takto:
' Tento zdrojový kód je nebezpečný. Using pripojeni As SqlConnection = New SqlConnection(connectionString) pripojeni.Open() Console.WriteLine("Zadej anglické slovíčko k překladu") Dim slovo As String = Console.ReadLine() Dim prikaz As SqlCommand = New SqlCommand("SELECT Czech FROM Word WHERE English='" & slovo & "'", pripojeni) Dim dataReader As SqlDataReader = prikaz.ExecuteReader() While dataReader.Read() Console.WriteLine("Překlad: {0}", dataReader("Czech")) End While pripojeni.Close() End Using
SQL dotaz je podobný tomu předchozímu. Nezajímají nás však již
všechny řádky, ale jen ty, kde má sloupec English
určitou
hodnotu. Podmínku v SQL dotazu jsme zapsali pomocí klauzule
WHERE
.
Navenek aplikace funguje korektně:
Konzolová aplikace
Zadej anglické slovíčko k překladu
computer
Překlad: počítač
Zamysleme se nad tím, co se stane, když nějaký uživatel zadá k překladu tento řetězec:
'; DROP TABLE Word --
Škodlivý kód se nám vloží přímo do dotazu a spustí se nad databází. Útočníkovi tak dáváme plnou kontrolu nad našimi daty. V tomto případě nám nenávratně vymaže celou tabulku. A to je ještě poměrně nevinný útok, mohl by nám vzít i hesla uživatelů a podobně.
Bezpečnostní problém jsme způsobili přímým vkládáním hodnot do textu SQL dotazu. Útok se proto nazývá SQL injection, tj. vložení cizího SQL kódu do našeho. Musíme počítat s tím, že škodlivý kód může být v každém parametru, který do dotazu vkládáme. Nelze se spolehnout na to, že tato proměnná asi nebude nic od uživatele obsahovat.
Ochrana před SQL injekcí
V minulosti se parametry ošetřovaly speciální funkcí, která tzv. zescapovala škodlivé znaky. Moderní dotazy se píší pomocí tzv. Prepared Statements. Ty fungují tak, že se do dotazu místo parametrů vloží jen speciální značky. Parametry se poté předávají odděleně. Ukažme si, jak do dotazu vložit parametry správně:
Using pripojeni As SqlConnection = New SqlConnection(connectionString) pripojeni.Open() Console.WriteLine("Zadej anglické slovíčko k překladu") Dim slovo As String = Console.ReadLine() Dim prikaz As SqlCommand = New SqlCommand("SELECT Czech FROM Word WHERE English=@slovo", pripojeni) prikaz.Parameters.AddWithValue("@slovo", slovo) Dim dataReader As SqlDataReader = prikaz.ExecuteReader() While dataReader.Read() Console.WriteLine("Překlad: {0}", dataReader("Czech")) End While pripojeni.Close() End Using
Všimněme si, že v SQL dotazu je jen zástupná značka,
která se označuje zavináčem @
a libovolným názvem. Nepíšeme
kolem ní ani apostrofy, ty jsou dodány později podle typu značky. Před
zavoláním metody ExecuteReader()
připojíme do dotazu
parametry, v našem případě parametr @slovo
,
jehož hodnotou bude proměnná slovo. Databáze si sama parametry ošetří a
nemusíme se bát, že by nám aplikaci někdo mohl nabourat.
V příští lekci, Databáze ve VB.NET - INSERT, UPDATE, DELETE a COUNT, se naučíme přidávat, mazat, editovat a
počítat záznamy v MS-SQL databázi ve VB.NET pomocí ADO.NET a třídy
SqlCommand
.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 6x (1021.43 kB)
Aplikace je včetně zdrojových kódů v jazyce VB.NET