PYTHON

Use Prepared Statements to Prevent SQL Injection

Learn how to prevent SQL Injection attacks in Python applications by consistently using prepared statements with parameterized queries, ensuring user input is safely handled.

import sqlite3

def create_user(username, password_hash):
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()

    try:
        # Create table if it doesn't exist
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY,
                username TEXT NOT NULL UNIQUE,
                password_hash TEXT NOT NULL
            )
        ''')
        conn.commit()

        # Using a prepared statement with parameterized query
        # The '?' placeholders ensure that user input is treated as data, not code.
        cursor.execute("INSERT INTO users (username, password_hash) VALUES (?, ?)",
                       (username, password_hash))
        conn.commit()
        print(f"User '{username}' created successfully.")
    except sqlite3.IntegrityError:
        print(f"Error: User '{username}' already exists.")
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        conn.close()

def find_user_by_username(username):
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    user = None
    try:
        # Using a prepared statement for SELECT query
        cursor.execute("SELECT id, username FROM users WHERE username = ?", (username,))
        user = cursor.fetchone()
        if user:
            print(f"Found user: ID={user[0]}, Username={user[1]}")
        else:
            print(f"User '{username}' not found.")
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        conn.close()
        return user

# --- Demonstrating Usage ---
# Safe usage
create_user("alice", "secure_hash_123")
create_user("bob", "another_hash_456")
find_user_by_username("alice")

# Attempting SQL Injection (will be safely handled by parameterized query)
# The string "' OR '1'='1" will be treated as part of the username, not executed as SQL.
find_user_by_username("' OR '1'='1")

# Clean up (optional)
# conn = sqlite3.connect('users.db')
# cursor = conn.cursor()
# cursor.execute("DROP TABLE IF EXISTS users")
# conn.commit()
# conn.close()
How it works: This Python snippet demonstrates how to prevent SQL Injection by using prepared statements with parameterized queries. Instead of concatenating user input directly into SQL strings, placeholders (`?`) are used. The database driver then separates the SQL command from the user-provided data, ensuring that malicious input (like `' OR '1'='1'`) is treated as a literal value rather than executable SQL code, thus protecting the database.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs