欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

细聊MySQL的安全机制

程序员文章站 2024-02-17 13:16:22
...

MySQL作为系统的数据库,在安全性方面有非常高的要求。如果一个系统的数据库被非法进入或窃听,则系统的数据将受到非常严重的威胁,轻则数据、密码被盗,重则导致整个系统瘫痪。所以数据库的安全对于系统来说是非常重要的。 本文将从MySQL的服务器启动与客户

MySQL作为系统的数据库,在安全性方面有非常高的要求。如果一个系统的数据库被非法进入或窃听,则系统的数据将受到非常严重的威胁,轻则数据、密码被盗,重则导致整个系统瘫痪。所以数据库的安全对于系统来说是非常重要的。


本文将从MySQL的服务器启动与客户端访问、操作及链路三方面来阐述MySQL的安全机制。


一、MySQL的服务器启动与客户端访问。
1、服务器启动,启动服务器在安全方面的影响主要是启动它的用户。默认情况下,MySQL不允许使用root账号启动。我们应该建立一个只能操作MySQL安装目录与数据目录的非交互式账号来运行mysqld服务器。另外,服务器最好针对指定客户机开放,应将服务器置于iptables后,如果过让任意主机都能通过telnet的方式连线到服务器,也将是不安全的。telnet的测试方式为shell > telnet ip(服务器的ip)3306(服务器的默认端口)
2、客户端访问,使用bin/mysql客户端工具登录时可以通过配置文件及直接在命令行添加参数两种方式。在登录时,我们需要使用密码才能进入,然而MySQL在安装后默认root账号是没有密码的。所以我们首先需要为root设置密码。如果root没有设置密码,那么可以通过以下方式设置:
2.1 shell > bin/mysql —user=root —host=127.0.0.1,回车后应该进入到mysql客户端的交互界面。
2.2 mysql > set password for ‘root’@‘127.0.0.1’ = password(’你设置的明文密码’)。这样127.0.0.1下的root密码就设置好了。需要注意的是,MySQL的登入账号不仅仅是用户名,而是用户名+IP或域名的方式确认唯一一个连线的。所以,如果该服务器的IP是192.168.1.5,在设置密码时我只设置了’root’@‘127.0.0.1’的密码,那么当用mysql —host=192.168.1.5 —user=root —password=’你设置的明文密码’登录时,会提示错误。所以,如果我们不在服务器本地登陆,那么我们还需要设置密码set password for ‘root’@‘192.168.1.5’=password(’你设置的明文密码’)。 另外一个需要注意的是,在设置密码时,我们使用了password()函数,password函数将明文密码转换成41个字节长的hash值。增加了密码的安全性。
如果我们将密码放置在配置文件中,记得将配置文件的访问权限设置成600或400,你也不想其它用户能够轻易的读到它吧。

二、MySQL操作的授权管理系统安全机制
2.1 MySQL权限管理系统的主要功能是验证客户端用户的登入以及验证该用户具体的对MySQL的操作权限,比如该用户可能只对某个数据库的其中某个表具有update权限和insert权限,那么系统将会禁止TA对其它的表进行写操作。但,以下的事情是权限系统办不到的:
2.1.1、你不能指定具体拒绝登入的用户。
2.1.2、你不能指定一个用户创建或删除一个数据库里的表,但又不让TA创建或删除该表所属的数据库。
2.1.3、用户的密码是全局性的,你不能针对数据库或表来设置密码。

2.2 MySQL将权限分为全局权限与对象权限。所谓的全局权限是与数据库、表、视图等不相干的权限,如密码的设置、用户的创建等。对象权限是相对于全局权限的,也就是与数据库、表、视图、列、索引等一切对象相关的权限。
关于权限的信息存储在mysql数据库中的user、db、tables_priv、columns_priv和prods_priv表里,在服务器启动后,程序会将权限表载入到内存里,客户端连入时会根据权限表验证用户的合法性,当客户端发出请求时,也会根据权限表验证用户操作的合法性。
下面我们可以大致看下我们能控制的具体权限以及这些权限作用的范围和控制权限的列名。


权限 控制权限的列名 作用范围
CREATE Create_priv 数据库、表、索引
DROP Drop_priv 数据库、表、视图
LOCK TABLES Lock_tables_priv 数据库
REFERENCES References_priv 数据库、表
EVENT Event_priv 数据库
ALTER Alter_priv
DELETE Delete_priv
INDEX Index_priv
INSERT Insert_priv 表、列
SELECT Select_priv 表、列
UPDATE Update_priv 表、列
CREATE TEMPORARY TABLES Create_tmp_table_priv
TRIGGER Trigger_priv
CREATE VIEW Create_view_priv 视图
SHOW VIEW Show_view_priv 视图
CREATE TABLESPACE Create_tablespace_priv 全局
CREATE USER Create_user_priv 全局
PROCESS Process_priv 全局
PROXY see proxies_priv table 全局
RELOAD Reload_priv 全局
REPLICATION CLIENT Repl_client_priv 全局
REPLICATION SLAVE Repl_slave_priv 全局
SHOW DATABASES Show_db_priv 全局
SHUTDOWN Shutdown_priv 全局
SUPER Super_priv 全局
ALL [PRIVILEGES]

全局
USAGE
全局


我们可以根据上表进行相应的权限设置。要设置权限,首先得知道我们设置的用户的当前的权限。利用下面的命令可知:
mysql > show grants for ‘user’@‘ip’;
再次强调下,虽然使用show grants for ‘user’;也可以显示,但’user’@‘ip’才代表mysql的一个唯一用户。调用命令后将显示如下结果:
GRANT USAGE ON *.* TO 'wangwei'@'%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' WITH MAX_QUERIES_PER_HOUR 20

USAGE是上表中的最后一行的值,是一个全局权限,只是代表能够进入到数据库。
*.*第一个*代表数据库名,第二个*代表表名。
IDENTIFIED BY后是密码
WITH后是权限参数,这里是限制每小时最多查询20次

然后开始设置我们自己的权限,如想设置某个表某列的查询权限则命令如下:
mysql > grant select(列名) on 数据库名.表名 to ‘用户名’@‘IP’;
这样,该用户即有指定列的查询权限了。

2.3 密码过期策略。如果你想让mysql用户隔一段时间设置一次密码,可用以下方法。
mysql > alter user ‘user’@‘ip’ password expire; 使该用户密码立即失效
mysql > alter user ‘user’@‘ip’ password expire interval 90 day; 每隔90天密码需要重设一次
mysql > alter user ‘user’@‘ip’ password expire never; 密码永不过期
还可以通过配置文件设置密码的默认过期时间如:
[mysqld]
default_password_lifetime=180

三、链路通讯安全。客户端通过网路与服务器通讯,除传输登录验证信息外还请求具体的数据库操作。所以服务器与客户端之间数据的保密性与完整性是非常重要的。这里,我们通过SSL来保证数据的安全性。
要使用SSL,需要MySQL服务器支持SSL协议。使用mysql > show variables like ‘have_ssl’;可以查询MySQL是否支持SSL。如果显示YES则该服务器正以SSL协议在运行。如果显示DISABLED则表示服务器支持SSL,但是没有开启SSL。如果显示其它,则表示MySQL服务器不支持SSL。需要重新下载新版本的MySQL或重新编译,启动SSL功能。本人所用的是MySQL 5.6的二进制版本,默认是支持SSL的。下面介绍下具体的配置方法。
配置SSL只需要四个参数ssl、ssl-ca、ssl-cert、ssl-key。ssl表明启动SSL功能。ssl-ca为CA证书的位置。ssl-cert为由CA签名的服务器证书所在位置。ssl-key为服务器的私钥位置。如果对CA及X509比较熟悉的朋友应该很好理解,这几个参数的作用。对不不理解的朋友最好去学习下CA认证与SSL协议的原理。不管你是否熟悉SSL。按照以下步骤应该也可以配置好安全链路的MySQL通讯。
下面介绍下具体的实现步骤:
1、下载和安装openssl。下载地址为http://www.openssl.org/source/。可以下载最新版openssl-1.0.1j.tar.gz。我就是用的最新版本。
安装方法:
shell > tar zxvf openssl-1.0.1j.tar.gz
shell > cd openssl-1.0.1j && ./config --prefix=/usr/local — openssldir=/usr/local/openssl
shell > make
shell > make install
安装后在/usr/local/bin下可找到openssl的命令。上面是很简单的源码编译安装方法,不用详细解释了。按照以上步骤应该可以安装好openssl。

2、建立CA证书
shell > mkdir newcerts && cd newcerts
shell > openssl genrsa 2048 > ca-key.pem 建立CA私钥
shell > openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca-cert.pem 建立CA根证书

3、建立CA签名的服务器证书及私钥
shell > openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pem 建立服务器证书请求文件及服务器私钥
shell > openssl rsa -in server-key.pem -out server-key.pem 加密私钥
shell > openssl x509 -req -in server-req.pem -days 3600 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem 签名服务器证书

生成的ca-cert.pem用于ssl-ca参数
生成的server-cert.pem用于ssl-cert参数
生成的server-key.pem用于ssl-key参数

服务器运行命令如下
mysqld —user=mysql —ssl —ssl-ca=/path/ca-cert.pem —ssl-cert=/path/server-cert.pem —ssl-key=/path/server-key.pem

客户端也可以创建SSL证书进行双向验证,也可以不做设置直接连接到服务器。运行后可用mysql > show variables like ‘have_ssl’;验证。如果结果显示YES。代表SSL设置成功。否则需要调试看看是什么问题。
如果出现问题,首先可以用shell> openssl verify -CAfile ca-cert.pem server-cert.pem看看证书是否正确生成。如果仍然有问题需要看下mysqld运行用户是否有权限读取证书。