网络安全篇(数据表单的创建 SQL命令拾遗 数据的SQL注入的防护)
Posted 学成七步
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络安全篇(数据表单的创建 SQL命令拾遗 数据的SQL注入的防护)相关的知识,希望对你有一定的参考价值。
SQL注入五孔不入,尽管是老技术了,但是依然是重点防护的手段,更多的需要我们数据库开发者细心!!
数据表的演练
1 创建数据表
create database jing_dong charset=utf8;
-- 使用 jing_dong数据库
use jing_dong;
create table goods(
id int unsigned primary key auto_increment not null,
name varchar(150) not null,
cate_name varchar(40) not null,
brand_name varchar(40) not null,
price decimal(10,3) not null default 0,
is_show bit not null default 1,
is_saleoff bit not null default 0
);
-- 展示数据库
show tables;
-- 插入数据
INSERT INTO `goods` VALUES (1, '联想(Lenovo)天逸510S 个人商务台式机电脑整机(i3-10100 8G 512G', '笔记本', '华硕', 2324.000, b'0', b'0');
INSERT INTO `goods` VALUES (2, '戴尔dell成就3690 商用办公台式机电脑主机(11代i5-11400 16G', '笔记本', '联想', 4234.000, b'0', b'0');
INSERT INTO `goods` VALUES (3, '联想(Lenovo)天逸510S 个人商务台式机电脑整机(i5-10400 16G 1T+256G SSD', '游戏本', '索尼', 2342.000, b'0', b'0');
INSERT INTO `goods` VALUES (4, '武极天机 i5 10400F/GTX1050Ti/游戏台式办公电脑主', '超极本', '苹果', 4655.000, b'0', b'0');
INSERT INTO `goods` VALUES (5, '荣耀笔记本 MagicBook X 14 2021 14英寸全面屏轻薄笔记本电脑 (i3 10110U 8GB', '笔记本', '苹果', 1233.000, b'0', b'0');
INSERT INTO `goods` VALUES (6, '戴尔Dell成就3000 办公商用家用台式机电脑英特尔十代处理器学习财务', '平板电脑', '戴尔', 3434.000, b'0', b'0');
INSERT INTO `goods` VALUES (7, '戴尔笔记本电脑dell灵越15-3501 15.6英寸高性能轻薄商务笔记本电脑(11代英特', '台式机', '华硕', 2344.000, b'0', b'0');
INSERT INTO `goods` VALUES (8, '联想(Lenovo)扬天M4000q英特尔酷睿i3 商用台式机电脑整机(i3-10100', '平板电脑', '联想', 4543.000, b'0', b'0');
INSERT INTO `goods` VALUES (9, '联想ThinkPad E15 2021款 酷睿版 英特尔酷睿i5/i7 轻薄笔记本电脑 人', '台式机', '苹果', 3455.000, b'0', b'0');
INSERT INTO `goods` VALUES (10, '硕扬 i5 10400F/八核/GTX1050TI 4G/32G内存游戏台式吃鸡', '台式机', '索尼', 2455.000, b'0', b'0');
INSERT INTO `goods` VALUES (11, '惠普(HP)小欧高清一体机电脑21.5英寸(J4025 4G 256SSD UMA 无线', '笔记本', '华硕', 7899.000, b'0', b'0');
-- 查询为超极本的商品
select *from goods where cate_name="超极本";
-- 但是我只想看商品品名称和价格
select name,price from goods where cate_name="超极本";
-- 但是我不认识英文怎么办,设置一个中文的对话框
select name as 名字,price as 价格 from goods where cate_name="超极本";
-- 显示商品种类
select name,cate_name from goods;
-- 我想看所有的电脑的分类,全部类别用distinct进行实现
select distinct cate_name from goods;
-- 我想看所有的电脑的分类,用分组来进行实现
select cate_name from goods group by cate_name;
-- 我想看电脑的分类并且要加上名字,用分组来进行实现
select cate_name,group_concat(name) from goods group by cate_name;
-- 求所有电脑产品的平均价格
select avg(price) from goods;
-- 求所有电脑产品的平均价格,并保留两位小数
select round(avg (price),2) from goods;
-- 显示每种类别商品的平均价格
select cate_name ,avg(price) from goods group by cate_name;
-- 查询每种类型的商品中最贵的,最便宜的,平均价,数量
select cate_name, max(price) ,min(price) ,avg(price),count(*) from goods group by cate_name;
-- 查询所有价格大于平均价格的商品,并且按价格降序排序
select id,name,price from goods where price> (select round (avg(price),2) as avg_price from goods) order by price desc;
-- 查询每种商品中最贵的电脑信息
select * from goods
inner join(
select
cate_name,
max(price) as max_price,
min(price) as min_price,
avg(price) as avg_price,
count(*) from goods group by cate_name
)
as goods_new_info
on goods.cate_name=goods_new_info.cate_name and goods.price=goods_new_info.max_price;
-- 思路,把第一次上面的查询语句看作一个表,用下面的检索条件进行适配,名字相等 价格相等,那么就直接输出出来,相当于两张表合并查询
-- 或者也可以有这种写法(表级的查询)
select *from
(select cate_name,max(price) as max_price from goods group by cate_name )
as g_new
left join goods as g
on g_new.cate_name =g.cate_name and g_new.max_price =g.price;
最后一个的输出结果为:
+----+----------------------------------------------------------------------+-----------+------------+----------+---------+------------+-----------+-----------+-----------+--------------+----------+
| id | name | cate_name | brand_name | price | is_show | is_saleoff | cate_name | max_price | min_price | avg_price | count(*) |
+----+----------------------------------------------------------------------+-----------+------------+----------+---------+------------+-----------+-----------+-----------+--------------+----------+
| 3 | 联想(Lenovo)天逸510S 个人商务台式机电脑整机(i5-10400 16G 1T+256G SSD | 游戏本 | 索尼 | 2342.000 | | | 游戏本 | 2342.000 | 2342.000 | 2342.0000000 | 1 |
| 4 | 武极天机 i5 10400F/GTX1050Ti/游戏台式办公电脑主 | 超极本 | 苹果 | 4655.000 | | | 超极本 | 4655.000 | 4655.000 | 4655.0000000 | 1 |
| 8 | 联想(Lenovo)扬天M4000q英特尔酷睿i3 商用台式机电脑整机(i3-10100 | 平板电脑 | 联想 | 4543.000 | | | 平板电脑 | 4543.000 | 3434.000 | 3988.5000000 | 2 |
| 9 | 联想ThinkPad E15 2021款 酷睿版 英特尔酷睿i5/i7 轻薄笔记本电脑 人 | 台式机 | 苹果 | 3455.000 | | | 台式机 | 3455.000 | 2344.000 | 2751.3333333 | 3 |
| 11 | 惠普(HP)小欧高清一体机电脑21.5英寸(J4025 4G 256SSD UMA 无线 | 笔记本 | 华硕 | 7899.000 | | | 笔记本 | 7899.000 | 1233.000 | 3922.5000000 | 4 |
+----+----------------------------------------------------------------------+-----------+------------+----------+---------+------------+-----------+-----------+-----------+--------------+----------+
查询各个电脑种类的最大价格
select cate_name ,max(price) from goods group by cate_name;
数据库高级演练 拆分为多个表
-- 创建商品分类
create table if not exists goods_cates(
id int unsigned primary key auto_increment,
name varchar(48) not null
);
-- 查看之前的goods表单中的所有分类
select cate_name from goods group by cate_name;
--将分组结果写入goods_cates 数据表中
insert into goods_cate(name) select cate_name from goods group by cate_name;
-- 同步表数据 通过goods_cates 数据表来更新goods表 更新goods 中的cate_name用第二张表来进行更新
update goods as g inner join goods_cates as c on g.cate_name=c.name set g.cate_name =c.id;
-- 我们发现主键的goods与goods_cates类型并不是一样的,这里我们就需要改变一下类型
alter table goods change cate_name cate_id int unsigned not null;
-- 插入关联,将cate_id 追加约束外键
alter table goods add foreign key(cate_id) references goods_cates(id);
-- 如何取消外键
alter table goods drop foreign key 外键名称;
pymysql 连接的过程
开始 ==> 创建connection > 获取cursor (游标对象)> 执行查询 执行命令 获取数据 处理数据 ==> 关闭cursor ==> 关闭 connection ==> 结束
import pymysql
#创建connect链接数据库
connect = pymysql.connect(host="localhost",port=3306,user='root',password='200228',database='jing_dong',charset='utf8')
#获得游标对象 cursor
cs1= connect.cursor()
#执行SQL语句中的select 并返回受影响的行数,查找一条数据
count =cs1.execute('select id,name from goods where id>=4')
print(count)
for i in range(count):
#获取查询结果
result = cs1.fetchone()
#打印查询的结果
print(result)
#关闭cursor对象
cs1.close()
#关闭连接
connect.close()
当我们的游标可以取到商品后,我们也可以取一下数据 信息,
cs1.fetchone() 取一个 cs1.fetchmany() 去多个
cs1.fetchall() 取所有的数据
fetchone等函数因为链接的是游标,因此,再没关闭连接和游标对象时,是按照前面执行的那步接着往下执行的
我们也可以通过定义后再进行取值
line_content = cs1.fetchone()
for temp in line_content:
print(temp)
#如果要是用fetchmany来进行查看的时候,就是元组套元组来进行显示
#这个的意思就是取五条数据
lines = cs1.fetchmany(5)
print(lines)
工程案例:
开发一款可以方便于京东商品查询的脚本,需使用面向对象开发;实现可查看数据库内所有商品 所有商品的分类 所有商品的品牌分类
from pymysql import connect
class JD(object):
def __init__(self):
# 初始化创建connection连接
self.conn = connect(host="localhost", port=3306, user='root', password='200228', database='jing_dong',
charset='utf8')
# 创建游标对象
self.cs1 = self.conn.cursor()
def __del__(self):
self.cs1.close()
self.conn.close()
def execute_sql(self, sql):
"""
:param sql: 传入sql数据,无需每次连接后断开
"""
self.cs1.execute(sql)
for temp in self.cs1.fetchall():
print(temp)
def show_all_intem(self):
"""显示所有的商品"""
# 创建connection连接
sql = "select *from goods;"
self.execute_sql(sql)
def show_cates(self):
sql = "SELECT name FROM goods_cates"
self.execute_sql(sql)
def show_brand(self):
sql = "SELECT name FROM goods_brands;"
self.execute_sql(sql)
@staticmethod
def print_menu():
"""
使用实例方法,全局调用
:return: 返回的值传入下一个即将调用的函数中
"""
print("----京东-----")
print("1:所有的商品")
print("2:所有的商品分类")
print("3:所有的商品品牌分类")
num = input("请输入功能对应的序号:")
# 这里切记,一定要return返回值
return num
def run(self):
while True:
num = self.print_menu()
if num == "1":
# 查询所有商品
self.show_all_intem()
elif num == "2":
# 查询分类
self.show_cates()
elif num == "3":
# 查询品牌
self.show_brand()
else:
print("输入有误,请重新输入....")
def main():
# 1. 创建一个京东商城的对象
jd = JD()
# 2. 调用这个对象的run 方法,让其运行
jd.run()
if __name__ == '__main__':
main()
pymysql增删改查:实质上都是一样的,唯一不一样的就是最后一个需要提交 通过使用 commit 方法
插入数据:
from pymysql import connect
conn = connect(host="localhost", port=3306, user='root', password='200228', database='jing_dong',
charset='utf8')
# 创建游标对象
cs1 = conn.cursor()
sql = "insert into goods_cates(name) VALUES ('硬盘_new')"
cs1.execute(sql)
#无论是更新还是删除,必须要commit提交一下数据库
conn.commit()
cs1.close()
conn.close()
实现数据的插入
from pymysql import connect
class JD(object):
def __init__(self):
# 初始化创建connection连接
self.conn = connect(host="localhost", port=3306, user='root', password='200228', database='jing_dong',
charset='utf8')
# 创建游标对象
self.cs1 = self.conn.cursor()
def __del__(self):
self.cs1.close()
self.conn.close()
def execute_sql(self, sql):
"""
:param sql: 传入sql数据,无需每次连接后断开
"""
self.cs1.execute(sql)
for temp in self.cs1.fetchall():
print(temp)
def show_all_intem(self):
"""显示所有的商品"""
# 创建connection连接
sql = "select *from goods;"
self.execute_sql(sql)
def show_cates(self):
sql = "SELECT name FROM goods_cates"
self.execute_sql(sql)
def show_brand(self):
sql = "SELECT name FROM goods_brand;"
self.execute_sql(sql)
def add_menu(self):
item_name =input("请输入新商品分类名称")
sql ="""insert into goods_brand(name) VALUES("%s") """ %item_name
self.execute_sql(sql)
#更新创建数据表单,实现数据的更新
self.conn.commit()
@staticmethod
def print_menu():
"""
使用实例方法,全局调用
:return: 返回的值传入下一个即将调用的函数中
"""
print("----京东-----")
print("1:所有的商品")
print("2:所有的商品分类")
print("3:所有的商品品牌分类")
print("4:插入商品品牌")
num = input("请输入功能对应的序号:")
# 这里切记,一定要return返回值
return num
def run(self):
while True:
num = self.print_menu()
if num == "1":
# 查询所有商品
self.show_all_intem()
elif num == "2":
# 查询分类
self.show_cates()
elif num == "3":
# 查询品牌
self.show_brand()
elif num == "4":
# 插入数据
self.add_menu()
else:
print("输入有误,请重新输入....")
def main():
# 1. 创建一个京东商城的对象
jd = JD()
# 2. 调用这个对象的run 方法,让其运行
jd.run()
if __name__ == '__main__':
main()
SQL注入:
什么是SQL注入,在数据库没有超级管理员的权限时,我们通过一些奇怪的命令也可以获取到数据表单
-- 输入5之后 可以通过这条命令获取到全部的信息
-- select * from goods where name =''or 1=1 or'';
'or 1=1 or'
输出
----->select * from goods where name =''or 1=1 or'';ql<------
(1, '联想(Lenovo)天逸510S 个人商务台式机电脑整机(i3-10100 8G 512G', 4, '华硕', Decimal以上是关于网络安全篇(数据表单的创建 SQL命令拾遗 数据的SQL注入的防护)的主要内容,如果未能解决你的问题,请参考以下文章