1. 术语认证、授权、访问控制、权限和许可
2. 账号的基本知识2.1 权限分为两种:与对象(例如表、数据库和视图)相关的和与对象无关的。
对象指定权限赋予你访问特定对象的权限。
全局权限可以让你执行一些功能。
2.2 授权表以下是所有的授权表,显示的次序就是当MySQL检查一个验证通过的用户是否允许使用某个操作的查询顺序:
- user
- db
- host
- tables_priv
- columns_priv
- procs_priv
2.3 如何检查权限MySQL在授权表里检查权限的次序就是上面提到的那样。服务器会再找到匹配的功能授权后停止检查。
2.4 增加、删除和查看授权使用grant来增加新用户账号,或者增加一项权限;但revoke只能删除权限,无法删除账号。想删除账号,只能使用drop user来做。
使用show grants来查看一个用户的授权情况,其结果的显示内容就是根据该用户当前的权限重新创建用户时所用的语句。
如果想查看其中特定一个的授权情况,就必须指定它的用户名和主机名。默认的主机名是%。
mysql> show grants for root@localhost;
2.5 设置MySQL 权限系统管理员账号:
system administrators管理的是“物理”服务器,包括操作系统、Unix登陆账号等等;
database administrators 专注于数据库服务器的管理。
- mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY 'p4ssword' WITH GRANT OPTION;
数据库管理员账号:
- mysql> GRANT ALL PRIVILEGES ON *.* TO 'dba'@'localhost' IDENTIFIED BY 'p4ssword' WITH GRANT OPTION;
每个雇员一个账号:
- mysql> GRANT INSERT,UPDATE PRIVILEGES ON widgets.orders TO 'tera'@'%.widgets.example.com' IDENTIFIED BY 'p4ssword';
模拟组:
日志,只写访问:
- mysql> GRANT INSERT ON logs.* TO 'logger'@'%.widgets.example.com' IDENTIFIED BY ‘p4ssword
备份:
- mysql> GRANT SELECT,LOCK TABLES,FILE, RELOAD ON *.* TO 'backup'@'localhost' IDENTIFIED BY 'p4ssword';
操作和监控:
- mysql> GRANT PROCESS,SHUTDOWN ON *.* TO 'noc'@'monitorserver.noc.widgets.example.com' IDENTIFIED BY 'p4ssword';
可能还要把super赋予他,这可以让他能执行show innodb status.
2.6 权限在MySQL 4.1 里的变化
2.7 权限在MySQL 5.0 里的变化
存储过程:
这些程序能在两种安全上下文里执行:作为定义者(例如那个定义程序的用户)和作为调用者(例如那个调用程序的用户)。
存储程序一般被用作代理人,把特定的权限赋予那些无法直接访问表的用户。常用的方法是创建一个授权用户,热按后,作为定义者创建一些列的存储程序,并给予它们SQL SECURITY DEFINER特性。
触发器:
INFROMATION_SCHEMA表的权限:
2.8 权限与性能权限太多
权限的粒度过细
列的权限和查询缓冲区
my.cnf里增加skip_name_resolve
2.9 常见问题和解决方案通过localost还是127.0.0.1 来连接:$ mysql --host=localhost #通过一个Unix socket连接
$ mysql --host=127.0.0.1
or
$ mysql --host=localhost --protocol=tcp #通过TCP/IP来连接
MySQL不会拿localhost作通配符匹配,换句话说,同时指定user@'%'和user@localhost不是多余的。
安全使用临时表:除了在特地为临时表准备的数据库里,其他地方都不接受用户的这些权限:
- mysql> create database temp;
- mysql> grant select,insert,update,delete,drop,alter,index,create temporary tables on temp.* to analyst@'%';
不允许没有密码的访问:[cliet]
passord
关闭匿名用户:运行MySQL提供的mysql_secure_installation程序来移除匿名用户;
/usr/local/mysql/bin/mysql_secure_installation
记得给主机名单独加引号:
- mysql> GRANT USAGE ON *.* TO 'fred@%'; #错误
- mysql> GRANT USAGE ON *.* TO 'fred'@'%';
不要重用用户名:赋予SELECT权限,允许执行show create table不要授予mysql数据库的权限不要随便授予SUPER权限:MySQL会为有SUPER权限的用户保留一条连接,哪怕是服务器已经达到了max_connections的极限。
用通配符数据库授予权限:取消特定的权限:如果你授予权限是全局化的,那你就无法用非全局话的方式来取消它们:
mysql> GRANT SELECT ON *.* TO 'user';
mysql> REVOKE SELECT ON sakila.film FROM user; #会报错:没有表级权限匹配这个指定的标准。
用户甚至在REVOKE之后还能连接到数据库:mysql> revoke all privileges on ...;
这个用户还是可以连接进来的,因为revoke没有删除用户账号,它只删除了权限。你必须使用drop user 彻底删除他的账号。
当无法授予或取消一项权限时:除了GRANT选项之外,你必须拥有要授予或取消的那个权限。这项安全措施可以防止用户之间逐级提高自己的权限。
如果你试着要取消所有权限,那你必须要有CREATE USER权限。
不可见的权限:show grant 并不能真正显示出一个用户的所有权限:它仅仅是显示出那些明确授予该用户的权限。一个用户也可以拥有别的许可,可能是由于这些许可被授权给了匿名用户。
主机名和数据库匹配时,首先匹配最具体的名称,不具体的匹配项的权限会被隐藏起来,哪怕它们的名字更加随意。
创建新用户:
mysql> GRANT USAGE ON *.* TO 'gotcha'@'%' IDENTIFIED BY 'p4ssword';
授权所有权限给新创建的用户:
mysql> GRANT ALL PRIVILEGES ON `%`.* TO 'gotcha'@'%';
废弃的权限:当删除对象时,MySQL不会清除那些旧权限.
- mysql> grant all privileges on my_db.* to analyst;
- mysql> select host,user from mysql.user;
- +-----------+-----------+
- | host | user |
- +-----------+-----------+
- | % | analyst |
- mysql> show grants for analyst;
- +----------------------------------------------------+
- | Grants for analyst@% |
- +----------------------------------------------------+
- | GRANT USAGE ON *.* TO 'analyst'@'%' |
- | GRANT ALL PRIVILEGES ON `my_db`.* TO 'analyst'@'%' |
- +----------------------------------------------------+
- 2 rows in set (0.00 sec)
- mysql> select d.host,d.db,d.user from mysql.db AS d left outer join information_schema.schemata as s on s.schema_name like d.db where s.schema_name is null;
- +------+-------+---------+
- | host | db | user |
- +------+-------+---------+
- | % | my_db | analyst |
- +------+-------+---------+
- 1 row in set (0.00 sec)
- mysql> revoke all privileges,grant option from `analyst`@`%`;
- Query OK, 0 rows affected (0.00 sec)
- mysql> show grants for analyst;
- +-------------------------------------+
- | Grants for analyst@% |
- +-------------------------------------+
- | GRANT USAGE ON *.* TO 'analyst'@'%' |
- +-------------------------------------+
- 1 row in set (0.00 sec)
- mysql> drop user analyst;
- Query OK, 0 rows affected (0.00 sec)
在MySQL 5.0及更新版本里,INFORMATION_SCHEMA表能帮你找出那些陈旧的权限:
- mysql> select d.host,d.db,d.user from mysql.db AS d left outer join information_schema.schemata as s on s.schema_name like d.db where s.schema_name is null;
3. 操作系统安全:不要用特权账号运行MySQL
让你的操作系统随时保持更新
在数据库主机上限制登录
将产品与其他任何东西隔离开
审查你的服务器
使用最强大的就意味着管用
4. 网络安全:4.1 只有localhost的连接[mysqld]
bind_address=127.0.0.1
4.2 防火墙没有默认的路由
4.3 在DMZ里的MySQL4.4 连接加密和隧道技术虚拟私有网
MySQLLi的SSL:
mysql> show variables like 'have_openssl';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_openssl | DISABLED |
+---------------+----------+
1 row in set (0.00 sec)
SSH隧道技术:
让我们假定你想在一台GNU/Linux工作站和db.example上的MySQL 服务器之间建立一个加密连接。在工作站这边,需要执行下述命令:
$ ssh -N -f -L 4406:db.example.com:3306
这就在工作站的TCP 4406端口与db.example.com的3306端口之间建立了一个隧道。现在,可以通过隧道从工作站连接到MySQL了:
$ mysql -h 127.0.0.1 -P 4406
4.5 TCP 封装$ ./configure --with-libwrap=/usr/local/tcp_wrappers
vi /etc/hosts.deny
ALL:ALL
vi /etc/hosts.allow
mysqld:192.168.1.0/255.255.0.:allow
vi /etc/services
mysql 3306/tcp #MySQL Server
4.6 自动主机封锁MySQL在防止基于网络的攻击方面提供了一些帮助:如果它注意到有太多的有害连接来自一个特定的主机,他就会封锁所有来自该主机的连接。
服务器变量max_connection_errors决定了MySQL在开始封锁主机前可以允许有多少个有害连接。“有害连接”指的是那些永不完成的连接
(结果是一直占用着一个可用的MySQL会话)。
当MySQL封锁了一个主机时,它会把相应的消息写进日志,消息内容如下:
Host 'host.xxx.com' blocked because of many connection errors.
Unblock with 'mysqladmin' flush-hosts';
通过mysqladmin' flush-hosts 让主机取消封锁,该命令仅仅执行了一个FLUSH HOSTS的SQL命令,她会清空MySQL的主机缓存表,还会解除所有
被封锁主机的封锁,对于单独一个主机他无法做到。
5. 数据加密5.1 密码散列
MySQL提供了3个用户函数可用于密码的散列:ENCRYPT()、SHA1()和MD5()。
mysql> select md5('p4ssword'),encrypt('p4ssword'),sha1('p4ssword') \G;
存储散列数据:
mysql> insert into user_table(user,pass) values('user',md5('p4ssword'));
验证一个密码:
my $sth = $dbh->prepare('SELECT * FROM user_table'.'where user = ? AND pass = MD5(?)');
$sth->execute($username,$password);
5.2 加密的文件系统
5.3 应用层的加密
5.4 源代码修改
6.在 Chroot环境使用MySQL