博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
pymysql的使用及sql注入
阅读量:7294 次
发布时间:2019-06-30

本文共 5632 字,大约阅读时间需要 18 分钟。

pymysql简介

pymysql是python操纵mysql的一个模块,本质上是一个socket客户端

pymysql使用

准备数据

#创建数据库db2,如果已存在,请忽略CREATE DATABASE db2 DEFAULT CHARACTER SET utf8;#创建用户表CREATE TABLE `userinfo` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',  `username` varchar(20) NOT NULL COMMENT '用户名',  `password` varchar(32) NOT NULL COMMENT '密码',  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';#插入一条数据INSERT INTO `db2`.`userinfo` (`id`, `username`, `password`) VALUES ('1', 'helln', '123');

实现

使用Python实现用户登录,如果用户存在则登录成功(假设该用户已在数据库中)

#导入模块import pymysqluser = input('请输入用户名:')pwd = input('请输入密码:')# 1.连接conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='', db='db2', charset='utf8')# 2.创建游标cursor = conn.cursor()# 注意%s需要加引号sql = "select * from userinfo where username='%s' and password='%s'" % (user, pwd)print('sql语句:',sql)# 3.执行sql语句cursor.execute(sql)result = cursor.execute(sql)  # 执行sql语句,返回sql查询成功的记录数目print('返回记录数:',result)# 关闭连接,游标和连接都要关闭cursor.close()conn.close()if result:    print('登陆成功')else:    print('登录失败')

演示

输入正确用户名和密码

请输入用户名:helln请输入密码:123sql语句: select * from userinfo where username='helln' and password='123'返回记录数: 1登陆成功

输入错误时

请输入用户名:helln请输入密码:234sql语句: select * from userinfo where username='helln' and password='234'返回记录数: 0登录失败

sql注入

sql注入有两种形式:用户名存在绕过密码、用户不存在绕过用户名和密码

用户名存在绕过密码

格式

存在的用户名' -- 任意字符或者存在的用户名' #任意字符

测试'--

请输入用户名:helln' -- skdjfskdf请输入密码:sdfsql语句: select * from userinfo where username='helln' -- skdjfskdf' and password='sdf'返回记录数: 1登陆成功

1542801-20190406203845450-1859590627.png

测试' #

请输入用户名:helln' #lsjefls请输入密码:woieurweiosql语句: select * from userinfo where username='helln' #lsjefls' and password='woieurweio'返回记录数: 1登陆成功

1542801-20190406203917915-1917128048.png

在navicat中可以看到-- 和#后面的都被注释掉了,所以只有username='helln'起作用,自然也就能够查询到结果

用户名不存在,绕过用户名和密码

格式

任意用户名' or 1=1 -- 任意字符或者任意用户名' or 1=1 #任意字符或者任意用户名' or '任意字符'='任意字符

注意:

  • 用户名后面有一个单引号
  • or前后都有空格
  • 必须保证等式成立

测试

请输入用户名:sfhgk' or 1=1 -- sfjeor请输入密码:vnxlngf' or 2=2 #sdfwersql语句: select * from userinfo where username='sfhgk' or 1=1 -- sfjeor' and password='vnxlngf' or 2=2 #sdfwer'返回记录数: 1登陆成功

sql注入的本质是(通过注释)构造恒为真的表达式绕过验证

解决办法

原来我们是用字符串拼接做的

sql="select * from userinfo where name='%s' and password='%s'" %(username,pwd)print(sql)result=cursor.execute(sql)

将上面的语句改为下面这样,注意一定不要再加引号了

#改写为(execute帮我们做字符串拼接,我们无需且一定不能再为%s加引号了)sql="select * from userinfo where name=%s and password=%s" #!!!注意%s需要去掉引号,因为pymysql会自动为我们加上result=cursor.execute(sql,[user,pwd]) #pymysql模块自动帮我们解决sql注入的问题,只要我们按照pymysql的规矩来。

commit()提交

在数据库里增、删、改的时候,必须要进行提交,否则插入的数据不生效。

#导入模块import pymysqluser = input('请输入用户名:')pwd = input('请输入密码:')# 1.连接conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='', db='db2', charset='utf8')# 2.创建游标cursor = conn.cursor()sql = "insert into userinfo(username,password) values (%s,%s)"print('sql语句:',sql)# 3.执行sql语句,返回sql查询成功的记录数#同时插入多条数据result = cursor.executemany(sql,[(user+'1',pwd),(user+'2',pwd)])print('返回记录数:',result)#一定记得commitconn.commit()# 关闭连接,游标和连接都要关闭cursor.close()conn.close()#判断结果if result:    print('ok')else:    print('error')

#!/usr/bin/env python# -*- coding: utf-8 -*-#导入模块import pymysqluser = input('请输入用户名:')pwd = input('请输入密码:')# 1.连接conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='', db='db2', charset='utf8')# 2.创建游标cursor = conn.cursor()sql = "update userinfo set username = %s  where id = '8'"print('sql语句:',sql)# 3.执行sql语句,返回sql查询成功的记录数#修改一条数据result = cursor.execute(sql,user)print('返回记录数:',result)#一定记得commitconn.commit()# 关闭连接,游标和连接都要关闭cursor.close()conn.close()#判断结果if result:    print('ok')else:    print('error')

#!/usr/bin/env python# -*- coding: utf-8 -*-#导入模块import pymysql#删除不需要执行这2个input了# user = input('请输入用户名:')# pwd = input('请输入密码:')# 1.连接conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', password='', db='db2', charset='utf8')# 2.创建游标cursor = conn.cursor()sql = "delete from userinfo  where id = '2'"print('sql语句:',sql)# 3.执行sql语句,返回sql查询成功的记录数#删除一条数据result = cursor.execute(sql)print('返回记录数:',result)#一定记得commitconn.commit()# 关闭连接,游标和连接都要关闭cursor.close()conn.close()#判断结果if result:    print('ok')else:    print('error')

查有三种:fetchone()fetchall()fetchmany

fetchone():获取下一行数据(第一次使用时是首行),返回值是一个元组

#导入模块import pymysql# 1.连接conn = pymysql.connect(host='localhost', port=3306, user='root', password='', db='db2', charset='utf8')# 2.创建游标cursor = conn.cursor()sql = 'select * from userinfo'cursor.execute(sql)# 查询第一行的数据row = cursor.fetchone()print(row) # (1, 'helln', '123')# 查询第二行数据row = cursor.fetchone()print(row) # (6, 'sophia', '123')# 4.关闭游标cursor.close()# 5.关闭连接conn.close()

在fetchone示例中,在获取行数据的时候,可以理解开始的时候,有一个行指针指着第一行的上方,获取一行,它就向下移动一行,所以当行指针到最后一行的时候,就不能再获取到行的内容,所以我们可以使用如下方法来移动行指针:

cursor.scroll(1,mode='relative')  # 相对当前位置移动,整数向下移动,负数向上移动cursor.scroll(2,mode='absolute') # 相对绝对位置移动

fetchall(): 获取所有数据,返回值是元组套元组

#导入模块import pymysql# 1.连接conn = pymysql.connect(host='localhost', port=3306, user='root', password='', db='db2', charset='utf8')# 2.创建游标cursor = conn.cursor()sql = 'select * from userinfo'cursor.execute(sql)# 获取所有的数据rows = cursor.fetchall()print(rows)# 4.关闭游标cursor.close()# 5.关闭连接conn.close()

默认情况下,我们获取到的返回值是元组,只能看到每行的数据,却不知道每一列代表的是什么,这个时候可以使用以下方式来返回字典,每一行的数据都会生成一个字典:

cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)  #在实例化的时候,将属性cursor设置为pymysql.cursors.DictCursor

fetchmany(): 获取多行记录,括号内的参数为获取的行数

#导入模块import pymysql# 1.连接conn = pymysql.connect(host='localhost', port=3306, user='root', password='', db='db2', charset='utf8')# 2.创建游标cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)sql = 'select * from userinfo'cursor.execute(sql)# 获取2条数据rows = cursor.fetchmany(2)print(rows)# 4.关闭游标cursor.close()# 5.关闭连接conn.close()

转载于:https://www.cnblogs.com/zzliu/p/10662720.html

你可能感兴趣的文章
IDEA github
查看>>
linux 驱动学习笔记05--文件系统与设备文件系统
查看>>
unresolved external symbol __forceAtlDllManifest错误的解决
查看>>
Linux的.run文件简单制作
查看>>
ubuntu解压命令(转)
查看>>
C#获取获取北京时间多种方法
查看>>
动态语言的灵活性是把双刃剑 -- 以 Python 语言为例
查看>>
1. 字节序的转换
查看>>
ubuntu14.04LTS下ECLIPSE+JAVA搭建
查看>>
学习RxJS: 导入
查看>>
PowerDesigner大小写转换
查看>>
纯 CSS 利用 label + input 实现选项卡
查看>>
Ubuntu 上安装R
查看>>
How .Net code can call unmanaged code?
查看>>
Archlinux安装配置以及遇到的问题
查看>>
怎么写出好代码——坏味道
查看>>
Java将CST的时间字符串转换成需要的日期格式字符串
查看>>
cisco 查看接口进出流量
查看>>
Dhcp+nfs+tftp+ks 完全无人值守安装linux操作系统
查看>>
TemplateDirectiveModel接口execute方法参数说明
查看>>