1 什么是SQL注入?

用户提交带有恶意的数据与SQL语句进行字符串方式的拼接,从而影响了SQL语句的语义,最终产生数据泄露的现象

  1. # 执行SQL语句,
  2. sql = "select * from students where name='%s';" % "小明' or 1 or '"
  3. print(sql) # select * from students where name='小明' or 1 or '';
  4. cursor.execute(sql)
  5. # 获取查询结果
  6. ret = cursor.fetchall()
  7. for row in ret:
  8. print(row)

这样会把所有的数据都查出来

2 如何防止SQL注入?

解决方案: SQL语句参数化

  • SQL语言中的参数使用%s来占位,此处不是python中的字符串格式化操作
  • 将SQL语句中%s占位所需要的参数存在一个列表中,把参数列表传递给execute方法中第二个参数
    1. # 准备SQL语句, %s是SQL语句的参数占位符, 防止注入
    2. sql = "select * from students where name=%s;"
    3. try:
    4. # 执行SQL语句
    5. cursor.execute(sql, ("小明' or 1 or '",))
    6. # 获取查询结果
    7. ret = cursor.fetchall()
    8. for row in ret:
    9. print(row)
    10. # 查询时最好也commit, 不然用Navicat改了数据, 这里再查, 还显示之前的
    11. db.commit()
    12. except:
    13. db.rollback()
    啥都没查到

    3 多个参数防注入

    1. # 准备SQL语句
    2. sql = "insert students(name, age, gender) values(%s, %s, %s);"
    3. try:
    4. # 执行SQL语句
    5. cursor.execute(sql, ("吴青峰", 35, "男"))
    6. # (添加,删除,修改后)要提交修改到数据库
    7. db.commit()
    8. except:
    9. # 对修改的数据进行撤销
    10. db.rollback()

    4 动态数据插入

    1. data = {
    2. 'id': '1',
    3. 'name': 'zengsf',
    4. 'age': 20
    5. }
    6. table = 'students'
    7. #获取到一个以键且为逗号分隔的字符串,返回一个字符串
    8. keys = ', '.join(data.keys())
    9. values = ', '.join(['%s'] * len(data))
    10. sql = 'INSERT {table}({keys}) VALUES ({values})'.format(table=table, keys=keys, values=values)
    11. try:
    12. #这里的第二个参数传入的要是一个元组
    13. if cursor.execute(sql, tuple(data.values())):
    14. print('Successful')
    15. db.commit()
    16. except:
    17. print('Failed')
    18. db.rollback()
    19. db.close()