導入A. IDEツール(Navicatは)
私たちは、Navicatのツールを使用し、本番環境はmysqlコマンドラインを使用することをお勧めしますが、我々のテストの便宜のために、あなたはIDEツールを使用することができ、このツールは、MySQLサーバを接続するためのソケットクライアント、ツールの可視化は、本質的である、と彼はグラフィカルインターフェイスバージョンですA。私たちは、LinuxとWindowsオペレーティングシステムの起動との間で同様の違いの違いを使用して、コマンドラインで直接それを使用しています。
ダウンロードリンクします。https://pan.baidu.com/s/1bpo5mqj
このブログを読んNavicatのインストールチュートリアル:https://www.cnblogs.com/clschao/articles/10022040.html
掌握:
# 1. 测试+链接数据库
# 2. 新建库
# 3. 新建表,新建字段+类型+约束
# 4. 设计表: 外键
# 5. 新建查询
# 6. 备份库/表
# 注意:
批量加注释: ctrl + ? 键
批量去注释: ctrl + shift + ? 键
二つ。Pymysqlモジュール
1. pymysqlインストール
# 安装
一:
pip3 install pymysql
二:
PyCharm里settings-----> Project Interpreter-----> 右上角的加号+ ------> 搜索框里搜索
2. Pythonのデータベース接続
import pymysql
# 打开数据库连接
conn = pymysql.connect('数据库ip','用户账号','密码','数据库名')
# 使用 cursor() 方法创建一个游标对象 cursor
cursor = conn.cursor()
# 使用 execute() 方法执行 SQL语句
cursor.execute("SQL语句")
# 查询
data = cursor.fetchone() # 查询单行数据
data = cursor.fetchmany(条数) # 查询多行数据
data = cursor.fetchall() # 查询所有的数据
print(data)
# 关闭游标
cursor.close()
# 关闭数据库连接
conn.close()
その他のパラメータ
import pymysql
conn = pymysql.connect(
host='localhost', user='root', password="123",
database='db', port=3306, charset='utf8', # charset时utf8,不能是utf-8
)
cur = conn.cursor(cursor=pymysql.cursors.DictCursor) # 可以把cursor得到的结果集变成[{},{},......]这种列表里套字典形式.fetchall或者fetchmany取出的结果是列表套字典的数据形式,如果fetchmany(1)则取到的结果是一个字典,而不是列表套字典
3.ルックアップテーブル操作
使用される単一のデータを取得するか、複数のデータを取得するために()メソッドはfetchAllするfetchone()メソッドのいずれかを使用してPythonのMySQLのクエリ。
- fetchone():このメソッドは、次のクエリの結果セットを取得します。結果セットが対象です
- fetchAllのは():行返されたすべての結果を受け取ります。
- ROWCOUNT:これは、読み取り専用属性、およびリターン実行が影響を受けた行の数の()メソッドを実行します。
import pymysql
# 建立数据库连接,第一个参数:ip地址,第二个:用户名,第三个:密码,第四个:数据库名
conn = pymysql.connect('127.0.0.1','root','123456','pysql')
# 使用cursor()方法创建一个游标对象 cursor
# cursor = conn.cursor()
cur = conn.cursor(cursor=pymysql.cursors.DictCursor)
# sql代码
sql = 'select * from info;'
# 执行sql语句,返回sql查询成功的记录数目,是个数字,是受sql语句影响到的记录行数,其实除了受影响的记录的条数之外,这些记录的数据也都返回了给游标
row = cursor.execute(sql)
print(cursor.rowcount) # 这是一个只读属性,并返回执行execute()方法后影响的行数
print(row) # 一个数字
# one_data = cursor.fetchone()
# many_data = cursor.fetchmany(3) # 当括号里写1是,得到的是字典
# all_data = cursor.fetchall()
# print(one_data)
# print(many_data)
# print(all_data)
cursor.close() # 关闭游标
conn.close() # 关闭连接
カーソルの移動
我们可以移动游标的位置,继续取我们前面的数据,通过cursor.scroll(数字,模式),第一个参数就是一个int类型的数字,表示往后移动的记录条数,第二个参数为移动的模式,有两个值:absolute:绝对移动,relative:相对移动
#绝对移动:它是相对于所有数据的起始位置开始往后面移动的
#相对移动:他是相对于游标的当前位置开始往后移动的
#绝对移动的演示
#print(cursor.fetchall())
#cursor.scroll(3,'absolute') #从初始位置往后移动三条,那么下次取出的数据为第四条数据
#print(cursor.fetchone())
#相对移动的演示
#print(cursor.fetchone())
#cursor.scroll(1,'relative') #通过上面取了一次数据,游标的位置在第二条的开头,我现在相对移动了1个记录,那么下次再取,取出的是第三条,我相对于上一条,往下移动了一条
#print(cursor.fetchone())
データへ4.操作の追加および削除
データベース接続オブジェクト.commit()の提出、または変更されませんデータベースにしてください。
データの挿入
import pymysql
# 打开数据库连接
conn = pymysql.connect('127.0.0.1','root','123456','pysql')
# 使用cursor()方法获取操作游标
cursor = conn.cursor()
# SQL 插入语句
sql = """ insert into info(username,password) values('zfy','123456'),('lfz','123');"""
try:
cursor.execute(sql) # 执行sql语句
conn.commit() # 提交到数据库执行
except:
conn.rollback() # 如果发生错误则回滚
# 关闭数据库连接
conn.close()
データを削除します。
import pymysql
# 打开数据库连接
conn = pymysql.connect('127.0.0.1','root','123456','pysql')
# 使用cursor()方法获取操作游标
cursor = conn.cursor()
# SQL 删除语句
sql = """ delete from info where id = %s""" # 不要直接字符串拼接,防止sql注入
try:
cursor.execute(sql,[2]) # 执行sql语句,第二个参数:列表里写sql的拼接字符.
conn.commit() # 提交到数据库执行
except:
conn.rollback() # 如果发生错误则回滚
# 关闭数据库连接
conn.close()
データの更新
import pymysql
# 打开数据库连接
conn = pymysql.connect('127.0.0.1','root','123456','pysql')
# 使用cursor()方法获取操作游标
cursor = conn.cursor()
# SQL 更新语句
sql = """ update info set password = 'hahaha' where id = %s """ # 不要直接字符串拼接,防止sql注入
try:
cursor.execute(sql,[3]) # 执行sql语句,第二个参数:列表里写sql的拼接字符.
conn.commit() # 提交到数据库执行
except:
conn.rollback() # 如果发生错误则回滚
# 关闭数据库连接
conn.close()
4.挿入された自己増力IDの最後のデータを取得します。
import pymysql
conn=pymysql.connect(host='localhost',user='root',password='123',database='egon')
cursor=conn.cursor()
sql='insert into userinfo(name,password) values("xxx","123");'
rows=cursor.execute(sql)
print(cursor.lastrowid) #在插入语句后查看
conn.commit()
cursor.close()
conn.close()
5.注入のSQL()を実行し
私たちは、パスワード認証が最初のユーザ名とパスワードをファイルに保存し、クライアントに経由で送信され、ユーザー名とパスワードが一致内のファイルの内容を読み取ることによって、ユーザ名、そして今、我々は、データベースを学ぶ前に、我々はできますデータベースにユーザーデータを保存し、データベース内のクライアントデータ用のユーザー名とパスワードを認証します。
二つのフィールド、ユーザ名、およびパスワードを含む、自身のUserInfoユーザー情報テーブルを作成し、これは2つのレコードを書き込みます
#我们来使用数据来进行一下用户名和密码的认证操作
import pymysql
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='666',
database='crm',
charset='utf8'
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
uname = input('请输入用户名:')
pword = input('请输入密码:')
sql = "select * from userinfo where username='%s' and password='%s';"%(uname,pword)
res = cursor.execute(sql) #res我们说是得到的行数,如果这个行数不为零,说明用户输入的用户名和密码存在,如果为0说名存在,你想想对不
print(res) #如果输入的用户名和密码错误,这个结果为0,如果正确,这个结果为1
if res:
print('登陆成功')
else:
print('用户名和密码错误!')
#通过上面的验证方式,比我们使用文件来保存用户名和密码信息的来进行验证操作要方便很多。
任意の文字列をして、スペースを追加し、正常にログインできるようになり、それが唯一のユーザーの名前を知っている彼は、 - 入力がユーザー名「ボックスに入力してからにする代わりにチャオがあればしかし、私たちは、次の操作を見てあなたは成功した場合にログインできるようになります:
uname = input('请输入用户名:')
pword = input('请输入密码:')
sql = "select * from userinfo where username='%s' and password='%s';"%(uname,pword)
print(sql)
res = cursor.execute(sql) #res我们说是得到的行数,如果这个行数不为零,说明用户输入的用户名和密码存在,如果为0说名存在,你想想对不
print(res) #如果输入的用户名和密码错误,这个结果为0,如果正确,这个结果为1
if res:
print('登陆成功')
else:
print('用户名和密码错误!')
#运行看结果:居然登陆成功
请输入用户名:chao' -- xxx
请输入密码:
select * from userinfo where username='chao' -- xxx' and password='';
1
登陆成功
我们来分析一下:
此时uname这个变量等于什么,等于chao' -- xxx,然后我们来看我们的sql语句被这个字符串替换之后是个什么样子:
select * from userinfo where username='chao' -- xxx' and password=''; 其中chao后面的这个',在进行字符串替换的时候,我们输入的是chao',这个引号和前面的引号组成了一对,然后后面--在sql语句里面是注释的意思,也就是说--后面的sql语句被注释掉了。也就是说,拿到的sql语句是select * from userinfo where username='chao';然后就去自己的数据库里面去执行了,发现能够找到对应的记录,因为有用户名为chao的记录,然后他就登陆成功了,但是其实他连密码都不知道,只知道个用户名。。。,他完美的跳过了你的认证环节。
その後、我々は、ユーザー名とパスワードを直接知っているが、まだ成功してログインすることはできません一度、例を見て:
请输入用户名:xxx' or 1=1 -- xxxxxx
请输入密码:
select * from userinfo where username='xxx' or 1=1 -- xxxxxx' and password='';
3
登陆成功
我们只输入了一个xxx' 加or 加 1=1 加 -- 加任意字符串
看上面被执行的sql语句你就发现了,or 后面跟了一个永远为真的条件,那么即便是username对不上,但是or后面的条件是成立的,也能够登陆成功。
上記の2つの例は、何の感情バック冷たいああ同志が存在しない、上記の2つの例を読んで、二つの問題SQLインジェクションあり、我々はそれを解決する方法を、この問題を解決する必要があり、心配しないのですか?
いくつかの特別なシンボルが実行論理SQLを変更することができますように、一部のサイトが直接あなたがコンテンツを入力すると、それはあなたに限定を与えないで、あなたは、いくつかの特殊記号を入力することはできません、実際には、だけではない - 他の記号がありますまた、実行論理SQL文を変更する、私たちはクライアントのユーザの入力制限を配置するには、このプログラムではありますが、他の人があなたのクライアントが要求を送信するシミュレートすることができ、それが可能である、彼はクライアントを偽装、あなたが従っていませんクライアントの要件は、我々はいくつかの特殊文字を作った、あなたのクライアントが限定されるものではありません。だから、これは単純なフィルタの特殊文字を行う方法を、クライアントの根本的な問題を解決することはできませんでしたか?また、サーバは、コンテンツの特殊文字にマッチした、クライアントから送信されますが、これらの特殊文字を持っている場合、私達はちょうどそれが着陸に失敗してみましょうすることができることを確認する必要があります。
問題のあるSQLインジェクションを解決するために、サービス側では:私たちは、彼は我々は次のように記述されたSQL文を記述した後ので、SQLインジェクションを防ぐことができたステッチを助けるpymysql、スプライシングSQL文字列を実行するために所有しないでください。
之前我们的sql语句是这样写的:
sql = "select * from userinfo where username='%s' and password='%s';"%(uname,pword)
以后再写的时候,sql语句里面的%s左右的引号去掉,并且语句后面的%(uname,pword)这些内容也不要自己写了,按照下面的方式写
sql = "select * from userinfo where username=%s and password=%s;"
难道我们不传值了吗,不是的,我们通过下面的形式,在excute里面写参数:
#cursor.execute(sql,[uname,pword]) ,其实它本质也是帮你进行了字符串的替换,只不过它会将uname和pword里面的特殊字符给过滤掉。
看下面的例子:
uname = input('请输入用户名:') #输入的内容是:chao' -- xxx或者xxx' or 1=1 -- xxxxx
pword = input('请输入密码:')
sql = "select * from userinfo where username=%s and password=%s;"
print(sql)
res = cursor.execute(sql,[uname,pword]) #res我们说是得到的行数,如果这个行数不为零,说明用户输入的用户名和密码存在,如果为0说名存在,你想想对不
print(res) #如果输入的用户名和密码错误,这个结果为0,如果正确,这个结果为1
if res:
print('登陆成功')
else:
print('用户名和密码错误!')
#看结果:
请输入用户名:xxx' or 1=1 -- xxxxx
请输入密码:
select * from userinfo where username=%s and password=%s;
0
用户名和密码错误!
pymysqlでexcuteは、問題への完璧なソリューションを提供します。
总结咱们刚才说的两种sql注入的语句
#1、sql注入之:用户存在,绕过密码
chao' -- 任意字符
#2、sql注入之:用户不存在,绕过用户与密码
xxx' or 1=1 -- 任意字符
ソリューション概要:
# 原来是我们对sql进行字符串拼接
# sql="select * from userinfo where name='%s' and password='%s'" %(user,pwd)
# print(sql)
# res=cursor.execute(sql)
#改写为(execute帮我们做字符串拼接,我们无需且一定不能再为%s加引号了)
sql="select * from userinfo where name=%s and password=%s" #!!!注意%s需要去掉引号,因为pymysql会自动为我们加上
res=cursor.execute(sql,[user,pwd]) #pymysql模块自动帮我们解决sql注入的问题,只要我们按照pymysql的规矩来。