mysql工具和sql注入问题

激活版, 下载地址

  • 几乎所有的SQL语句,通过鼠标点点点的方式实现。
  • 模型功能,表与表之间的关系很形象。
  • 视图功能,SQL语句自动补全,局部执行功能很太实用

Pymysql模块

  • pymysql模块是第三方模块,提供python连接并操作MySQL数据库的功能。通过pip下载。
  • 通过cursor对象执行sql语句查询和查询结果的显示。
  • cursor.excute()的返回结果是sql语句影响的条数
  • cursor.fetchone\fetchmany\fetchall()获取查询结果
  • cursor.scroll()回滚光标的位置。支持相对模式relative和绝对模式absolute
  • 其实,查询结果都保存在_rows中(元组或列表),fetch和scroll只是修改在_rows中取值的索引
import pymysql

conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    password='123456',
    database='day48',
    charset='utf8'
)

cursor = conn.cursor(pymysql.cursors.DictCursor)   
# 数据展现的格式,默认是元组的形式(仅有数据),此时指定为字典的形式,即可以看得见字段名和数据

sql = 'select * from student;'

res = cursor.execute(sql)       # 返回受影响的条数

# print(cursor._rows)           # 保存了所有的数据

print(cursor.fetchone())        # 取出一个数据
print(cursor.fetchmany(2))      # 取出多个数据
print(cursor.fetchall())        # 取数所有数据

cursor.scroll(-4, mode='relative')
print(cursor.fetchmany(2))

sql注入

利用sql语句注释或其他逻辑漏洞,书写一些特点的语句实现固定的语法。比如,对登录校验的sql注入

# --后面的内容注释了
select * from user where name='jason' -- jhsadklsajdkla' and password=''

# or 后面逻辑判断肯定为真
select * from user where name='xxx' or 1=1 -- sakjdkljakldjasl' and password=''

解决办法:敏感的数据不要自己拼接sql语句,交给execute帮你拼接即可。

# 比如登录校验
...
cursor = conn.cursor()

username = input('>>>:')
password = input('>>>:')

sql = "select * from user where name=%s and password=%s"
# 不要手动拼接数据 先用%s占位 之后将需要拼接的数据直接交给execute方法即可

rows = cursor.execute(sql, (username, password))  
# 自动识别sql里面的%s用后面元组里面的数据替换

if rows:
    print('登录成功')
    print(cursor.fetchall())
else:
    print('用户名密码错误')

补充

# execute 自动传参,占位符问题

def execute(self, query, args=None):
        """Execute a query

        :param str query: Query to execute.

        :param args: parameters used with query. (optional)
        :type args: tuple, list or dict

        :return: Number of affected rows
        :rtype: int

        If args is a list or tuple, %s can be used as a placeholder in the query.
        If args is a dict, %(name)s can be used as a placeholder in the query.
        """

pymysql针对增删改的操作

  • pymysql针对数据的增删改的操作,需要二次确认操作,才可以真正的修改数据库。

    sql = 'insert into student(gender, class_id, sname) values("男", 1, "哈哈")'
    effet_row = cursor.execute(sql)
    conn.commit()	# 需要确认一次
    
  • 如果嫌conn.commit()麻烦,可以直接在实例化conn对象的时候,加一个参数autocommit=True

    conn = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        passwd='123456',
        db='day48',
        charset='utf8',
        autocommit=True
    )
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    sql = 'insert into student(gender, class_id, sname)'values("男", 1, "哈哈")'
    effet_row = cursor.execute(sql) # 直接就修改数据库了
    
  • 补充:如果批处理操作数据,可以使用executemany

    cursor = conn.cursor(pymysql.cursors.DictCursor)
    sql = 'insert into student(gender, class_id, sname)values(%s, %s, %s)'
    item_list = [('男', 1, 's1'), ('男', 2, 's2'), ('女', 1, 's3'),]
    
    effet_row = cursor.executemany(sql, args=item_list) # 传一个列表
    print(effet_row)
    

pymysql调用存储过程

  • 通过接口cursor.callproc(self, procname, args=())
  • 可以通过cursor.execute('select @_p1_2;')查看out类型的参数
import pymysql


conn = pymysql.connect(
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    passwd = '123456',
    db = 'day48',
    charset = 'utf8',
    autocommit = True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# 调用存储过程
cursor.callproc('p1',(1,5,10))
"""
@_p1_0=1
@_p1_1=5
@_p1_2=10
"""
# print(cursor.fetchall())
cursor.execute('select @_p1_2;')
print(cursor.fetchall())

pymysql开启事务

  • 异常捕获
  • 回滚操作,conn.rollback()
  • 没有因此常时,事务提交 conn.commit()
try:
    cursor.execute(sql_1)
    cursor.execute(sql_2)
    cursor.execute(sql_3)
except Exception as e:
    conn.rollback()		 # 事务回滚
    print('事务处理失败', e)
else:
    conn.commit() # 事务提交
    print('事务处理成功', cursor.rowcount)# 关闭连接
    cursor.close()
    conn.close()
posted @ 2020-05-07 15:15  the3times  阅读(241)  评论(0)    收藏  举报