Kihagyás

Python és adatbázis kapcsolat

A legtöbb adatbázis-kezelő rendszerhez létezik Python csomag, amely segítségével könnyen lehet adatokat lekérdezni, módosítani, törölni, stb. Az adatbázis-kezelő rendszerek közül a legnépszerűbbek a PostgreSQL, MySQL, SQLite és MongoDB. Ezekhez a rendszerekhez a Python nyelvhez külön csomagokat kell telepíteni, amelyek segítségével a Python programok képesek lesznek az adatbázisokkal való kommunikációra.

Előfeltétel

Az alábbi anyag feltételezi az alapvető Python ismeretek meglétét valamint az adatbázis-kezelés alapjainak ismeretét.

SQLite

Az SQLite egy könnyen használható, beépített adatbázis-kezelő rendszer, amelynek nincs szüksége külön szerverre. Az SQLite adatbázis egyetlen fájlból áll, amelyet a Python programok könnyen kezelhetnek. Az SQLite adatbázisokhoz a Python nyelvhez tartozó sqlite3 csomagot kell telepíteni.

Adatbázis létrehozása

Az alábbi példában egy egyszerű SQLite adatbázist hozunk létre, amelyben egy users tábla lesz, amelyben a felhasználók neve és e-mail címe lesz tárolva.

1
2
3
4
5
6
7
8
9
import sqlite3

connection = sqlite3.connect('example.db') #(1)

with connection: #(2)
    cursor = connection.cursor() #(3)

    cursor.execute('''CREATE TABLE IF NOT EXISTS users
                (name TEXT, email TEXT)''') #(4)
  1. Ez a sor létrehoz egy kapcsolatot az example.db nevű SQLite adatbázis-fájlhoz. Ha ez a fájl még nem létezik, az SQLite automatikusan létrehozza. A connection változó ezt a kapcsolatot reprezentálja, amelyen keresztül kommunikálhatsz az adatbázissal.
  2. A with utasítás biztosítja, hogy a kapcsolat a blokk végrehajtása után automatikusan lezáruljon, ami magában foglalja a tranzakciók automatikus véglegesítését is, ha nem történt kivétel.
  3. A cursor objektumot használjuk az adatbázis-műveletek, például lekérdezések és adatmanipulációk végrehajtására.
  4. Ez a parancs egy SQL utasítást hajt végre, amely létrehoz egy users nevű táblát az adatbázisban, ha az még nem létezik. A táblának két oszlopa van: name és email, mindkettő szöveges típusú (TEXT). A CREATE TABLE IF NOT EXISTS kifejezés biztosítja, hogy ha a tábla már létezik, az SQL utasítás nem hoz létre új táblát vagy nem okoz hibát, hanem egyszerűen figyelmen kívül hagyja a parancsot.

Adatok beszúrása

Az alábbi példában a users táblába beszúrunk két felhasználót.

import sqlite3

connection = sqlite3.connect('example.db')

with connection:
    cursor = connection.cursor()

    cursor.execute("INSERT INTO users VALUES ('John Doe', 'john.doe@xyz.com')") #(1)

    cursor.execute("INSERT INTO users (name, email) VALUES ('Jane Doe', 'jane.doe@xyz.com')") #(2)
  1. Ez az utasítás beszúr egy új sort az users táblába, ahol az első érték a name oszlopnak, a második érték pedig az email oszlopnak felel meg. Itt nem adtuk meg explicit módon az oszlopneveket, így a rendszer feltételezi, hogy az értékek sorrendje megegyezik az adatbázis tábla oszlopainak deklarált sorrendjével. Ez az utasítás John Doe nevet és email címét szúrja be az adatbázisba.
  2. Ez az utasítás szintén beszúr egy új sort az users táblába, de itt explicit módon megadtuk az oszlopneveket (name, email), amelyekbe az értékeket beszúrni kívánjuk. Ez jó gyakorlat, mivel így világosan látható, melyik érték melyik oszlophoz tartozik, és csökkenti a hibák esélyét, különösen akkor, ha a táblában több oszlop is van, vagy ha nem minden oszlopba szeretnél adatot beszúrni. Ebben az esetben Jane Doe nevet és email címét szúrja be az adatbázisba.

Adatok beszúrása változókkal

Ez a Python kód egy egyszerű példát mutat arra, hogyan lehet felhasználói bemenetet fogadni, és azt adatokként beszúrni egy SQLite adatbázis users táblájába. A kód használja az sqlite3 modult az adatbázis-kezeléshez.

import sqlite3 #(1)

connection = sqlite3.connect('example.db') #(2)

name = input("Add meg a nevet: ") #(3)
email = input("Add meg az email címet: ") #(4)

with connection: #(5)
    cursor = connection.cursor() #(6)

    cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", [name, email]) #(7)
  1. Az sqlite3 modul importálása, ami lehetővé teszi az SQLite adatbázisok kezelését Pythonból.
  2. Létrehoz egy kapcsolatot az example.db nevű SQLite adatbázis-fájlhoz. Ha ez a fájl nem létezik, az SQLite létrehozza.
  3. Bekéri a felhasználótól a nevet, és az értéket eltárolja a name változóban.
  4. Bekéri a felhasználótól az email címet, és az értéket eltárolja az email változóban.
  5. gy kontextuskezelő használata, amely automatikusan kezeli az adatbázis-kapcsolatot. A blokk végén gondoskodik a kapcsolat lezárásáról és a tranzakciók véglegesítéséről (commit), ha nem történt kivétel.
  6. Létrehoz egy cursor objektumot, amit az adatbázis-műveletek végrehajtására használunk.
  7. Egy paraméterezett SQL INSERT utasítás, ami beszúrja a felhasználó által megadott name és email értékeket az users tábla megfelelő oszlopaiba. A ? helyőrzőket a [name, email] listában szereplő értékekkel helyettesíti, ami segít megelőzni az SQL-injekciós támadásokat.

Adatok lekérdezése

Az alábbi példában lekérdezzük az összes felhasználót a users táblából.

import sqlite3

connection = sqlite3.connect('example.db')

with connection:
    cursor = connection.cursor()

    lekerdezes = cursor.execute("SELECT * FROM users")
    for sor in lekerdezes:
        print(sor)

Adatok módosítása

Az alábbi példában módosítjuk a John Doe felhasználó e-mail címét.

1
2
3
4
5
6
7
8
import sqlite3

connection = sqlite3.connect('example.db')

with connection:
    cursor = connection.cursor()

    cursor.execute("UPDATE users SET email = 'doe.john@xyz.com' WHERE name = 'John Doe'")

Adatok törlése

Az alábbi példában töröljük a Jane Doe felhasználót a users táblából.

1
2
3
4
5
6
7
8
import sqlite3

connection = sqlite3.connect('example.db')

with connection:
    cursor = connection.cursor()

    cursor.execute("DELETE FROM users WHERE name = 'Jane Doe'")

Tábla kiürítése

Az alábbi példában kiürítjük a users táblát.

1
2
3
4
5
6
7
8
import sqlite3

connection = sqlite3.connect('example.db')

with connection:
    cursor = connection.cursor()

    cursor.execute("DELETE FROM users")

Feladatok

Adatbeszúrás és lekérdezés

Tip

Ez a feladat lehetőséget nyújt arra, hogy gyakorolj az adatbázis-kezeléssel, a felhasználói bemenet kezelésével és az adatok lekérdezésével kapcsolatos alapvető készségeket Pythonban.

  1. Adatbázis és Tábla Létrehozása: Hozz létre egy adatbázist "library.db" néven, és ebben egy "books" nevű táblát, amelynek két oszlopa van: title (a könyv címe) és author (a könyv szerzője).
  2. Adatok Hozzáadása: A felhasználó adhat hozzá új könyveket az adatbázishoz, megadva a könyv címét és szerzőjét.
  3. Adatok Lekérdezése: A felhasználó lekérdezheti az összes könyvet az adatbázisból, megjelenítve a könyvek címét és szerzőjét.

A Feladat Végrehajtása

  1. A program elindítása után a felhasználó választhat, hogy hozzáad-e új könyveket, lekérdezi az adatbázisban lévő könyveket, vagy kilép a programból.
  2. Új könyv hozzáadásakor a program bekéri a könyv címét és szerzőjét, majd hozzáadja ezeket az adatbázishoz.
  3. A lekérdezés opció kiírja az összes könyv címét és szerzőjét az adatbázisból.
Lehetséges megoldás
import sqlite3

# Adatbázis kapcsolat létrehozása
conn = sqlite3.connect('library.db')
c = conn.cursor()

# 'books' tábla létrehozása
c.execute('''
CREATE TABLE IF NOT EXISTS books (
    title TEXT,
    author TEXT
)
''')

# Könyv hozzáadásának függvénye
def add_book():
    title = input("Add meg a könyv címét: ")
    author = input("Add meg a könyv szerzőjét: ")

    c.execute("INSERT INTO books (title, author) VALUES (?, ?)", (title, author))
    conn.commit()
    print("Könyv hozzáadva az adatbázishoz.")

# Összes könyv lekérdezésének függvénye
def query_books():
    c.execute("SELECT title, author FROM books")
    for row in c.fetchall():
        print(f"Cím: {row[0]}, Szerző: {row[1]}")

# Fő program
while True:
    user_input = input("Mit szeretnél csinálni? (hozzáad, lekérdez, kilép): ")
    if user_input == "hozzáad":
        add_book()
    elif user_input == "lekérdez":
        query_books()
    elif user_input == "kilép":
        break
    else:
        print("Érvénytelen parancs.")

# Kapcsolat bezárása
conn.close()

SQL injekció

SQL injekció

Az alábbi anyag ismerete kritikus fontosságú a biztonságos adatbázis-kezeléshez.

Az SQL-injekció egy biztonsági rést jelent, amely akkor fordul elő, amikor egy alkalmazás nem megfelelően kezeli a felhasználói bemenetet, ami lehetővé teszi egy támadó számára, hogy kártékony SQL utasításokat küldjön az adatbázisnak. Ez általában adatok ellopásához, módosításához vagy akár az egész adatbázis törléséhez vezethet.

SQL Injection Támadás Példa

Tegyük fel, hogy van egy egyszerű alkalmazásunk, amely lehetővé teszi a felhasználók számára, hogy bejelentkezzenek az email címük és jelszavuk megadásával. A bejelentkezési űrlap adatait az alkalmazás egy SQL lekérdezésbe illeszti, hogy ellenőrizze, létezik-e a megadott felhasználónévvel és jelszóval rendelkező felhasználó az adatbázisban:

SELECT * FROM users WHERE email = 'beküldött_email' AND password = 'beküldött_jelszó';

Támadás

Egy támadó az alábbi bemenetet adhatja meg az email cím mezőbe (a jelszó mezőt üresen hagyva vagy tetszőleges értékkel kitöltve): ' OR '1'='1

Ez a bemenet az alábbi SQL lekérdezést eredményezi:

SELECT * FROM users WHERE email = '' OR '1'='1' AND password = 'tetszőleges_jelszó';

Az '1'='1' kifejezés mindig igaz, így a lekérdezés minden felhasználót visszaad az adatbázisból, függetlenül a beküldött jelszótól. Ha az alkalmazás az első találatot használja a bejelentkezési döntés alapjául, a támadó sikeresen bejelentkezhet anélkül, hogy ismernie kellene egy valódi felhasználó jelszavát.

Védekezés az SQL Injection ellen

Paraméterezett lekérdezések (Prepared Statements):

Használj paraméterezett lekérdezéseket vagy előkészített utasításokat, ahol a SQL kód és az adatok különállóak. Ez megakadályozza, hogy a bemeneti adatok befolyásolják a lekérdezés logikáját.

Példa paraméterezett lekérdezésre Pythonban az sqlite3 modullal:

cursor.execute("SELECT * FROM users WHERE email = ? AND password = ?", (email, password))