Python阵营有很多操作数据库的开源库(安装pip后,可以借助”pip search mysql”查看可用的库列表),其中被使用最多的无疑是MySQLdb,这个库简单易上手。其偏底层的特性为开发者提供灵活性的同时,也对不少新手写出的DB操作代码提出了考验,因为它只支持raw sql,容易导致sql注入攻击。
鉴于此,很多库提供了ORM接口能力,借助OO思想,数据库中的表被映射为Python的类,类的对象代表数据表中的一行记录,所有的DB操作都通过对象方法调用来实现,这些调用在底层被自动转换成SQL语句,在转换过程中,通常会采用parameter bind的方式保证生成的parameterized SQL不存在被注入的风险。
SQLAlchemy就是这样一个具备ORM能力的DB操作Python库,此外,该库还支持开发者执行raw sql,并通过其提供的text对象实现params binding,从而防护SQL注入风险。
备注1:PHP中的DB操作库(如PDO或MySQLi)支持的prepare/bind_param接口也是业界推荐的预防sql injection的方法,而escape_string只能对单/双引号等特殊字符做简单的替换,它并不能保证防御所有的危险字符。
备注2:SQLAlchemy的官方文档比较多,其架构细节可以参考SQLAlchemy at Architecture of Open Source Applications这篇文章,相信对初学者有不小的帮助。
下面的代码示例用来说明如何借助SQLAlchemy的parameters bind能力来写出能防止sql注入的raw sql。
前提假设
假设我们实现了一个简单的sqlalchemy封装类(dbutil.py),代码如下: