pymysql的使用及sql注入
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 pymysql
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()
# 注意%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
请输入密码:123
sql语句: select * from userinfo where username='helln' and password='123'
返回记录数: 1
登陆成功
输入错误时
```
请输入用户名:helln
请输入密码:234
sql语句: select * from userinfo where username='helln' and password='234'
返回记录数: 0
登录失败
<br>
## sql注入
sql注入有两种形式:用户名存在绕过密码、用户不存在绕过用户名和密码
### 用户名存在绕过密码
格式
存在的用户名' -- 任意字符
或者
存在的用户名' #任意字符
<br>
测试'--
请输入用户名:helln' -- skdjfskdf
请输入密码:sdf
sql语句: select * from userinfo where username='helln' -- skdjfskdf' and password='sdf'
返回记录数: 1
登陆成功
![](https://img2018.cnblogs.com/blog/1542801/201904/1542801-20190406203845450-1859590627.png)
<br>
测试' #
请输入用户名:helln' #lsjefls
请输入密码:woieurweio
sql语句: select * from userinfo where username='helln' #lsjefls' and password='woieurweio'
返回记录数: 1
登陆成功
![](https://img2018.cnblogs.com/blog/1542801/201904/1542801-20190406203917915-1917128048.png)
在navicat中可以看到-- 和#后面的都被注释掉了,所以只有username='helln'起作用,自然也就能够查询到结果
<br>
### 用户名不存在,绕过用户名和密码
格式
任意用户名' or 1=1 -- 任意字符
或者
任意用户名' or 1=1 #任意字符
或者
任意用户名' or '任意字符'='任意字符
<br>
注意:
- 用户名后面有一个单引号
- or前后都有空格
- 必须保证等式成立
<br>
测试
请输入用户名:sfhgk' or 1=1 -- sfjeor
请输入密码:vnxlngf' or 2=2 #sdfwer
sql语句: select * from userinfo where username='sfhgk' or 1=1 -- sfjeor' and password='vnxlngf' or 2=2 #sdfwer'
返回记录数: 1
登陆成功
<b><font color='#ff0000'>sql注入的本质是(通过注释)构造恒为真的表达式绕过验证</font></b>
<br>
## 解决办法
原来我们是用字符串拼接做的
```python
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 pymysql
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 = "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)
#一定记得commit
conn.commit()
# 关闭连接,游标和连接都要关闭
cursor.close()
conn.close()
#判断结果
if result:
print('ok')
else:
print('error')
### 改
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#导入模块
import pymysql
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 = "update userinfo set username = %s where id = '8'"
print('sql语句:',sql)
3.执行sql语句,返回sql查询成功的记录数
修改一条数据
result = cursor.execute(sql,user)
print('返回记录数:',result)
一定记得commit
conn.commit()
关闭连接,游标和连接都要关闭
cursor.close()
conn.close()
判断结果
if result:
print('ok')
else:
print('error')
<br>
### 删
```python
#!/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)
#一定记得commit
conn.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示例中,在获取行数据的时候,可以理解开始的时候,有一个行指针指着第一行的上方,获取一行,它就向下移动一行,所以当行指针到最后一行的时候,就不能再获取到行的内容,所以我们可以使用如下方法来移动行指针:
```python
cursor.scroll(1,mode='relative') # 相对当前位置移动,整数向下移动,负数向上移动
cursor.scroll(2,mode='absolute') # 相对绝对位置移动
```
fetchall(): 获取所有数据,返回值是元组套元组
```python
#导入模块
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()
默认情况下,我们获取到的返回值是元组,只能看到每行的数据,却不知道每一列代表的是什么,这个时候可以使用以下方式来返回字典,每一行的数据都会生成一个字典:
```python
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) #在实例化的时候,将属性cursor设置为pymysql.cursors.DictCursor
fetchmany(): 获取多行记录,括号内的参数为获取的行数
```python
#导入模块
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()
pymysql的使用及sql注入的更多相关文章
- MySQL 之Navicat Premium 12安装使用、pymysql模块使用、sql注入问题的产生与解决
本文内容提要: Navicat Premium 12 的介绍.使用. pymysql模块的使用 sql注入问题的产生与解决 -------------------------------------- ...
- MySQL— pymysql模块(防止sql注入),可视化软件Navicat
一.Pymysql import pymysql #python2.X 中是 mysqldb 和 pythonmysql 用法是一模一样的 #pymysql可以伪装成上面这两个模块 user = in ...
- pymysql 解决 sql 注入问题
1. SQL 注入 SQL 注入是非常常见的一种网络攻击方式,主要是通过参数来让 mysql 执行 sql 语句时进行预期之外的操作. 即:因为传入的参数改变SQL的语义,变成了其他命令,从而操作了数 ...
- Navicat工具、pymysql模块 sql注入
cls超 Navicat工具.pymysql模块 阅读目录 一 IDE工具介绍 二 pymysql模块 一 IDE工具介绍(Navicat) 生产环境还是推荐使用mysql命令行,但为了方便我们测试, ...
- 第二百八十一节,MySQL数据库-SQL注入和pymysql模块防止SQL注入
MySQL数据库-SQL注入和pymysql模块防止SQL注入 SQL注入就是通过SQL语句绕开程序判断,获取到数据库的内容 下面以一个简单的程序登录SQL注入举例: 正常登录 1.数据库有一张会员表 ...
- PyMySQL防止SQL注入
一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体 ...
- MySQL-注释-Navicat基本使用-复杂查询练习题-解题思路-pymysql操作数据库-SQL注入-05
目录 mysql语句注释 navicat 的基本使用 特色(个人总结) 与数据服务器建立连接 创建&打开数据库.表 创建 打开 修改操作表结构 修改表结构 查询修改操作表数据 基本语句对应的操 ...
- python连接MySQL pymysql模块,游标,SQL注入问题,增删改查操作
pymysql模块 pymysql是用python控制终端对MySQL数据库进行操作的第三方模块 import pymysql # 1.连接数据库 client = pymysql.connect( ...
- 数据库——可视化工具Navicat、pymysql模块、sql注入问题
数据库--可视化工具Navicat.pymysql模块.sql注入问题 Navicat可视化工具 Navicat是数据库的一个可视化工具,可直接在百度搜索下载安装,它可以通过鼠标"点点点&q ...
随机推荐
- Linux之Samba部署
1.Samba介绍 Samba 是在 Linux 和 UNIX 系统上实现 SMB 协议的一个免费软件,由服务器及客户端程序构成,SMB(Server Messages Block,信息服务块)是一种 ...
- Vue学习之路1-集成环境安装
1.前言 Vue 是一款友好的.多用途且高性能的javascript框架,与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用,它能够帮你创建可维护性和可测试性更强的代码库,Vue是渐进式的j ...
- 我的第一个python web开发框架(31)——定制ORM(七)
几个复杂的ORM方式都已介绍完了,剩下一些常用的删除.获取记录数量.统计合计数.获取最大值.获取最小值等方法我就不一一详细介绍了,直接给出代码大家自行查看. #!/usr/bin/env python ...
- Docker(2):使用Dockerfile创建支持SSH服务的镜像
1.创建工作目录 # mkdir sshd_ubuntu # ls 在其中,创建Dockerfile和run.sh文件 # cd sshd_ubuntu/ # touch Dockerfile run ...
- python之json模块
#!/usr/bin/python # -*- coding: UTF- -*- ''' )序列化相关 json pickle (序列化是指将) 序列化是指将一个字符串转换成基础数据类型或者基础数据类 ...
- 【Swift 3.0】iOS 国际化切换语言
有的 App 可能有切换语言的选项,结合系统自动切换最简单的办法: fileprivate var localizedBundle: Bundle = { return Bundle(path: Bu ...
- python多线程和多进程
1 概念梳理: 1.1 线程 1.1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发 ...
- C#中的IntPtr
IntPtr是一个类,用于包装调用WindowsAPI函数的指针,根据平台的不同,底层指针可以是32位或64位:它用以表示指针或句柄的平台特定类型,C#中主要用它调用C++\C封装的DLl库:下面主要 ...
- SpringCloud-Eureka服务注册与发现(二)
SpringCloud-Eureka服务注册与发现(二) https://www.cnblogs.com/qdhxhz/p/9357502.html https://blog.csdn.net/wei ...
- 三、数据API-3
预备 返回格式需要包括: // Code 状态码(200,400等) // Msg 提示信息(邮箱格式不正确:数据返回成功等) // Result 返回数据 一.WebAPI与传统MVC的区别是 MV ...