Python Academy · Lektion

Parameteriserede forespørgsler

Forebyg SQL-injektion

Lektion 3 af 413 trin

Parameteriserede forespørgsler er en gratis Python Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Python Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Python Academy-kurset indeholder 4 lektioner i alt.

Faren ved at sammenkæde strenge

Det er risikabelt at opbygge SQL ved at sammenkæde strenge. Hvis brugerinput indeholder SQL, kan det ændre din forespørgsel. Det kaldes SQL-injektion.

Gør aldrig dette med data, du ikke stoler på.

name = 'Alice'
# Unsafe pattern - do NOT do this
query = "SELECT * FROM users WHERE name = '" + name + "'"
print(query)

Sådan ser en injektion ud

Forestil dig en ondsindet værdi. Når du sammenkæder den, ændres forespørgslens betydning fuldstændigt.

name = "x' OR '1'='1"
query = "SELECT * FROM users WHERE name = '" + name + "'"
print(query)
print('The OR clause makes every row match!')

Pladsholdere redder dagen

Den sikre metode er parametriserede forespørgsler. Brug ? som pladsholder, og angiv værdierne som en tupel. Driveren undgår sikkert, at de fortolkes som SQL.

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
cur.execute('INSERT INTO users (name) VALUES (?)', ('Alice',))
cur.execute('SELECT * FROM users')
print(cur.fetchall())
conn.close()

Flere pladsholdere

Brug én ? pr. værdi. Angiv dem i en tupel i den samme rækkefølge, som de vises i.

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)')
cur.execute('INSERT INTO users (name, age) VALUES (?, ?)', ('Bob', 25))
cur.execute('SELECT * FROM users')
print(cur.fetchall())
conn.close()

Tupler med én værdi

En tupel med ét element skal have et afsluttende komma: ('Alice',). Uden kommaet opfatter Python parenteserne som almindelig gruppering.

good = ('Alice',)
bad = ('Alice')
print(type(good), type(bad))

Injektionsforsøg blokeret

Med pladsholdere behandles en ondsindet værdi som almindelige data, ikke som SQL. Den matcher ganske enkelt ingenting.

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
cur.execute('INSERT INTO users (name) VALUES (?)', ('Alice',))
evil = "x' OR '1'='1"
cur.execute('SELECT * FROM users WHERE name = ?', (evil,))
print('Rows matched:', cur.fetchall())
conn.close()

Navngivne pladsholdere

SQLite understøtter også navngivne pladsholdere med syntaksen :name. Angiv en ordbog med værdier.

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)')
cur.execute('INSERT INTO users (name, age) VALUES (:n, :a)', {'n': 'Carol', 'a': 40})
cur.execute('SELECT * FROM users')
print(cur.fetchall())
conn.close()

Parametre i WHERE

Pladsholdere fungerer i alle delsætninger, der tager imod en værdi, herunder WHERE.

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)')
cur.execute('INSERT INTO users (name, age) VALUES (?, ?)', ('Alice', 30))
cur.execute('INSERT INTO users (name, age) VALUES (?, ?)', ('Bob', 25))
cur.execute('SELECT name FROM users WHERE age > ?', (28,))
print(cur.fetchall())
conn.close()

executemany

Hvis du vil indsætte mange rækker, skal du bruge executemany() sammen med en liste af tupler. Det er hurtigere og stadig sikkert.

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
rows = [('Alice',), ('Bob',), ('Carol',)]
cur.executemany('INSERT INTO users (name) VALUES (?)', rows)
cur.execute('SELECT COUNT(*) FROM users')
print(cur.fetchone())
conn.close()

Pladsholdere er ikke til identifikatorer

Pladsholdere fungerer kun for værdier, ikke for tabel- eller kolonnenavne. De skal komme fra en tilladelsesliste i din egen kode, som du stoler på.

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
allowed = {'name', 'id'}
col = 'name'
if col in allowed:
    cur.execute('SELECT ' + col + ' FROM users')
    print('Safe column query ran')
conn.close()

En genanvendelig indsættelsesfunktion

Hvis du pakker parametriserede indsættelser ind i en funktion, bliver din kode overskuelig og konsekvent sikker.

import sqlite3
conn = sqlite3.connect(':memory:')
cur = conn.cursor()
cur.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')

def add_user(cursor, name):
    cursor.execute('INSERT INTO users (name) VALUES (?)', (name,))

add_user(cur, 'Dave')
cur.execute('SELECT * FROM users')
print(cur.fetchall())
conn.close()

Hurtig kontrol

Afprøv din viden om sikre forespørgsler.

Opsummering

Du har lært at skrive forespørgsler, der er sikre mod injektion.

  • Sammenkæd aldrig input, du ikke stoler på, med SQL
  • Brug ?-pladsholdere sammen med en tupel af værdier
  • Navngivne :name-pladsholdere tager imod en ordbog
  • executemany() indsætter mange rækker sikkert
  • Pladsholdere er til værdier, ikke identifikatorer
Gratis at komme i gang

Lær Python med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
76
Lektioner
320

Ofte stillede spørgsmål

Er lektionen “Parameteriserede forespørgsler” gratis?

Ja — hele teksten til “Parameteriserede forespørgsler” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Python Academy-kurset, skal du opgradere til CoddyKit PRO. Python Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Parameteriserede forespørgsler”?

Forebyg SQL-injektion Du øver dig i Python Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Python Academy?

Der kræves ingen tidligere erfaring. Python Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Parameteriserede forespørgsler”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Python Academy-lektion?

Ja. Alle Python Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Opret forbindelse og tabeller
  2. Insert, Select, Update, Delete
  3. Parameteriserede forespørgsler
  4. Transaktioner og context managers
← Tilbage til Python Academy