Mysql--运维篇--安全性(数据库访问控制,最小权限原则,表空间加密,TLS加密,证书签发,SQL注入及防范等)

一、数据库访问控制

MySQL的访问控制是确保数据库安全的关键机制之一。通过合理的用户权限管理和访问控制策略,可以防止未经授权的用户访问、修改或删除敏感数据。

1、MySQL访问控制的工作原理

MySQL使用基于用户的访问控制模型,每个用户都有特定的权限来执行不同的操作。
访问控制主要由以下几个部分组成:

  • 身份验证(Authentication):验证用户的身份,确保只有合法用户能够连接到数据库。
  • 授权(Authorization):根据用户的身份,授予其相应的权限,限制其可以执行的操作。
  • 权限继承:用户可以从角色或其他用户继承权限,简化权限管理。
(1)、身份验证

MySQL支持多种身份验证方法,常见的包括:

1、基于密码的身份验证:

用户使用用户名和密码进行身份验证,这也是最常见的身份验证方式。
sql示例:

CREATE USER 'user'@'host' IDENTIFIED BY 'password';
2、多因素认证(MFA):

可以通过插件(如pam或ldap)实现多因素认证,增强安全性。
sql示例:

-- 使用PAM插件进行身份验证
CREATE USER 'user'@'host' IDENTIFIED WITH auth_pam;
3、证书身份验证:

通过SSL/TLS证书进行身份验证,适用于需要高安全性的场景。
sql示例:

-- 要求客户端使用SSL进行身份验证
ALTER USER 'user'@'host' REQUIRE SSL;
4、无密码身份验证:

对于某些内部应用或自动化脚本,可以使用无密码身份验证(如unix_socket),但需谨慎使用。
sql示例:

CREATE USER 'user'@'localhost' IDENTIFIED WITH unix_socket;
(2)、授权

授权是指为用户分配特定的权限,允许或禁止其执行某些操作。MySQL提供了细粒度的权限控制,可以根据不同的对象(如表、视图、存储过程等)和操作类型(如SELECT、INSERT、UPDATE、DELETE等)进行授权。

1、权限级别

MySQL提供了多个权限级别,从全局到列级,允许你根据需求进行精确的权限控制:

全局权限:
对整个服务器上的所有数据库和表生效。
sql示例:

GRANT ALL PRIVILEGES ON *.* TO 'user'@'host';

数据库权限:
对特定数据库中的所有表生效。
sql示例:

GRANT ALL PRIVILEGES ON database.* TO 'user'@'host';

表权限:
对特定数据库中的某个表生效。
sql示例:

GRANT SELECT, INSERT, UPDATE ON database.table TO 'user'@'host';

列权限:
对特定表中的某些列生效。
sql示例:

GRANT SELECT (column1, column2) ON database.table TO 'user'@'host';

存储过程权限:
对特定存储过程或函数生效。
sql示例:

GRANT EXECUTE ON PROCEDURE database.procedure_name TO 'user'@'host';

撤销权限:
可以随时撤销用户的权限,以确保权限不会被滥用。
sql示例:

REVOKE SELECT, INSERT, UPDATE ON database.table FROM 'user'@'host';
2、常见权限类型
  • SELECT:允许用户查询表中的数据。
  • INSERT:允许用户向表中插入新数据。
  • UPDATE:允许用户更新表中的现有数据。
  • DELETE:允许用户删除表中的数据。
  • CREATE:允许用户创建新的数据库、表或索引。
  • DROP:允许用户删除数据库、表或索引。
  • ALTER:允许用户修改表结构(如添加或删除列)。
  • INDEX:允许用户创建或删除索引。
  • GRANT OPTION:允许用户将自己拥有的权限授予其他用户。
  • SUPER:允许用户执行一些特权操作(如更改全局配置、终止其他会话等)。应谨慎授予此权限。
3、权限继承与角色管理

MySQL 8.0及以上版本引入了角色(Role)概念,允许你将一组权限分配给一个角色,然后将该角色授予多个用户。这简化了权限管理,尤其是当多个用户需要相同的权限时。

创建角色:
sql示例:

CREATE ROLE 'admin_role';

为角色授予权限:
sql示例:

GRANT ALL PRIVILEGES ON *.* TO 'admin_role';

将角色授予用户:
sql示例:

GRANT 'admin_role' TO 'user1'@'host', 'user2'@'host';

启用或禁用角色:
默认情况下,授予的角色不会自动启用。你可以通过以下命令启用或禁用角色。
sql示例:

SET DEFAULT ROLE ALL TO 'user1'@'host';  -- 启用所有角色
SET DEFAULT ROLE NONE TO 'user1'@'host'; -- 禁用所有角色

2、最小权限原则

最小权限原则是访问控制的核心思想,即为每个用户分配仅限于完成其任务所需的最小权限。遵循这一原则可以有效减少潜在的安全风险。

避免使用GRANT ALL:
不要为普通用户授予ALL PRIVILEGES,而是根据实际需求授予具体的权限。
sql示例:
– 不推荐

GRANT ALL PRIVILEGES ON *.* TO 'user'@'host';
-- 推荐
GRANT SELECT, INSERT, UPDATE ON database.table TO 'user'@'host';

限制SUPER权限:
SUPER权限允许用户执行一些特权操作(如更改全局配置、终止其他会话等),应仅授予信任的管理员用户。
sql示例:

-- 不推荐
GRANT SUPER ON *.* TO 'user'@'host';
-- 推荐
GRANT RELOAD, PROCESS ON *.* TO 'user'@'host';

禁用root用户远程访问:
默认情况下,root用户可以从任何主机连接到MySQL。建议只允许root用户从本地主机(localhost)访问,并为远程管理创建单独的管理员账户。
sql示例:

-- 禁止 root 用户远程访问
REVOKE ALL PRIVILEGES ON *.* FROM 'root'@'%';
FLUSH PRIVILEGES;

3、定期审查和清理用户权限

随着时间的推移,可能会有不必要的用户或权限存在。定期审查和清理用户权限可以帮助你保持系统的安全性。

查看所有用户的权限:
sql示例:

SELECT user, host, authentication_string, plugin FROM mysql.user;

删除不再需要的用户:
sql示例:

DROP USER 'user'@'host';

撤销不必要的权限:
sql示例:

REVOKE ALL PRIVILEGES ON *.* FROM 'user'@'host';

4、使用强密码策略

弱密码容易被暴力破解或猜测,因此建议启用强密码策略并定期更改密码。

启用密码强度检查:
MySQL提供了内置的密码验证插件,可以强制用户使用强密码。
配置示例:

[mysqld]
validate_password=ON
validate_password_policy=MEDIUM
validate_password_length=8
validate_password_number_count=1
validate_password_mixed_case_count=1
validate_password_special_char_count=1

定期更改密码:
建议定期更改用户密码,尤其是具有高权限的用户。
sql示例:

ALTER USER 'user'@'host' IDENTIFIED BY 'new_password';

5、网络和防火墙配置

除了用户权限管理,网络配置也是访问控制的重要组成部分。通过限制MySQL端口的访问,可以进一步提高安全性。

绑定到特定IP地址:
通过配置文件将MySQL绑定到特定的IP地址,防止外部网络直接访问MySQL服务器。
配置示例:

[mysqld]
bind-address = 127.0.0.1   # 仅允许本地访问

使用防火墙限制访问:
使用防火墙规则限制对MySQL端口(默认3306)的访问,只允许信任的IP地址或网络段访问。
命令示例:
使用iptables限制MySQL端口的访问

sudo iptables -A INPUT -p tcp --dport 3306 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP

解释:
第一条规则 允许来自 192.168.1.0/24 子网的流量。
第二条规则 拒绝所有其他流量。

启用SSL/TLS加密:
通过启用 SSL/TLS 加密,确保客户端与服务器之间的通信是加密的,防止中间人攻击。

6、常见问题及解决方式

(1)、无法连接到MySQL
  • 问题:用户无法连接到MySQL,提示“Access denied”或“Connection refused”。
  • 解决方式:
    • 检查用户是否正确配置了主机名(host),确保用户只能从允许的主机连接。
    • 确认MySQL服务是否正在运行,并且监听了正确的端口。
    • 检查防火墙设置,确保MySQL端口未被阻止。
    • 确认用户密码是否正确,是否启用了强密码策略。
(2)、权限不足
  • 问题:用户尝试执行某些操作时,提示“Access denied”或“Insufficient privileges”。
  • 解决方式:
    • 检查用户是否拥有执行该操作所需的权限。可以通过SHOW GRANTS查看用户的权限。
    • 如果权限不足,使用GRANT命令为用户授予权限。
    • 确保用户没有被授予过多的权限,遵循最小权限原则。
(3)、用户权限过多
  • 问题:用户拥有过多的权限,可能存在安全隐患。
  • 解决方式:
    • 定期审查用户的权限,确保每个用户只拥有完成其任务所需的最小权限。
    • 撤销不必要的权限,尤其是SUPER和GRANT OPTION等高权限。
(4)、远程访问被拒绝
  • 问题:用户尝试从远程主机连接到MySQL时,提示“Access denied”。
  • 解决方式:
    • 确认用户是否被允许从远程主机连接。可以通过GRANT命令为用户授予权限,指定允许的主机。
    • 检查MySQL配置文件中的bind-address设置,确保MySQL允许远程连接。
    • 检查防火墙设置,确保MySQL端口未被阻止。

7、数据库访问控制总结

MySQL的访问控制是确保数据库安全的重要机制。通过合理的用户权限管理、网络配置和强密码策略,可以有效防止未经授权的访问、篡改和泄露。为了确保系统的安全性,建议采取以下最佳实践:

  • 遵循最小权限原则,为每个用户分配仅限于完成其任务所需的最小权限。
  • 定期审查和清理用户权限,确保系统中没有不必要的用户或权限。
  • 使用强密码策略,启用密码强度检查并定期更改密码。
  • 限制MySQL端口的访问,使用防火墙和SSL/TLS加密保护网络通信。
  • 启用日志审计,定期检查日志,及时发现并响应潜在的安全威胁。

二、数据加密

1、表空间加密

表空间加密(Tablespace Encryption)是指对InnoDB表空间中的数据进行加密,确保即使磁盘上的数据文件被窃取,攻击者也无法读取其中的内容。MySQL使用AES-256算法对表空间进行加密,默认情况下,加密是透明的,应用程序不需要做任何修改即可使用加密表空间。

当然表空间加密会带来一定的性能开销,尤其是在写操作频繁的情况下。根据MySQL官方文档,加密表空间的性能开销大约在5%到10%之间。如果你的应用程序对性能要求较高,建议在生产环境中进行性能测试,评估加密对系统的影响。

如何启用InnoDB表空间加密?

(1)、生成加密密钥:

使用mysql_ssl_rsa_setup工具生成RSA密钥对。(如:keyring_file插件)。将密钥存储在安全的位置。

(2)、配置MySQL启用表空间加密:

配置示例:

[mysqld]
innodb_encrypt_tables=ON
innodb_encryption_threads=4
innodb_encrypt_log=ON

解释:
innodb_encrypt_table=ON指定为表空间进行加密。注意,配置并重启Mysql后,仅会对新创建的表空间文件进行加密,之前已经存在的表空间文件不会进行加密,可以在手动配置加密。
innodb_encrypt_log=ON指定为日志文件进行加密。如(重做日志(redo log)和撤销日志(undo log))等。

(3)、设置加密密钥库:
  • 可以使用MySQL内置的密钥管理插件(如keyring_file或keyring_vault)来管理加密密钥。
    配置示例:
 [mysqld]
 early-plugin-load=keyring_file.so
 keyring_file_data=/var/lib/mysql/keyring
(4)、已有表空间加密:

如果你已经有一些未加密的表空间,可以通过ALTER TABLE语句将其转换为加密表空间。
sql示例:

ALTER TABLE existing_table ENCRYPTION='Y';

2、备份文件加密

备份文件通常包含数据库中的所有数据,如果备份文件被窃取,攻击者可能会通过恢复备份获取敏感信息。因此,对备份文件进行加密是非常重要的。除了加密备份文件,还应确保备份文件存储在安全的位置。

建议使用以下措施:

  • 使用安全的存储介质:将备份文件存储在加密的硬盘或云存储服务中。
  • 限制访问权限:确保只有授权人员可以访问备份文件,设置严格的文件权限。
  • 定期删除过期备份:避免长期保存不必要的备份文件,减少潜在的风险。

如何对备份文件加密?
方法1:使用mysqldump进行逻辑备份
mysqldump是MySQL提供的逻辑备份工具,它将数据库导出为SQL文件。虽然mysqldump本身不支持直接加密备份文件,但你可以通过管道将输出传递给加密工具(如gpg或openssl)以实现备份文件加密。

示例:

使用gpg加密备份文件:
mysqldump -u root -p mydatabase | gpg --encrypt --recipient "your_email@example.com" > backup.sql.gpg
使用openssl加密备份文件:
mysqldump -u root -p mydatabase | openssl enc -aes-256-cbc -salt -out backup.sql.enc

方法2:使用Percona XtraBackup进行物理备份
Percona XtraBackup是一个用于InnoDB和MyRocks表的物理备份工具,支持热备份和增量备份。XtraBackup内置了加密功能,可以在备份过程中直接对备份文件进行加密。
示例:

步骤1:安装Percona XtraBackup:
sudo apt-get install percona-xtrabackup-80
   
步骤2:配置加密选项:
在备份命令中指定加密算法和密钥。XtraBackup支持多种加密算法,如AES128, AES192, AES256。
xtrabackup --backup --target-dir=/backup --encrypt=AES256 --encrypt-key="your_encryption_key"
   
步骤3:解密备份文件:
恢复备份时,需要使用相同的密钥进行解密。
xtrabackup --decrypt=AES256 --target-dir=/backup --encrypt-key="your_encryption_key"

3、网络通信SSL/TLS加密

(1)、什么是SSL/TLS加密?

SSL/TLS(Secure Sockets Layer/Transport Layer Security)是一种用于加密网络通信的协议,确保客户端与服务器之间的数据传输是安全的。通过启用SSL/TLS,可以防止中间人攻击(Man-in-the-Middle Attack),确保敏感数据(如用户名、密码)不会在传输过程中被窃取。

(2)、如何启用SSL/TLS加密?

在安全通信中,SSL/TLS证书用于加密和验证客户端与服务器之间的通信。为了实现这一点,通常需要一个证书颁发机构(CA, Certificate Authority)来签发服务器和客户端的证书。如果你不想使用商业CA,可以使用OpenSSL生成自签名的CA证书,并用它来签发服务器和客户端的证书。

1、生成CA证书

示例:

openssl req -new -x509 -days 365 -nodes -out ca.pem -keyout ca-key.pem

解释:

  • openssl req:这是OpenSSL的请求(Request)命令,用于生成证书签名请求(CSR)或直接生成自签名证书。
  • -new:表示这是一个新的证书请求。
  • -x509:表示生成的是一个自签名证书(X.509 格式),而不是证书签名请求(CSR)。自签名证书是不需要其他CA签发的证书,它自己就是自己的根证书。
  • -days 365:指定证书的有效期为365天。你可以根据需要调整这个值。
  • -nodes:表示私钥不进行加密(No DES)。如果不加这个选项,生成的私钥会要求输入密码进行加密。对于自动化部署或服务启动时,通常不希望每次都需要输入密码,因此使用-nodes选项。
  • -out ca.pem:指定输出的自签名证书文件名为ca.pem。
  • -keyout ca-key.pem:指定输出的私钥文件名为ca-key.pem。

结果:

  • 这个命令生成了一个自签名的CA证书(ca.pem)和对应的私钥(ca-key.pem)。CA证书将用于签发服务器和客户端的证书。
  • 服务端和客户端:CA证书本身不会直接用于服务端或客户端,但它用于验证服务器和客户端证书的真实性。客户端和服务端都需要信任这个CA证书。

简单理解下:
需要实现SSL(即加密网络通信),就需要在服务端和客户端都配置相关的证书。如果想要两个证书之间彼此能够信任,就要求两个证书都必须使用同一个CA证书进行签发。这样两个证书就可以彼此信任,两台机器就可以正常建立SSL连接了。

2、生成服务器证书

第一步:生成服务器的私钥和证书签名请求(CSR)
示例:

openssl req -newkey rsa:2048 -days 365 -nodes -keyout server-key.pem -out server-req.pem

解释:

  • openssl req:同上,用于生成证书签名请求(CSR)。
  • -newkey rsa:2048:生成一个新的2048位RSA私钥。你可以根据需要选择不同的密钥长度(如4096位)。
  • -days 365:指定证书的有效期为365天。
  • -nodes:同上,表示私钥不进行加密。
  • -keyout server-key.pem:指定输出的服务器私钥文件名为server-key.pem。
  • -out server-req.pem:指定输出的证书签名请求(CSR)文件名为server-req.pem。

作用:

  • 这个命令生成了服务器的私钥(server-key.pem)和证书签名请求(server-req.pem)。CSR 是一个包含公钥和其他信息(如域名、组织名称等)的文件,用于向CA申请签发证书。

第二步:使用CA证书签发服务器证书
示例:

openssl x509 -req -in server-req.pem -days 365 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem

解释:

  • openssl x509:这是OpenSSL的X.509证书处理命令,用于生成和操作X.509证书。
  • -req:表示输入是一个证书签名请求(CSR),即server-req.pem。
  • -in server-req.pem:指定输入的CSR文件为server-req.pem。
  • -days 365:指定生成的服务器证书有效期为365天。
  • -CA ca.pem:指定用于签发证书的CA证书为ca.pem。
  • -CAkey ca-key.pem:指定用于签发证书的CA私钥为 ca-key.pem。
  • -set_serial 01:为证书设置一个唯一的序列号。每个证书都应该有一个唯一的序列号,以确保其唯一性。这里使用01作为序列号,实际应用中可以根据需要递增。
  • -out server-cert.pem:指定输出的服务器证书文件名为server-cert.pem。

作用:

  • 这个命令使用CA证书和私钥对服务器的CSR进行签名,生成服务器的正式证书(server-cert.pem)。
  • 服务端:服务器将使用正式证书server-cert.pem和私钥server-key.pem来与客户端建立加密连接。客户端会验证服务器证书是否由可信的CA签发(即ca.pem)。
3、生成客户端证书

第一步:生成客户端的私钥和证书签名请求(CSR)
示例:

openssl req -newkey rsa:2048 -days 365 -nodes -keyout client-key.pem -out client-req.pem

解释:

  • 这个命令与生成服务器证书的第一步类似,生成了客户端的私钥(client-key.pem)和证书签名请求(client-req.pem)。

作用:

  • 生成客户端的私钥和CSR,准备向CA申请签发客户端证书。

第二步:使用CA证书签发客户端证书
示例:

openssl x509 -req -in client-req.pem -days 365 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem

解释:

  • 这个命令与生成服务器证书的第二步类似,使用CA证书和私钥对客户端的CSR进行签名,生成客户端的正式证书(client-cert.pem)。

作用:

  • 客户端:客户端将使用client-cert.pem和client-key.pem来与服务器建立加密连接。服务器会验证客户端证书是否由可信的CA签发(即ca.pem)。

简单说明:
从上面配置服务器证书的过程可以看出,签发服务器的过程都是一样的。
第一步都是先生成机器的私钥和CSR的请求文件(请求文件主要用于第二步配置CA证书)。
第二步,使用上一步的请求文件,生成正式的服务器证书。
两步执行后,最终给我们提供了适用于SSL连接的秘钥和客户端证书文件。

说明:
除了上诉手动创建和配置证书外,你也可以从商业证书颁发机构(如Let’s Encrypt、DigiCert)购买SSL证书,以获得更高的信任度。

(3)、配置MySQL启用SSL/TLS
1、配置MySQL使用SSL证书

证书生成完了之后,就可以配置Mysql启用SSL连接了。

在MySQL配置文件(my.cnf或my.ini)中添加以下配置:
示例:

[mysqld]
ssl-ca=/etc/mysql/ssl/ca.pem
ssl-cert=/etc/mysql/ssl/server-cert.pem
ssl-key=/etc/mysql/ssl/server-key.pem
#可选:强制所有连接使用 SSL
#require_secure_transport=ON

解释:
配置为指定服务端的相关证书,分别为ca证书,服务端正式证书,服务端证书秘钥等。

配置修改保存后需要重新启动Mysql服务后才会生效。
示例:

sudo systemctl restart mysql
或者
sudo service mysql restart
2、启用强制SSL连接

除了上述在配置文件中配置启用SSL外,你还可以通过SQL命令要求客户端必须使用SSL连接。对于特定用户,可以使用REQUIRE SSL选项。
sql示例:

ALTER USER 'user'@'host' REQUIRE SSL;
3、验证SSL连接

你可以使用mysql客户端连接到数据库,并验证是否启用了SSL。
命令示例:

mysql -u user -p --ssl-ca=/etc/mysql/ssl/ca.pem --ssl-cert=/etc/mysql/ssl/client-cert.pem --ssl-key=/etc/mysql/ssl/client-key.pem

解释:
当Mysql服务端启用了SSL后,客户端进行连接进需要指定相关的证书文件进行连接确认。
如ca证书,客户端证书和私钥等。

在MySQL中运行以下命令,检查是否启用了SSL。
sql示例:

SHOW STATUS LIKE 'Ssl_cipher';

解释:
如果返回非空结果,则表示SSL已成功启用。

(4)、Java客户端连接MySQL并启用SSL

1、导入依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

2、配置JDBC URL以启用SSL
在Java程序中,你可以通过JDBC URL来启用SSL连接。以下是启用SSL的典型JDBC URL格式:

String url = "jdbc:mysql://localhost:3306/your_database?useSSL=true&requireSSL=true";

解释:

  • useSSL=true:启用SSL连接。
  • requireSSL=true:强制使用SSL连接。如果服务端没有启用SSL,连接将失败。

3、提供CA证书、客户端证书和私钥
如果你启用了双向认证(即客户端也需要提供证书),你需要在JDBC URL中指定CA证书、客户端证书和私钥的路径。可以通过javax.net.ssl.trustStore和javax.net.ssl.keyStore系统属性来指定这些文件。

方法1:通过系统属性指定证书

System.setProperty("javax.net.ssl.trustStore", "/path/to/ca.pem");
System.setProperty("javax.net.ssl.trustStoreType", "PEM");  // 如果是PEM格式的CA证书
System.setProperty("javax.net.ssl.keyStore", "/path/to/client.p12");  // 客户端证书和私钥的PKCS12文件
System.setProperty("javax.net.ssl.keyStorePassword", "your_password");  // PKCS12文件的密码
System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");

// 创建数据库连接
Connection conn = DriverManager.getConnection(url, "your_username", "your_password");

方法2:通过JDBC URL参数指定证书
MySQL JDBC驱动也支持直接在JDBC URL中指定证书和私钥的路径。你可以使用以下参数:

String url = "jdbc:mysql://localhost:3306/your_database" +
             "?useSSL=true" +
             "&requireSSL=true" +
             "&clientCertificateKeyStoreUrl=file:/path/to/client.p12" +
             "&clientCertificateKeyStorePassword=your_password" +
             "&clientCertificateKeyStoreType=PKCS12" +
             "&trustCertificateKeyStoreUrl=file:/path/to/ca.pem" +
             "&trustCertificateKeyStoreType=PEM";
             
// 创建数据库连接
Connection conn = DriverManager.getConnection(url, "your_username", "your_password");

解释:

  • clientCertificateKeyStoreUrl:指定客户端证书和私钥的PKCS12文件路径。
  • clientCertificateKeyStorePassword:指定PKCS12文件的密码。
  • clientCertificateKeyStoreType:指定客户端证书和私钥的存储格式(通常是PKCS12)。
  • trustCertificateKeyStoreUrl:指定CA证书的路径。
  • trustCertificateKeyStoreType:指定CA证书的存储格式(通常是PEM)。

4、完整示例代码
以下是一个完整的Java示例,展示了如何使用SSL连接到MySQL数据库。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class MySQLSSLConnectionExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/your_database" +
                     "?useSSL=true" +
                     "&requireSSL=true" +
                     "&clientCertificateKeyStoreUrl=file:/path/to/client.p12" +
                     "&clientCertificateKeyStorePassword=your_password" +
                     "&clientCertificateKeyStoreType=PKCS12" +
                     "&trustCertificateKeyStoreUrl=file:/path/to/ca.pem" +
                     "&trustCertificateKeyStoreType=PEM";

        String username = "your_username";
        String password = "your_password";

        try (Connection conn = DriverManager.getConnection(url, username, password);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT VERSION()")) {
            if (rs.next()) {
                System.out.println("Connected to MySQL server version: " + rs.getString(1));
            }
            // 检查是否使用了 SSL
            try (ResultSet sslRs = stmt.executeQuery("SHOW STATUS LIKE 'Ssl_cipher'")) {
                if (sslRs.next()) {
                    System.out.println("SSL Cipher: " + sslRs.getString("Value"));
                } else {
                    System.out.println("SSL is not being used.");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

4、SSL/TLS的性能影响

启用SSL/TLS会带来一定的性能开销,尤其是在高并发场景下。根据MySQL官方文档,SSL/TLS的性能开销大约在5%到10%之间。如果你的应用程序对网络延迟敏感,建议在生产环境中进行性能测试,评估SSL/TLS对系统的影响。

5、证书签发与RSA加密的区别

(1)、RSA加密
1、什么是RSA?

RSA(Rivest–Shamir–Adleman)是一种非对称加密算法,广泛用于加密通信、数字签名和身份验证。

RSA的核心思想是基于一对密钥:

  • 公钥(Public Key):用于加密数据或验证签名。
  • 私钥(Private Key):用于解密数据或生成签名。
2、RSA的工作原理
  • 加密:发送方使用接收方的公钥对消息进行加密,只有拥有对应私钥的接收方才能解密消息。
  • 签名:发送方使用自己的私钥对消息进行签名,接收方使用发送方的公钥验证签名的真实性。
3、应用场景
  • 加密通信:确保消息在传输过程中不会被窃听或篡改。
  • 数字签名:确保消息的完整性和发送者的身份真实性。
(2)、证书签名
1、什么是证书?

数字证书(如SSL/TLS证书)是一种电子文档,用于证明某个实体(如服务器、客户端或个人)的身份。

证书通常包含以下信息:

  • 主体名称(Subject):证书所有者的身份信息(如域名、组织名称等)。
  • 公钥(Public Key):与证书所有者对应的公钥。
  • 颁发者(Issuer):签发该证书的证书颁发机构(CA)。
  • 有效期(Validity):证书的有效起始时间和结束时间。
  • 签名(Signature):由CA使用其私钥对证书内容进行的数字签名。
2、证书签名的工作原理
  • 证书申请:实体(如服务器或客户端)生成一对公钥和私钥,并向CA提交证书签名请求(CSR),其中包含公钥和其他身份信息。
  • CA签名:CA验证实体的身份后,使用其私钥对CSR中的内容进行签名,生成正式的数字证书。
  • 证书验证:当其他实体(如客户端)接收到证书时,它会使用CA的公钥验证证书的签名是否有效。如果签名有效,说明证书是由可信的CA签发的,且证书中的公钥是属于证书声明的主体。
3、应用场景
  • SSL/TLS加密通信:客户端通过验证服务器的证书来确保服务器的身份是可信的,并使用证书中的公钥与服务器建立加密连接。
  • 代码签名:开发者可以使用数字证书对软件进行签名,用户可以通过验证签名来确保软件的来源是可信的。
(3)、证书签名与RSA加密的关系

虽然证书签名和RSA加密都涉及到非对称加密,但它们的应用场景和具体操作有所不同。以下是它们之间的关系和区别:

1、相同点
  • 都使用非对称加密:两者都依赖于公钥和私钥对。证书签名中,CA使用其私钥对证书进行签名;RSA加密中,发送方使用接收方的公钥加密数据,接收方使用私钥解密数据。
  • 都涉及数字签名:证书签名本质上是一种数字签名,用于验证证书的真实性和完整性。RSA加密也可以用于生成和验证数字签名。
2、不同点

在这里插入图片描述

3、具体示例
  • 证书签名:假设你有一个Web服务器,你需要向CA申请一个SSL/TLS证书。你生成一对公钥和私钥,并将公钥和服务器信息提交给CA。CA使用其私钥对这些信息进行签名,生成一个数字证书。客户端在连接到服务器时,会使用CA的公钥验证证书的签名,以确保服务器的身份是可信的。
  • RSA加密:假设你想要加密一条消息发送给某人。你可以使用对方的公钥对消息进行加密,只有对方使用其私钥才能解密这条消息。同样,你也可以使用自己的私钥对消息进行签名,对方可以使用你的公钥验证签名的真实性。
(4)、证书和RSA总结
  • 证书签名和RSA加密都基于非对称加密,但它们的应用场景不同。
  • 证书签名主要用于验证身份,确保某个实体(如服务器或客户端)的身份是可信的。它通过CA的私钥对证书进行签名,并通过CA的公钥验证签名。
  • RSA加密主要用于加密通信或生成/验证数字签名。它允许发送方使用接收方的公钥加密消息,接收方使用私钥解密消息,或者发送方使用自己的私钥对消息进行签名,接收方使用发送方的公钥验证签名。
    在SSL/TLS协议中,证书签名和RSA加密通常是结合使用的:
  • 证书签名用于验证服务器的身份。
  • RSA加密用于加密通信过程中的密钥交换或数据传输。

三、SQL注入(SQL Injection)

1、什么是SQL注入?

SQL注入是一种攻击技术,攻击者通过在应用程序的输入字段中插入恶意的SQL代码,绕过应用程序的逻辑,执行未经授权的数据库操作。SQL注入通常发生在应用程序没有对用户输入进行适当的验证或转义时。

2、SQL注入的危害

  • 数据泄露:攻击者可以通过SQL注入获取敏感数据,如用户密码、信用卡信息等。
  • 数据篡改:攻击者可以修改或删除数据库中的数据,导致业务中断或数据丢失。
  • 权限提升:攻击者可以通过SQL注入获取管理员权限,完全控制数据库。
  • 远程代码执行:在某些情况下,攻击者可以通过SQL注入执行操作系统命令,进一步控制服务器。

3、SQL注入的示例

假设有一个登录表单,应用程序使用以下SQL查询来验证用户:

原本sql应该为:

SELECT * FROM users WHERE username = 'input_username' AND password = 'input_password';

如果攻击者在username字段中输入’’ OR ‘1’='1,查询将变为:
sql注入示例:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'input_password';

由于’1’='1’始终为真,查询将返回所有用户的记录,导致攻击者成功登录。

4、MyBatis中的SQL注入风险

在MyBatis中,SQL注入的风险主要来自于以下几种情况:

  • 动态SQL:当使用if、choose、foreach等标签构建动态SQL时,如果用户输入没有经过适当的处理,可能会导致SQL注入。
  • 字符串拼接:在某些情况下,开发者可能会手动拼接SQL语句,而不是使用MyBatis提供的安全机制,这也会引入SQL注入风险。
  • 未绑定参数:如果直接将用户输入作为SQL语句的一部分,而没有使用参数绑定,可能会导致SQL注入。

5、MyBatis中SQL注入的防范

(1)、使用#{}参数绑定

#{}是MyBatis提供的安全参数绑定机制。它会自动对用户输入进行转义,确保输入不会被解释为SQL代码。因此,应该尽量避免使用${},而是使用#{}来绑定参数。

不安全的动态SQL示例:

<select id="getUsersByTableName" parameterType="String" resultType="User">
    SELECT * FROM ${tableName}  <!-- 危险!${} 直接插入用户输入 -->
</select>

安全的动态SQL示例:

<select id="searchUsers" parameterType="map" resultType="User">
    SELECT * FROM users
    <where>
        <if test="username != null">
            AND username = #{username}  <!-- 安全!使用 #{} 绑定参数 -->
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </where>
</select>

优点:

  • 安全性高:#{}会自动对用户输入进行转义,防止SQL注入。
  • 性能优化:预编译SQL语句可以提高执行效率。
  • 易于维护:代码更清晰,减少了拼接SQL语句的复杂性。
  • 避免使用 处理用户输入:除非你完全信任输入来源,否则不要使用 {}处理用户输入:除非你完全信任输入来源,否则不要使用 处理用户输入:除非你完全信任输入来源,否则不要使用{}。
  • 动态表名或列名:如果确实需要使用${},请确保这些值来自应用程序内部,而不是用户输入。
(2)、使用@Param注解

在MyBatis的注解风格中,使用@Param注解可以明确指定参数名称,确保参数绑定的安全性。@Param注解可以用于方法参数,确保每个参数都被正确绑定到SQL语句中。

使用@Param注解的示例:

public interface UserMapper {
    @Select("SELECT * FROM users WHERE username = #{username} AND age = #{age}")
    List<User> searchUsers(@Param("username") String username, @Param("age") Integer age);
}

解释:
@Param实际上也是#{}的原理(参数绑定机制),即不会改变sql结构,把入参当成值去替换sql语句中的参数。

优点:

  • 明确参数名称:@Param注解可以确保每个参数都被正确绑定,避免混淆。
  • 安全性高:所有参数都通过{}进行绑定,防止SQL注入。
(3)、使用MyBatis Plus

MyBatis Plus是MyBatis的增强工具,提供了更多的功能和安全性增强。MyBatis Plus内置了许多安全机制,可以帮助开发者更轻松地防止SQL注入。

MyBatis Plus的安全特性:

  • 内置的条件构造器:MyBatis Plus提供了Wrapper和QueryWrapper等条件构造器,可以安全地构建动态SQL,避免手动拼接SQL语句。
  • 自动参数绑定:MyBatis Plus会自动对用户输入进行参数绑定,防止SQL注入。
  • 链式调用:MyBatis Plus支持链式调用,代码更加简洁,减少了出错的可能性。

MyBatis Plus示例:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface UserMapper extends BaseMapper<User> {
    default List<User> searchUsers(String username, Integer age) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        if (username != null && !username.isEmpty()) {
            queryWrapper.eq("username", username);
        }
        if (age != null) {
            queryWrapper.eq("age", age);
        }
        return this.selectList(queryWrapper);
    }
}

优点:

  • 安全性高:QueryWrapper会自动对用户输入进行参数绑定,防止SQL注入。
  • 代码简洁:链式调用使得代码更加简洁,减少了出错的可能性。
(4)、严格验证和过滤用户输入

即使使用了#{}参数绑定,仍然建议对用户输入进行严格的验证和过滤。确保输入符合预期的格式和类型,避免意外的输入导致问题。

正则表达式验证:
对于字符串输入,使用正则表达式验证输入格式,确保输入只包含合法字符。

import java.util.regex.Pattern;

public class InputValidator {
    private static final Pattern USERNAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_]+$");
    private static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$");

    public static boolean isValidUsername(String username) {
        return USERNAME_PATTERN.matcher(username).matches();
    }

    public static boolean isValidEmail(String email) {
        return EMAIL_PATTERN.matcher(email).matches();
    }
}

限制输入长度:
设置合理的输入长度限制,防止过长的输入导致缓冲区溢出或其他漏洞。

public class InputValidator {
    public static boolean isInputLengthValid(String input, int maxLength) {
        return input != null && input.length() <= maxLength;
    }
}
(5)、启用SQL注入防护插件

某些Web应用程序防火墙(WAF)和安全插件(如ModSecurity)可以检测并阻止常见的SQL注入攻击。虽然这些工具不能替代良好的编程实践,但可以在一定程度上增强安全性。

(6)、定期审查和测试代码

定期审查代码,查找潜在的SQL注入漏洞。可以使用静态代码分析工具(如SonarQube)或动态渗透测试工具(如OWASP ZAP)来检测和修复漏洞。

乘风破浪会有时,直挂云帆济沧海!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/953875.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

抽奖滚动功能

代码 <template><div class"box"><video class"video" src"../../assets/video/底层.mp4" loop autoplay muted></video><img class"choujiang" src"../../assets/image/抽奖1.png" alt"&…

【Python】Python之locust压测教程+从0到1demo:基础轻量级压测实战(1)

文章目录 一、什么是Locust二、Locust 架构组成三、实战 Demo准备一个可调用的接口编写一个接口测试用例编写一个性能测试用例执行性能测试用例代码1、通过 Web UI 执行&#xff08;GUI模式&#xff09;2、通过命令行执行&#xff08;非GUI模式&#xff09; 小知识&#xff1a;…

Microsoft

Microsoft Word目录1.目录编号与文字的间距设置2. 目录编号缩进设置 Excel函数MID&#xff08;提取字符&#xff09;CONCAT&#xff08;组合字符串&#xff09;EXACT&#xff08;比较字符串&#xff09; PowerPointwindows 11 恢复右键传统菜单 Word 目录 1.目录编号与文字的…

用 Python 处理 CSV 和 Excel 文件

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

JS后盾人--再一次的走进JS?

程序跑起来与避免延迟 如果你讲JS&#xff0c;你就不可能只讲JS 后盾人说开发就要用VScode&#xff08;确实&#xff0c;Windows和Linux都可以跑&#xff09; 然后就是第一天开发的时候装的那些插件 前端访问流程基本分析 托管到服务器上的东西&#xff0c;谁访问下载到谁的…

Android 调用系统服务接口获取屏幕投影(需要android.uid.system)

媒体投影 借助 Android 5&#xff08;API 级别 21&#xff09;中引入的 android.media.projection API&#xff0c;您可以将设备屏幕中的内容截取为可播放、录制或投屏到其他设备&#xff08;如电视&#xff09;的媒体流。 Android 14&#xff08;API 级别 34&#xff09;引入…

PT8M2102 触控型 8Bit MCU

1. 产品概述 PT8M2102 是一款基于 RISC 内核的 8 位 MTP 单片机&#xff0c;内部集成了电容式触摸感应模块、 TIMER 、 PWM、 LVR 、 LVD 、 WDT 等外设&#xff0c;其主要用作触摸按键开关&#xff0c;广泛适用于触控调光、电子玩具、消 费电子、家用电器等领域&am…

LangGraph 教程:初学者综合指南(2)

工具集成 将工具集成到 LangGraph 聊天机器人中可以显着增强其功能&#xff0c;使其能够按照您喜欢的方式访问和处理信息。 让我们修改上一节中创建的基本聊天机器人&#xff0c;以包含一个可以在网络上搜索信息的工具。我们将使用langchain_中community.tools TavilySearchR…

项目练习:若依管理系统字典功能-Vue前端部分

文章目录 一、情景说明二、若依Vue相关代码及配置1、utils代码2、components组件3、api接口代码4、main.js配置 三、使用方法1、html部分2、js部分 一、情景说明 我们在做web系统的时候&#xff0c;肯定会遇到一些常量选择场景。 比如&#xff0c;性别&#xff1a;男女。 状态…

oracle闪回表

文章目录 闪回表案例1&#xff1a;&#xff08;未清理回收站时的闪回表--成功&#xff09;案例2&#xff08;清理回收站时的闪回表--失败&#xff09;案例3&#xff1a;彻底删除表&#xff08;不经过回收站--失败&#xff09;案例4&#xff1a;闪回表之后重新命名新表总结1、删…

TensorFlow Quantum快速编程(基本篇)

一、TensorFlow Quantum 概述 1.1 简介 TensorFlow Quantum(TFQ)是由 Google 开发的一款具有开创性意义的开源库,它宛如一座桥梁,巧妙地将量子计算与 TensorFlow 强大的机器学习功能紧密融合。在当今科技飞速发展的时代,传统机器学习虽已取得诸多瞩目成就,然而面对日益…

K8s数据存储之详解(Detailed Explanation of K8s Data Storage)

K8s数据存储相关概念详解&#xff08;临时存储&#xff0c;节点存储&#xff0c;网络存储&#xff0c;PV/PVC&#xff09; 本篇文章分享一下存储卷和数据持久化的相关概念&#xff1a; 存储卷概述 临时存储卷&#xff08;Ephemeral Volumes&#xff09; 节点存储卷&#xff…

java求职学习day12

1 泛型机制&#xff08;熟悉&#xff09; 1.1 基本概念 &#xff08;1&#xff09;通常情况下集合中可以存放不同类型的元素&#xff0c;是因为将所有对象都看作Object类型放入&#xff0c;因此从集合中取出元素时&#xff0c;也是Object类型&#xff0c;为了表达该元素真实的…

相加交互效应函数发布—适用于逻辑回归、cox回归、glmm模型、gee模型

在统计分析中交互作用是指某因素的作用随其他因素水平变化而变化&#xff0c;两因素共同作用不等于两因素单独作用之和(相加交互作用)或之积(相乘交互作用)。相互作用的评估是尺度相关的&#xff1a;乘法或加法。乘法尺度上的相互作用意味着两次暴露的综合效应大于&#xff08;…

Spring Boot 2 学习全攻略

Spring Boot 2 学习资料 Spring Boot 2 学习资料 Spring Boot 2 学习资料 在当今快速发展的 Java 后端开发领域&#xff0c;Spring Boot 2 已然成为一股不可忽视的强大力量。它简化了 Spring 应用的初始搭建以及开发过程&#xff0c;让开发者能够更加专注于业务逻辑的实现&am…

【面试题】技术场景 4、负责项目时遇到的棘手问题及解决方法

工作经验一年以上程序员必问问题 面试题概述 问题为在负责项目时遇到的棘手问题及解决方法&#xff0c;主要考察开发经验与技术水平&#xff0c;回答不佳会影响面试印象。提供四个回答方向&#xff0c;准备其中一个方向即可。 1、设计模式应用方向 以登录为例&#xff0c;未…

30分钟内搭建一个全能轻量级springboot 3.4 + 脚手架 <1> 5分钟快速创建一个springboot web项目

快速导航 <1> 5分钟快速创建一个springboot web项目 <2> 5分钟集成好最新版本的开源swagger ui&#xff0c;并使用ui操作调用接口 <3> 5分钟集成好druid并使用druid自带监控工具监控sql请求 <4> 5分钟集成好mybatisplus并使用mybatisplus generator自…

【Rust自学】11.10. 集成测试

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.10.1. 什么是集成测试 在Rust里&#xff0c;集成测试完全位于被测试库的外部。集成测试调用库的方式和其他代码一样&#xff0c;这也…

JAVA实现2048小游戏(附源码)

文章目录 一、设计来源2048小游戏讲解1.1 主界面1.2 4*4难度界面1.3 5*5难度界面1.4 6*6难度界面1.5 挑战失败提示界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载更多优质源码分享 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/a…

【自动化测试】—— Appium安装配置保姆教程(图文详解)

目录 一. 环境准备 二. JDK安装 1. 下载JDK 2. 安装JDK 3. 配置环境 4. 验证安装 三. Android SDK安装 1. 下载Android SDK 2. 安装Android SDK 3. 安装工具 4. 配置环境 5. 验证安装 四. NodeJS安装 1. 下载NodeJS 2. 安装NodeJS 3. 验证安装 4. 安装淘宝镜像…