0Pricing
Python Academy · Lezione

Query parametrizzate

Prevenire l'iniezione SQL

Query parametrizzate è una lezione Python Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Python Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Python Academy include 4 lezioni in totale.

Il rischio della concatenazione di stringhe

Costruire SQL concatenando stringhe è rischioso. Se l'input dell'utente contiene SQL, può modificare la query. Questo attacco si chiama SQL injection.

Non lo faccia mai con dati non attendibili.

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

Come si presenta un attacco di SQL injection

Immagini un valore malevolo. Concatenarlo modifica completamente il significato della query.

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

I segnaposto come soluzione

Il modo sicuro consiste nell'utilizzare query parametrizzate. Utilizzi ? come segnaposto e passi i valori in una tupla. Il driver li sottopone all'escaping in modo sicuro.

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()

Più segnaposto

Utilizzi un ? per ogni valore. Li passi in una tupla nello stesso ordine in cui compaiono.

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()

Tuple con un solo valore

Una tupla con un solo elemento richiede una virgola finale: ('Alice',). Senza la virgola, Python interpreta le parentesi semplicemente come raggruppamento.

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

Tentativo di injection bloccato

Con i segnaposto, un valore malevolo viene trattato come semplice dato, non come SQL. Semplicemente non corrisponde ad alcun risultato.

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()

Segnaposto denominati

SQLite supporta anche i segnaposto denominati con la sintassi :name. Passi un dizionario di valori.

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()

Parametri in WHERE

I segnaposto funzionano in qualsiasi clausola che accetti un valore, inclusa 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

Per inserire molte righe, utilizzi executemany() con un elenco di tuple. È più rapido e resta sicuro.

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()

I segnaposto non servono per gli identificatori

I segnaposto funzionano solo per i valori, non per i nomi delle tabelle o delle colonne. Questi ultimi devono provenire da una whitelist attendibile definita nel Suo codice.

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()

Una funzione di inserimento riutilizzabile

Racchiudere gli inserimenti parametrizzati in una funzione mantiene il codice ordinato e sicuro in modo coerente.

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()

Verifica rapida

Verifichi la Sua conoscenza delle query sicure.

Riepilogo

Ha imparato a scrivere query protette dalla SQL injection.

  • Non concateni mai input non attendibili in SQL
  • Utilizzi i segnaposto ? con una tupla di valori
  • I segnaposto denominati :name richiedono un dizionario
  • executemany() inserisce molte righe in modo sicuro
  • I segnaposto servono per i valori, non per gli identificatori

Domande Frequenti

La lezione «Query parametrizzate» è gratuita?

Sì — il testo completo di «Query parametrizzate» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Python Academy, passa a CoddyKit PRO. Il corso Python Academy include 4 lezioni in totale.

Cosa imparerò in «Query parametrizzate»?

Prevenire l'iniezione SQL Eserciti Python Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Python Academy?

Non è richiesta alcuna esperienza precedente. Python Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Query parametrizzate»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Python Academy?

Sì. Ogni lezione Python Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Connessione e creazione di tabelle
  2. Insert, Select, Update, Delete
  3. Query parametrizzate
  4. Transazioni e context manager
← Torna a Python Academy