SQLAlchemy中的可选参数

时间:2017-12-21 19:44:35

标签: python flask sqlalchemy prepared-statement flask-sqlalchemy

我有一个在SQLAlchemy中执行的原始SQL,可选参数来自查询字符串。

我做了一个函数来构建where子句的句子:

def queryParams(self, params):
    params = urllib.parse.parse_qs(params)
    query = ""
    for (key, val) in params.items():
        for value in val:
            if(re.match("/(\d+(\.\d+)?)/", value) != False or (value == "false" or value == "true")):
                query += ' AND ' + key + ' = ' + value
            else:
                query += ' AND ' + key + ' = ' + "'" + value + "'"

    return query

问题是当我需要执行查询时,我必须将其连接到SQL字符串,这对于SQL注入发生并不好。

    s = text(
        'select a.cod_lim_judicial, a.desc_lim_judicial, a.dt_lim_judicial, '
        'a.dt_validade, a.nr_mandado, a.tipo_liminar, a.folhas_incidencia, '
        'a.num_folha, a.mes_ano_folha, p.mat_servidor, p.cod_depend, a.perc_pa '
        'from folha.fl_liminar a, folha.fl_pens_x_liminar p '
        'where a.cod_lim_judicial = p.cod_lim_judicial (+)' + self.queryParams(parameters))
    result = conn.execute(s).fetchall()

如何使用预准备语句使用可选参数?

感谢提前!

1 个答案:

答案 0 :(得分:0)

以下是您可以做的一些简化示例:

In [42]: def queryParams(params):
    ...:     params = urllib.parse.parse_qs(params)
    ...:     for key, val in params.items():
    ...:         # Trust the implicit conversions:
    ...:         # https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/Data-Type-Comparison-Rules.html#GUID-6DB331B5-0F34-4215-9A20-16AEA9D7FF4B
    ...:         yield column(key) == val
    ...: 

使用column()句柄引用保留字和大小写混合,并在列名中转义坏字符,但您仍应该将白名单列入白名单。该比较生成一个二进制SQL表达式对象,其绑定参数为val。您可以合并Core constructs with text fragments以生成查询:

In [43]: params = 'asdf=1&qwer=true&foo=baz'

In [44]: s = select([text("""
    ...:         a.cod_lim_judicial, a.desc_lim_judicial, a.dt_lim_judicial,
    ...:         a.dt_validade, a.nr_mandado, a.tipo_liminar, a.folhas_incidencia,
    ...:         a.num_folha, a.mes_ano_folha, p.mat_servidor, p.cod_depend, a.perc_pa""")]).\
    ...:     select_from(
    ...:         outerjoin(
    ...:             text("folha.fl_liminar a"),
    ...:             text("folha.fl_pens_x_liminar p"),
    ...:             text("a.cod_lim_judicial = p.cod_lim_judicial"))).\
    ...:     where(and_(*queryParams(params)))
    ...: 


In [45]: print(s)
SELECT 
        a.cod_lim_judicial, a.desc_lim_judicial, a.dt_lim_judicial,
        a.dt_validade, a.nr_mandado, a.tipo_liminar, a.folhas_incidencia,
        a.num_folha, a.mes_ano_folha, p.mat_servidor, p.cod_depend, a.perc_pa 
FROM folha.fl_liminar a LEFT OUTER JOIN folha.fl_pens_x_liminar p ON a.cod_lim_judicial = p.cod_lim_judicial 
WHERE asdf = :asdf_1 AND qwer = :qwer_1 AND foo = :foo_1