SQL注入
==目标:==了解什么是SQL注入?
SQL注入指的是:恶意篡改或注入SQL条件。
当开发者的数据条件若被恶意篡改,那就达不到预期的查询效果。
为了了解SQL注入是怎么回事?通过一个案例来分析。
例如,使用命令来完成:
(1)给学生表tb_student中添加一些数据,查看效果;
(2)查询age=22的这条数据的所有信息;
(3)使用SQL注入方式来恶意篡改查询条件,比如在条件结尾处,添加or 1=1,并查询结果;
(4)思考:对比两次查询结果,该如何解决这类SQL注入问题呢?
###################SQL注入#########################
# 使用库
use sz38db_students;
# 插入几条数据
insert into student(name, gender, age) values ('周行','男',22);
insert into student(name, gender, age) values ('赵雪珂','女',22);
# 查询 age = 22
select * from student where age=22;
# 篡改条件 SQL注入
# select * from student where age=22 or age>0;
select * from student where age=22 or 1=1;
# 避免问题产生? -语句参数化
==总结:==
(1)恶意篡改或注入新的SQL条件的行为叫做();==A、SQL注入==;B、SQL添加;
(2)注意:当恶意篡改了SQL条件后,查询的结果可能达不到预期效果。
语句参数化
==目标:==掌握语句参数化的使用。
如果要解决SQL注入的问题,在pymysql模块中,可采用语句参数化来解决。
语句参数化是指以%s表示值,然后再传入具体的参数值进行替换。
为了更好理解语句参数化,可以把SQL语句的参数化、值,简要地理解为print()函数中的格式化符号输出:
print("xxx%s, xxx%d"%(name, age))
要使用cursor对象的函数:
| 函数 | 含义 |
|---|---|
| execute(operate, param) | 用于执行SQL语句,返回受影响的行数。 其中,参数operation为字符串类型,表示具体的SQL语句,注意,若在SQL语句中要向外传入参数值,则该参数均使用%s表示; 参数parameters为列表类型,表示SQL语句中的参数。 |
说明:
param参数的类型是列表list。
例如,使用pymysql模块来完成:
(1)通过键盘录入的方式输入变化的数据值;
(2)使用语句参数化和execute()给数据表添加一条数据内容;
(3)操作完成后,使用DataGrip查看添加成功后的数据结果。

# 1.导入模块
import pymysql
# 2.创建连接对象
db_conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="sz38db_students",
charset="utf8"
)
# 3.创建游标对象
db_cursor = db_conn.cursor()
# 4.编写SQL执行
name = input("请输入姓名:")
gender = input("请输入性别:")
age = int(input("请输入年龄:"))
params = [name,gender,age]
sql = "insert into student(name,gender,age) values(%s,%s,%s)" # 不管什么类型的数据,都是使用%s替换
# sql = "insert into student(name,gender,age) values(%s,%s,%d)" # 错误
db_cursor.execute(sql,params)
# *5.提交事务
db_conn.commit()
# 6.关闭游标
db_cursor.close()
# 7.关闭连接
db_conn.close()
print("数据操作已完成!!")
==总结:==
(1)请问:语句参数化时,必须使用%s表示参数,这句话正确吗?==A、正确==;B、错误;
(2)注意:要进行语句参数化时,使用execute()方法时需要传递两个参数。
查询数据
==目标:==掌握pymysql查询数据操作。
查询数据,要使用cursor对象的函数:
| 函数 | 含义 |
|---|---|
| execute(operate [, param]) | 用于执行SQL语句,返回受影响的行数。 其中,参数operation为字符串类型,表示具体的SQL语句,注意,若在SQL语句中要向外传入参数值,则该参数均使用%s表示; 参数parameters为列表类型,表示SQL语句中的参数。 |
| fetchone() | 在执行查询语句时,获取查询结果集的第一行数据,返回一个元组,即(v1, v2,...)。 |
| fetchall() | 在执行查询时,获取结果集的所有行,返回一个元组,即((v11, v12,...), (v21, v22,...),...)。 |
说明:
查询的数据结果是元组类型。
例如,使用pymysql模块来完成:
(1)使用fetchone来查询一条某xx姓名的数据信息;
(2)使用fetchall()查询出所有数据信息,并遍历出详细信息。
import pymysql
db_conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="sz38db_students",
charset="utf8"
)
db_cursor = db_conn.cursor()
# 执行查询语句
# sql = "select * from student where name=%s"
# name = input("请输入姓名:")
# # params = [name,]
# params = [name]
# db_cursor.execute(sql,params)
# # fetchone()
# result = db_cursor.fetchone()
# print(f"查询一条结果:{result}")
# sql = "select * from student where name=%s"
sql = "select name from student where name=%s"
name = input("请输入姓名:")
# params = [name,]
params = [name]
db_cursor.execute(sql,params)
# fetchone()
result = db_cursor.fetchone()
print(f"查询一条结果:{result}")
# print(f"查询一条结果:{result[1]}")
# 提交事务
db_conn.commit()
db_cursor.close()
db_conn.close()
print("数据查询已结束!~~")
import pymysql
db_conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="sz38db_students",
charset="utf8"
)
db_cursor = db_conn.cursor()
# 执行查询语句
sql = "select * from student"
db_cursor.execute(sql)
# fetchall()
result = db_cursor.fetchall()
print(f"查询所有结果:{result}")
for student in result:
print(student)
for id,name,gender,age in result:
print(name)
# 提交事务
db_conn.commit()
db_cursor.close()
db_conn.close()
print("数据查询已结束!~~")
==总结:==
(1)当要获取所有查询结果数据时,可以使用()方法;A、fetchone();==B、fetchall()==;
(2)注意:虽然查询数据无需提交事务,但还是建议提交一下,这样可以避免与CRUD的差异化。
注册与登录案例
注册
==目标:==了解注册用户的使用。
比如,在登录某网站前,是需要进行注册用户的。那么,注册是怎么做的呢?
其实,注册用户本质上就是给用户表添加一条数据。
例如,一起来完成:
(1)新建一个班级db_users数据库,编码为utf8;
(2)在库中新建一个用户表,字段有:编号id[主键自增]、用户名username、密码password;
(3)使用键盘录入数据的形式输入用户名、密码,并用于注册一个用户;
(4)使用DataGrip查看注册成功后的用户数据结果。
import pymysql
db_conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="sz38db_users",
charset="utf8"
)
db_cursor = db_conn.cursor()
# 执行插入语句
in_name = input("请输入用户名:")
in_pwd = input("请输入密码:")
params = [in_name,in_pwd]
sql = "insert into tb_user(username,password) values(%s,%s)"
db_cursor.execute(sql,params)
# 提交事务
db_conn.commit()
db_cursor.close()
db_conn.close()
print("数据注册已结束!~~")
==总结:==
(1)当要注册用户时,本质上实现的是()功能;==A、插入数据==;B、查询数据;
(2)注意:使用pymysql模块操作注册功能时,记得进行语句参数化。
登录
==目标:==掌握如何进行登录操作。
当成功注册用户信息后,则可以进行登录操作了。那么,登录是怎么做的呢?
其实,登录账户本质上就是:查询用户数据,并与用户手动输入的用户名和密码进行匹配。
当匹配成功,则可以登录;反之,则登录失败。
例如,一起来完成:
(1)使用键盘录入数据的形式输入用户名、密码,并用于登录操作;
(2)当登录时,使用的数据内容则是已注册成功的用户表信息;
(3)观察注册成功后的用户数据,当已匹配成功,则表示成功登录。
import pymysql
db_conn = pymysql.connect(
host="localhost",
port=3306,
user="root",
password="123456",
database="sz38db_users",
charset="utf8"
)
db_cursor = db_conn.cursor()
# 执行查询语句、匹配
sql = "select username,password from tb_user"
db_cursor.execute(sql)
query_result = db_cursor.fetchall()
print(query_result)
# 匹配
in_uname = input("请输入用户名:")
in_upwd = input("请输入密码:")
# for user in query_result:
for username,password in query_result:
if in_uname == username and in_upwd == password:
print(f"恭喜你,{username}, 已登录成功!!")
break # 跳出
else:
print("登录失败!!!")
# 提交事务
db_conn.commit()
db_cursor.close()
db_conn.close()
print("数据注册已结束!~~")
# 需求:
# 1.根据上述sql无法知道是用户名或密码哪个出错了, 若要知道到底是哪个出错, 做新需求?? select username from tb_user where password=xx;
# 2.注册和登录账户时,应该要给密码加密处理? 做新需求?? -hashlib库 [MD5 =32位] [SHA1 = 40位] ==>学习: 是什么? 使用API? 实战开发?
# https://tool.lu/encdec/
# *3.验证码? 邮箱号、手机号等? --新增字段、添加数据等??
==总结:==
(1)在Python中,如果要判断数据内容是否匹配成功可以使用()语句;==A、if==;B、where;
(2)注意:在实际应用中,登录和注册功能可能还会涉及到用户数据加密,比如MD5加密、SHA1加密等。










![[游戏开发][UE5]引擎学习记录](https://img-blog.csdnimg.cn/direct/a0ee1c2ccf7349128c2c6f29f9b601f1.png)








