【Python从入门到进阶】56、Mysql防止SQL注入及ORM库简化操作

2024-06-02 11:28

本文主要是介绍【Python从入门到进阶】56、Mysql防止SQL注入及ORM库简化操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接上篇《55、使用Python轻松操作Mysql数据库》
上一篇我们讲解了Mysql的基本链接和增删改查,本篇我们来介绍链接Mysql时参数化查询与防止SQL注入以及使用ORM(对象关系映射)库简化操作的内容。

一、参数化查询与防止SQL注入

在数据库操作中,SQL注入是一种常见的安全漏洞,它允许攻击者通过注入恶意的SQL代码片段来操纵SQL查询的逻辑,从而可能窃取、修改或删除数据库中的数据。为了防止SQL注入攻击,最佳实践是使用参数化查询或预编译语句(prepared statements)。

1、SQL注入简介

SQL注入攻击发生在用户输入被直接拼接到SQL查询语句中,而没有被适当地验证或转义。攻击者可以构造特殊的输入,使得原本用于筛选或检索数据的SQL语句变得具有破坏性。

例如,假设有一个简单的查询用于检索用户信息:

SELECT * FROM users WHERE username = '$username' AND password = '$password';

如果$username或$password变量直接来自用户输入,并且没有经过适当的验证或转义,那么攻击者可以通过输入类似' OR '1'='1的值来绕过身份验证。

2、参数化查询

参数化查询(或预编译语句)是一种在查询语句中使用参数占位符,并在执行查询之前为这些占位符提供实际值的技术。这种方法确保用户输入不会被解释为SQL代码的一部分,从而防止了SQL注入攻击。

在Python的mysql.connector库中,可以使用参数化查询。下面是一个例子:

import mysql.connector  # 数据库连接配置(省略)  # 连接到数据库(省略)  # 参数化查询示例  
query = "INSERT INTO users (username, password) VALUES (%s, %s)"  
data = ("secure_username", "hashed_password")  cursor.execute(query, data)  # 提交事务并关闭连接(省略)

在上面的例子中,%s是参数占位符,data是一个元组,包含要插入的实际值。这些值在查询执行之前被绑定到占位符上,而不是直接拼接到查询字符串中。

3、为什么要使用参数化查询

使用参数化查询有以下几个好处:

●安全性:通过确保用户输入不会被解释为SQL代码的一部分,参数化查询可以防止SQL注入攻击。
●性能:预编译的语句可以被数据库缓存和重用,这可以提高执行相同或类似查询的性能。
●可读性:使用参数化查询可以使代码更清晰、更易于维护,因为它减少了字符串拼接和格式化的需要。
●类型安全:数据库驱动程序会验证参数的类型和值,这有助于减少由于类型不匹配或无效值导致的错误。

4、如何实施参数化查询

实施参数化查询的具体方法取决于你使用的编程语言和数据库驱动程序。在Python中,使用mysql.connector、sqlite3、psycopg2(对于PostgreSQL)等库时,都可以使用参数化查询(mysql.connector的操作方法如2小结描述)。

在编写代码时,始终遵循以下最佳实践:

●永远不要直接将用户输入拼接到SQL查询语句中。
●使用参数化查询或预编译语句来确保用户输入被安全地处理。
●对所有用户输入进行验证和清理,以防止潜在的攻击向量。
●定期更新和修补你的数据库和数据库驱动程序,以利用最新的安全特性。

通过遵循这些最佳实践,你可以大大降低应用程序受到SQL注入攻击的风险。

二、使用ORM(对象关系映射)库简化操作

在数据库编程中,对象关系映射(Object-Relational Mapping,简称ORM)是一种技术,它允许开发者使用面向对象的方式来操作数据库,而无需编写大量的SQL语句。ORM库在应用程序和数据库之间建立了一个桥梁,通过自动处理数据转换、查询构建和数据库交互等任务,大大简化了数据库操作。

1、ORM的概述

ORM库的主要目标是实现数据库表与编程语言中的类之间的映射。在ORM中,数据库表被映射为类,表中的行被映射为类的实例(对象),而列则被映射为对象的属性。通过操作这些对象,开发者可以间接地操作数据库中的数据。

ORM库通常提供以下功能:

●数据映射:将数据库表映射为类,以及将表中的行和列映射为对象的属性和方法。
●查询构建:允许开发者使用面向对象的方式来构建和执行SQL查询。
●关系管理:处理数据库中的关系(如一对一、一对多、多对多等),并在对象之间建立相应的关联。
●事务管理:提供对数据库事务的支持,确保数据的一致性和完整性。

2、使用ORM库的好处

使用ORM库进行数据库操作有以下好处:

●简化开发:通过面向对象的方式来操作数据库,开发者无需编写大量的SQL语句,降低了开发难度和复杂性。
●提高可维护性:ORM库通常具有良好的封装性和可扩展性,使得代码更加易于维护和扩展。
●减少错误:ORM库能够自动处理数据转换和查询构建等任务,减少了因手动编写SQL语句而导致的错误。
●提高性能:ORM库通常具有缓存机制,能够减少与数据库的交互次数,提高应用程序的性能。

3、流行的ORM库

在Python中,有几个流行的ORM库可供选择,包括SQLAlchemy、Django ORM(Django框架的一部分)、Peewee等。这些库都提供了丰富的功能和灵活的配置选项,可以根据项目的需求选择合适的ORM库。

【SQLAlchemy示例】
SQLAlchemy是一个功能强大的Python ORM库,它支持多种数据库后端,并提供了丰富的API和扩展功能。下面是一个使用SQLAlchemy进行数据库操作的简单示例:

首先,安装SQLAlchemy库(如果尚未安装):

pip install sqlalchemy

然后,使用SQLAlchemy定义数据模型(即数据库表,这里以操作Mysql为例):

# 导入sqlalchemy的Columu类,用于定义模型中的字段
from sqlalchemy import Column, Integer, String
# 导入create_engine函数,用于创建数据库引擎
from sqlalchemy import create_engine
# 导入declarative_base函数,用于创建ORM基类
# 导入sessionmaker类,用于创建会话类
from sqlalchemy.orm import declarative_base, sessionmaker# 定义基础类,继承自declarative_base()返回的基类
Base = declarative_base()# 定义User模型,继承自Base基类
class User(Base):__tablename__ = 'users'id = Column(Integer, primary_key=True)name = Column(String)age = Column(Integer)email = Column(String, unique=True)address = Column(String)# 创建数据库引擎,用于链接数据库
engine = create_engine('mysql+mysqlconnector://root:1234@localhost/test')# 创建会话类,用于与数据库进行交互
Session = sessionmaker(bind=engine)# 创建表(如果表不存在)
Base.metadata.create_all(engine)# 创建一个会话对象
session = Session()# 使用会话对象执行数据库操作
session = Session()
new_user = User(name='韩梅梅', age=16, email='hanmeimei@example.com', address='北京市朝阳区')
session.add(new_user)
session.commit()# 查询用户
print('[查询所有用户]')
users = session.query(User).all()
for user in users:print(user.id, user.name, user.age, user.email, user.address)# 查询姓名为韩梅梅的数据
print('[查询姓名为韩梅梅的用户]')
name_to_search = '韩梅梅'
users = session.query(User).filter_by(name=name_to_search).all()
for user in users:print(user.id, user.name, user.age, user.email, user.address)# 关闭会话
session.close()

在这个示例中,我们首先定义了一个名为User的数据模型,它对应于名为users的数据库表。然后,我们创建了一个数据库引擎和一个会话类,用于与数据库进行交互。接下来,我们使用会话对象执行了插入和查询操作,然后分别查询了全部数据,和按照权限查询数据。最后,我们关闭了会话以释放资源。

新增数据效果:

查询数据效果:

通过使用ORM库(如SQLAlchemy),我们可以更加高效、安全和可维护地进行数据库操作。

转载请注明出处:https://guangzai.blog.csdn.net/article/details/139377496

这篇关于【Python从入门到进阶】56、Mysql防止SQL注入及ORM库简化操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1023834

相关文章

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

C++必修:模版的入门到实践

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C++学习 贝蒂的主页:Betty’s blog 1. 泛型编程 首先让我们来思考一个问题,如何实现一个交换函数? void swap(int& x, int& y){int tmp = x;x = y;y = tmp;} 相信大家很快就能写出上面这段代码,但是如果要求这个交换函数支持字符型

mysql索引四(组合索引)

单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引;组合索引,即一个索引包含多个列。 因为有事,下面内容全部转自:https://www.cnblogs.com/farmer-cabbage/p/5793589.html 为了形象地对比单列索引和组合索引,为表添加多个字段:    CREATE TABLE mytable( ID INT NOT NULL, use

mysql索引三(全文索引)

前面分别介绍了mysql索引一(普通索引)、mysql索引二(唯一索引)。 本文学习mysql全文索引。 全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。 在MySql中,创建全文索引相对比较简单。例如:我们有一个文章表(article),其中有主键ID(

mysql索引二(唯一索引)

前文中介绍了MySQL中普通索引用法,和没有索引的区别。mysql索引一(普通索引) 下面学习一下唯一索引。 创建唯一索引的目的不是为了提高访问速度,而只是为了避免数据出现重复。唯一索引可以有多个但索引列的值必须唯一,索引列的值允许有空值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该使用关键字UNIQUE,把它定义为一个唯一索引。 添加数据库唯一索引的几种

mysql索引一(普通索引)

mysql的索引分为两大类,聚簇索引、非聚簇索引。聚簇索引是按照数据存放的物理位置为顺序的,而非聚簇索引则不同。聚簇索引能够提高多行检索的速度、非聚簇索引则对单行检索的速度很快。         在这两大类的索引类型下,还可以降索引分为4个小类型:         1,普通索引:最基本的索引,没有任何限制,是我们经常使用到的索引。         2,唯一索引:与普通索引

零基础STM32单片机编程入门(一)初识STM32单片机

文章目录 一.概要二.单片机型号命名规则三.STM32F103系统架构四.STM32F103C8T6单片机启动流程五.STM32F103C8T6单片机主要外设资源六.编程过程中芯片数据手册的作用1.单片机外设资源情况2.STM32单片机内部框图3.STM32单片机管脚图4.STM32单片机每个管脚可配功能5.单片机功耗数据6.FALSH编程时间,擦写次数7.I/O高低电平电压表格8.外设接口

Python 字符串占位

在Python中,可以使用字符串的格式化方法来实现字符串的占位。常见的方法有百分号操作符 % 以及 str.format() 方法 百分号操作符 % name = "张三"age = 20message = "我叫%s,今年%d岁。" % (name, age)print(message) # 我叫张三,今年20岁。 str.format() 方法 name = "张三"age

【服务器运维】MySQL数据存储至数据盘

查看磁盘及分区 [root@MySQL tmp]# fdisk -lDisk /dev/sda: 21.5 GB, 21474836480 bytes255 heads, 63 sectors/track, 2610 cylindersUnits = cylinders of 16065 * 512 = 8225280 bytesSector size (logical/physical)