You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask+WTForms构建SQLite查询:ORDER BY下拉选项失效问题

这个问题我之前也碰到过!核心原因是SQL参数化查询的设计限制:SQLite(其实大部分数据库都是这样)的参数绑定只能用来传递数据值,不能用来传递列名、表名这类SQL标识符。

你现在的代码里把order_by作为参数传给execute(),SQL会把它当成一个字符串字面量来处理。比如当用户选择"name"排序时,实际执行的SQL是:

SELECT * FROM supplementInfo WHERE (name) LIKE (?) OR (brand) LIKE (?) ORDER BY 'name'

这里的'name'是一个固定字符串,所有行的这个"值"都一样,所以排序根本不会生效。

解决办法:白名单校验+直接拼接合法列名

要解决这个问题,我们需要先验证用户提交的排序字段是我们预先允许的列名(防止SQL注入),然后直接把合法的列名拼到SQL语句中:

  1. 首先定义一个允许的排序列白名单,和你表单里的选项严格对应;
  2. 检查用户提交的orderBy值是否在白名单内,不在的话用默认值兜底;
  3. 把合法的列名直接插入到SQL语句里(注意不要加引号)。

修改后的代码如下:

@app.route('/', methods=('GET', 'POST'))
def index():
    products = get_products()
    form = SearchForm()
    # 定义允许的排序列白名单,和表单的choices完全匹配
    allowed_order_columns = {'name', 'brand', 'price', 'rating'}
    
    if form.validate_on_submit():
        # 校验排序字段,非法值用默认值name代替
        order_by = form.orderBy.data if form.orderBy.data in allowed_order_columns else 'name'
        item = '%' + form.searchFor.data + '%'
        
        # 直接将合法的列名拼入SQL(因为已经做了白名单校验,不会有注入风险)
        c.execute(f"SELECT * FROM supplementInfo WHERE (name) LIKE ? OR (brand) LIKE ? ORDER BY {order_by}", 
                  (item, item))
        search_results = c.fetchall()
        return render_template('index.html', search_results=search_results, form=form)
    else:
        return render_template('index.html', form=form, products=products)

为什么这样安全?

因为我们只允许用户从我们预先定义的列名中选择,即使有人恶意篡改表单提交的值,不在白名单里的内容会被替换成默认值,完全杜绝了SQL注入的风险。

内容的提问来源于stack exchange,提问作者cmrussell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:07:21