1.MySQL访问权限
MySQL权限系统最重要的功能就是,验证从指定主机连接的用户,并将该用户与数据库上的权限关联。关于用户管理的箴言:
明确指定允许访问的用户 不要创建可以建表、删表的用户(table、db) 把密码跟与用户关联,不要把密码与对象关联(db、table、routine、etc……)
服务器在mysql库保存权限信息,服务启动时把这些表的内容读入内存,验证权限时依据内中的授权表比对。MySQL认为没有道理来自不同主机访问的同一个用户属于相同的身份,对于用户身份的是同时比对主机名、与用户名。
1.1.授权表
MySQL使用多个表管理用户权限,使用账户管理语句可以修改这些表的内容(CREATE USER、GRANT、REVOKE)。每个授权表包含“作用域”、“特权列”。user表作用域列决定是否拒绝或允许连接接入。user表的权限列作用于所有database。db表作用域决定那个用户允许访问那个db。db表的权限列控制访问db时允许的操作。……
表 | 作用域 | 说明 |
---|---|---|
user | Host、User | 用户账户访问实例 全局权限、…… |
db | Db、Host、User | 数据库级别权限 |
tables_priv | Table_name、Db、Host、User | 表级别权限 |
columns_priv | Columns_name、Table_name、Db、Host、User | …… |
procs_priv | Routine_name、Routine_type、Db、Host、User | 存储过程、函数…… |
proxies_priv | Proxied_host、Proxied_user、Db、Host、User | 代理用户权限 |
1.2.指定账户名称
“MySQL帐户名”由用户名和主机名组成。研究下如何编写账户名称,包括特殊值和通配符规则。
帐户名的语法格式:'user_name'@'host_name'。使用“CREATE_USER”、“GRANT”、“SET PASSWORD”这些操作时,帐户名写成'user_name',就被实例解读为'user_name'@'%'。帐户名在指定的时候,引号不是必须的;当user_name包含特殊字符(空格、-)、host_name包含特殊字符或通配符。就像'sunny bay'@'%.51cto.com'。如果账户名称这样指定'user@host',实例会认为其为'user@host'@'host_name'。
创建账户时,user_name和host_name分别存在了系统库user表的不同字段里。user_name区分大小写,host_name不区分大小写。当user_name指定成''@'host_name',认为就是个匿名用户。
host_name可以包含通配符。可以是域名、主机名、ip地址、ip/prefix。
mysql> create user 'david'@'10.0.0.0/26'; Query OK, 0 rows affected (0.00 sec) mysql> select count(*) from user where user='david'; +----------+ | count(*) | +----------+ | 1 | +----------+ 1 row in set (0.02 sec)
1.3.访问控制
一个用户连接到MySQL服务时,服务例程会检查用户账户名和密码。在user表可以找到对应条目时,就允许建立连接,否则就拒绝。(检查作用域)
允许创建连接会话后,进入访问控制第二阶段。对于该连接会话上发出的请求,确定要完成的操作,然后检查权限是否允许。(检查特权列)
1.4.权限变更生效
数据库实例验证连接时,依据内存中的授权表信息。当使用GRANT、REVOKE、SET PASSWORD、RENAME USER这些语句修改了mysql库中的授权表时,实例会检测到这些变化,并立即重新加载到内存授权表。
倘若修改mysql库中的授权表时,使用的是INSERT、UPDATE、DELETE时,就需要自己手动重新加载授权表。
# 刷新内存授权表 mysql> flush privileges; Query OK, 0 rows affected (0.00 sec) C:\Users\Administrator>mysqladmin -uroot -p flush-privileges Enter password: ****** C:\Users\Administrator>mysqladmin -uroot -p reload Enter password: ******
加载内存授权表后,对于已经建立连接会话的用户需要退出重新建立会话。数据库级别权限修改会在下一次执行use db_name时生效。表、列级别权限,会在下一次请求时生效。应用程序客户端,使用本地缓存的情况下刷新有可能无效。
当服务启动时,使用了选项--skip-grant-tables,授权表不被加载,而且不会验证用户权限(stage1 & stage2)。为了让实例验证用户权限,加载授权表即可。
1.5.FAQ
◎服务没有运行
报错信息
C:\Users\Administrator>mysql ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061) [view@file ~]$ mysql ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
◎没有监听网络协议
启动服务时,使用了--skip-networking、--bind-address=127.0.0.1。
◎选项错误
客户端程序使用了错误的配置文件(环境变量)作为命令选项。可以使用选项--no-defaults,跳过默认选项。
Default options are read from the following files in the given order: C:\Windows\my.ini C:\Windows\my.cnf C:\my.ini C:\my.cnf C:\Program Files\MySQL\MySQL Server 5.5\my.ini C:\Program Files\MySQL\MySQL Server 5.5\my.cnf The following groups are read: mysql client The following options may be given as the first argument: --print-defaults Print the program argument list and exit. --no-defaults Don't read default options from any option file. --defaults-file=# Only read default options from the given file #. --defaults-extra-file=# Read this file after the global files are read.
C:\Users\Administrator>mysql --print-defaults mysql would have been started with the following arguments: --port=3306 --default-character-set=utf8
2.用户账户管理
2.1.创建用户
用户信息保存在 mysql 库的 user 表(授权表)。创建用户的方法:①使用账户管理语句 CREATE USER 和 GRANT。②直接操作授权表,如、INSERT、UPDATE 和 DELETE。
增加用户,以 root 权限操作(用户不能建表、不能删除表)
# 创建用户 mysql> create user 'username'@'clienthost' identified by 'userpassword'; Query OK, 0 rows affected (0.00 sec) # 授权 mysql> grant all privileges on dbname.table to 'username'@'clienthost'; Query OK, 0 rows affected (0.00 sec) # 撤销权限 mysql> revoke create, drop on dbname.* from 'username'@'clienthost'; Query OK, 0 rows affected (0.00 sec)
查看用户授予了什么权限
mysql> show grants for 'username'@'clienthost'; +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Grants for username@clienthost | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'username'@'clienthost' IDENTIFIED BY PASSWORD '*36D54E64A3248C55234862F9C6E93BF10D9F09F0' | | GRANT SELECT, INSERT, UPDATE, DELETE, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, EVENT, TRIGGER ON `dbname`.* TO 'username'@'clienthost' | +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 2 rows in set (0.00 sec) mysql> select * from mysql.db where user='username' \G *************************** 1. row *************************** Host: clienthost Db: dbname User: username Select_priv: Y Insert_priv: Y Update_priv: Y Delete_priv: Y Create_priv: N Drop_priv: N Grant_priv: N References_priv: Y Index_priv: Y Alter_priv: Y Create_tmp_table_priv: Y Lock_tables_priv: Y Create_view_priv: Y Show_view_priv: Y Create_routine_priv: Y Alter_routine_priv: Y Execute_priv: Y Event_priv: Y Trigger_priv: Y 1 row in set (0.00 sec)
2.2.删除用户
以root登录,删除刚刚创建的用户
mysql> drop user 'username'@'clienthost';