Flask 使用 SQLAlchemy 如何防止 SQL 注入攻击使用参数化查询

文章导读
在 Flask 中使用 SQLAlchemy 防止 SQL 注入的核心在于避免字符串拼接,转而使用 ORM 自带的参数化查询机制。对于常规查询,应直接使用 model.query.filter() 或 filter() 方法,SQLAlchemy 会自动处理参数绑定。若必须使用原生 SQL,需通过 text() 函数配合命名占位符(如 :username)及参数字典传递数据,严禁使用 f-stri
📋 目录
  1. A Python 编写 Flask API 如何防止 SQL 注入_使用参数化查询与 ORM 安全防护
  2. B Flask 防止 SQL 注入_SQLAlchemy 参数化绑定与安全查询规范
  3. C 【Web 安全与防护】第 5 章 Flask 防御 SQL 注入
  4. D Flask 防止注入的具体代码示例
  5. E FAQ
A A

在 Flask 中使用 SQLAlchemy 防止 SQL 注入的核心在于避免字符串拼接,转而使用 ORM 自带的参数化查询机制。对于常规查询,应直接使用 model.query.filter() 或 filter() 方法,SQLAlchemy 会自动处理参数绑定。若必须使用原生 SQL,需通过 text() 函数配合命名占位符(如 :username)及参数字典传递数据,严禁使用 f-string 或 format() 拼接变量。此外,动态表名或字段名无法参数化,必须通过白名单校验确保合法性,从而从根本上隔离数据与代码,防止恶意注入。

Python 编写 Flask API 如何防止 SQL 注入_使用参数化查询与 ORM 安全防护

拼接字符串执行 SQL 必出安全问题,因攻击者可注入恶意代码;必须用参数化查询分离数据与语句,sqlite3 用?或:name,psycopg2 用%s 或%(key)s,表名等动态部分需白名单校验。Flask 中用 sqlite3 或 psycopg2 执行 SQL 时,为什么拼接字符串必出问题 直接用 f"SELECT * FROM users WHERE id = {user_id}"或"SELECT * FROM users WHERE name = '" + name + "'",等于把数据库的钥匙塞给前端。哪怕 user_id 看着是数字,攻击者也能传 1 OR 1=1 --进来,绕过条件、拖库、删表。根本原因不是“没过滤”,而是 SQL 解析器会把拼进去的字符串当语句一部分执行——参数化查询强制让数据和语句分离,数据库只把占位符当值处理,不重新编译语法。

Flask 防止 SQL 注入_SQLAlchemy 参数化绑定与安全查询规范

SQLAlchemy 的 query() 和 filter() 默认通过参数化绑定防 SQL 注入,但动态字段名、表名等元信息需白名单校验;text() 必须用:placeholder+ 字典传参,禁用字符串拼接。SQLAlchemy 的 query() 和 filter() 默认不防 SQL 注入?不是“默认防”,而是——只要不用字符串拼接,就天然免疫。很多人误以为 filter() 里写 name == request.args.get('q') 就安全,其实它只是把值当 Python 对象传给 SQLAlchemy,底层走参数化绑定 (如 WHERE name = %s),不会拼进 SQL 字符串。但一旦你用 f"name LIKE '%{q}%'"或 text("SELECT * FROM user WHERE name = '" + q + "'"),防线立刻崩溃。

【Web 安全与防护】第 5 章 Flask 防御 SQL 注入

二、使用参数化查询 如果必须使用原生 SQL,务必使用参数化查询。1. 使用 SQLAlchemy 的参数化查询 fromsqlalchemyimporttext@app.route('/search')defsearch():query=request.args.get('q','')# 参数化查询 result=db.session.execute(text("SELECT * FROM user WHERE username = :username"),{"username":query}).fetchall()returnstr(result) AI 写代码 python 运行 1 2 3 4 5 6 7 8 9 10 11 2. 使用其他数据库驱动 (如 psycopg2) importpsycopg2@app.route('/search')defsearch():query=request.args.get('q','')conn=psycopg2.connect("dbname=test user=postgres password=secret")cursor=conn.cursor()# 参数化查询 cursor.execute("SELECT * FROM user WHERE username = %s",(query,))result=cursor.fetchall()returnstr(result) AI 写代码 python 运行 1 2

Flask 防止注入的具体代码示例

以下是一个使用 Flask-SQLAlchemy 进行参数化查询以防止 SQL 注入的示例代码:【python】fromflask import Flask, request, jsonify fromflask_sqlalchemy import SQLAlchemy fromwerkzeug.security importgenerate_password_hash, check_password_hash app=Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///example.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False db=SQLAlchemy(app) classUser(db.Model): id=db.Column(db.Integer, primary_key=True) username=db.Column(db.String(80), unique=True, nullable=False) password=db.Column(db.String(200), nullable=False) def __repr__(self): returnf'' @app.route('/register', methods=['POST']) def register(): data=request.get_json() username=data.get('username') password=generate_password_hash(data.get('password')) new_user=User(username=username, password=password) db.session.add(new_user) db.session.commit() returnjsonify({'message':'User registered successfully'}),201

Flask 使用 SQLAlchemy 如何防止 SQL 注入攻击使用参数化查询

FAQ

SQLAlchemy 的 filter 方法是否默认安全?

是的,只要不使用字符串拼接,filter 方法会将值作为 Python 对象传递,底层走参数化绑定,天然免疫 SQL 注入。

使用 text() 执行原生 SQL 时如何传参?

必须使用命名占位符(如 :username)配合字典传参,例如 text("SELECT * FROM user WHERE username = :username"), {"username": query},严禁直接拼接变量。