Flask+SQLAlchemy+SQLite3数据库搜索防SQL注入的代码改造方案咨询
防范SQL注入的改造方案
针对你的场景,核心要解决两个SQL注入风险点:用户可控的字段名和用户输入的搜索内容。下面结合你的Flask-SQLAlchemy模型和表单,给出具体的改造步骤和代码:
1. 先做字段名的白名单验证
因为SQL参数化查询无法参数化字段名(比如WHERE {column} LIKE ...里的column),所以必须先验证用户选择的字段是否是你预先定义的合法字段,避免恶意字段名注入。
首先,基于你的My_library模型,定义一个允许搜索的字段白名单:
ALLOWED_SEARCH_FIELDS = { "title", "authors", "published_date", "isbn_or_identifier", "language" }
2. 使用Flask-SQLAlchemy ORM构建安全查询
直接使用ORM的查询API,既能避免手动拼接SQL,又能自动处理参数化,比原生text语句更简洁安全。
改造你的搜索函数:
# 假设你已经初始化了db,比如db = SQLAlchemy(app) def search_in_database(column, searched_data): # 第一步:验证字段是否在白名单内 if column not in ALLOWED_SEARCH_FIELDS: raise ValueError("Invalid search field") # 第二步:获取模型对应的字段对象 model_field = getattr(My_library, column) # 第三步:构建模糊查询,使用ORM的like方法,参数化搜索内容 query = My_library.query.filter(model_field.like(f"%{searched_data}%")) # 获取结果,返回id列表 return [item.id for item in query.all()]
为什么这样安全?
- 字段名通过白名单验证,只有你允许的字段才能被查询,杜绝了
column参数的注入(比如用户传入title; DROP TABLE...会被直接拦截)。 - 搜索内容的
like查询由SQLAlchemy自动参数化,searched_data里的特殊字符(比如'、;)会被自动转义,不会被解析为SQL语句的一部分。
3. 结合搜索表单优化用户输入处理
你现有的表单是用于添加记录的,建议新增一个专门的搜索表单,让用户直观选择字段和输入内容:
from flask_wtf import FlaskForm from wtforms import SelectField, StringField, SubmitField from wtforms.validators import DataRequired class SearchForm(FlaskForm): # 下拉框列出允许搜索的字段,对应白名单 search_field = SelectField( "Search by", choices=[ ("title", "Title"), ("authors", "Authors"), ("published_date", "Published Date"), ("isbn_or_identifier", "ISBN"), ("language", "Language") ], validators=[DataRequired()] ) search_content = StringField("Search content", validators=[DataRequired()]) submit = SubmitField("Search")
然后在视图函数里处理表单提交:
@app.route("/search", methods=["GET", "POST"]) def search(): form = SearchForm() results = [] if form.validate_on_submit(): try: results = search_in_database(form.search_field.data, form.search_content.data) except ValueError as e: # 处理非法字段的情况,比如返回错误提示 flash(str(e)) return render_template("search.html", form=form, results=results)
4. 额外的安全建议
- 保持你现有的表单验证逻辑,比如对
published_date、isbn_or_identifier等字段做类型验证,进一步过滤非法输入。 - 绝对避免直接把用户输入的内容拼接到SQL语句中(不管是字段名还是值),始终依赖ORM或参数化查询。
- 可以给数据库用户配置最小权限(比如只允许SELECT操作),即使发生意外注入,也能降低破坏程度。
内容的提问来源于stack exchange,提问作者Golab368
相关产品推荐
相关产品推荐

