我正在使用脚本来创建Mysql数据库和表。这些脚本包含以下授权部分:
GRANT SELECT ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
REVOKE ALL PRIVILEGES ON my_database.* FROM my_user@"%";
GRANT SELECT, UPDATE ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
最初,我只使用了第三行,但遇到了以下问题:每当我从用户删除权限Q并重新运行该脚本时,用户仍然拥有数据库中的该权限。所以我在授权行之前添加了撤销行。
然后我遇到了以下问题:每当我在'新'Mysql安装上运行脚本时,撤销失败,因为用户尚未存在。所以我在撤销之前添加了一个“虚拟”补助金。
问题:有没有更好的方法来实现这一目标?我的“真实”脚本包含大量用户和大量数据库,并且难以阅读,因为我想要分配的每组权限需要三行。我只想用一行。
修改(根据答案和评论的反馈):
我正在寻找最简单的方式来说出类似
的内容SET PRIVILEGES SELECT, UPDATE
ON my_database.*
TO my_user@"%"
IDENTIFIED BY 'my_password';
my_user可能
答案 0 :(得分:5)
如有必要,您可以使用过程创建新用户,并为数据库授予权限。我使用了prepared statements和GRANT语句。 MySQL 5.5中的预处理语句支持GRANT,如果使用的是较低版本,则可以将GRANT命令重写为INSERT INTO。
USE测试;
DELIMITER $$
CREATE PROCEDURE procedure_user(
IN host_name VARCHAR(60), IN user_name VARCHAR(60),
IN db_name VARCHAR(255),
IN db_privs VARCHAR(255))
BEGIN
SELECT 1 INTO @exist FROM mysql.user WHERE user = user_name AND host = host_name;
-- Create new user, generate command like this: CREATE USER 'user1'@'%';;
IF @exist IS NULL THEN
SET @sql = CONCAT('CREATE USER ''', user_name, '''@''', host_name, '''');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
-- Generate command like this: GRANT INSERT, UPDATE ON database1.* TO 'user1'@'%';
SET @sql = CONCAT('GRANT ', db_privs, ' ON ', db_name, '.* TO ''', user_name, '''@''', host_name, '''');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;
使用示例:
-- First command will create new user user1@% and will grant SELECT, INSERT, UPDATE privileges to database1.
CALL procedure_user('%', 'user1', 'database1', 'SELECT, INSERT, UPDATE');
-- Second command just will grant SELECT, INSERT, UPDATE privileges to database2 to that user.
CALL procedure_user('%', 'user1', 'database2', 'SELECT, INSERT, UPDATE');
答案 1 :(得分:3)
确保用户在不授予任何权限的情况下存在:
GRANT USAGE ON *.* TO my_user@"%" IDENTIFIED BY 'my_password';
如果您真的想一步完成授权和撤销,您可能需要直接使用内部权限存储表进行清理:
INSERT INTO `mysql`.`db` (
`Host`, `Db`, `User`,
`Select_priv`, `Insert_priv`, `Update_priv`, `Delete_priv`,
`Create_priv`, `Drop_priv`, `Grant_priv`, `References_priv`, `Index_priv`, `Alter_priv`,
`Create_tmp_table_priv`, `Lock_tables_priv`, `Create_view_priv`, `Show_view_priv`,
`Create_routine_priv`, `Alter_routine_priv`, `Execute_priv`)
VALUES (
'my_user', '%', 'my_database',
'Y', 'N', 'Y', 'N',
'N', 'N', 'N', 'N', 'N', 'N',
'N', 'N', 'N', 'N',
'N', 'N', 'N')
ON DUPLICATE KEY UPDATE
`Select_priv` = 'Y', `Insert_priv` = 'N', `Update_priv` = 'Y', `Delete_priv` = 'N',
`Create_priv` = 'N', `Drop_priv` = 'N', `Grant_priv` = 'N', `References_priv` = 'N', `Index_priv` = 'N', `Alter_priv` = 'N',
`Create_tmp_table_priv` = 'N', `Lock_tables_priv` = 'N', `Create_view_priv` = 'N', `Show_view_priv` = 'N',
`Create_routine_priv` = 'N', `Alter_routine_priv` = 'N', `Execute_priv` = 'N';
但是,这样的可移植性较差,需要更多权限,并且在必要时不会创建用户帐户,因此您最好使用三语句方法。
为了帮助解决可读性问题,您可以使用帐户和权限创建某种CSV,从中生成SQL脚本。
答案 2 :(得分:3)
很抱歉,实际上是一个评论的长答案,但我没有得到它。你的“第三线”GRANT命令对我很有用。这是两个应该起作用的案例。如果你能发布一些重现bug的测试命令,那就太好了。至少我可以从中学到:)
mysql> SHOW GRANTS FOR my_user@"%";
ERROR 1141 (42000): There is no such grant defined for user 'my_user' on host '%'
好的,用户不存在。
mysql> create database my_database;
Query OK, 1 row affected (0.00 sec)
mysql> GRANT SELECT ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW GRANTS FOR my_user@"%";
+-----------------------------------------------------------------------+
| Grants for my_user@% |
+-----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' |
| GRANT SELECT ON `my_database`.* TO 'my_user'@'%' |
+-----------------------------------------------------------------------+
2 rows in set (0.00 sec)
好的,他有SELECT权限。
other_database
和my_database
上也是正确的:mysql> SHOW GRANTS FOR my_user@"%";
ERROR 1141 (42000): There is no such grant defined for user 'my_user' on host '%'
好的,用户不存在。
mysql> create database my_database;
Query OK, 1 row affected (0.00 sec)
mysql> create database other_database;
Query OK, 1 row affected (0.01 sec)
mysql> GRANT SELECT ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
Query OK, 0 rows affected (0.00 sec)
mysql> GRANT SELECT ON other_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW GRANTS FOR my_user@"%";
+-----------------------------------------------------------------------+
| Grants for my_user@% |
+-----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' |
| GRANT SELECT ON `other_database`.* TO 'my_user'@'%' |
| GRANT SELECT ON `my_database`.* TO 'my_user'@'%' |
+-----------------------------------------------------------------------+
3 rows in set (0.00 sec)
以上是测试夹具,现在我们向用户授予新的UPDATE
权限:
mysql> GRANT UPDATE ON my_database.* TO my_user@"%" IDENTIFIED BY 'my_password';
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW GRANTS FOR my_user@"%";
+-----------------------------------------------------------------------+
| Grants for my_user@% |
+-----------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'my_user'@'%' IDENTIFIED BY PASSWORD '*CC...18' |
| GRANT SELECT ON `other_database`.* TO 'my_user'@'%' |
| GRANT SELECT, UPDATE ON `my_database`.* TO 'my_user'@'%' |
+-----------------------------------------------------------------------+
3 rows in set (0.00 sec)
他的许可在other_database
上没有变更,他在UPDATE
和前my_database
获得了新的SELECT
权限。
根据评论,只有UPDATE
没有SELECT
。
不幸的是,对于当前的MySQL版本,只用一个命令就不可能做到这一点。 GRANT
没有REMOVE EXISTING
条款。
我认为最好的解决方案是@eswald的GRANT USAGE ON ...
,但它仍然是3个命令。
DELETE FROM mysql.db WHERE user = 'my_user' AND host ='%' AND db = 'my_database'
但它需要一个FLUSH PRIVILEGES
所以它也是3个命令。
解决方法可能是一个bash脚本,它会生成问题中的三个命令:
#!/bin/bash
function grant {
USER=$1
PASSWORD=$2
DB=$3
PERMISSIONS=$4
echo "GRANT USAGE ON $DB TO $USER IDENTIFIED BY '$PASSWORD';"
echo "REVOKE ALL PRIVILEGES ON $DB FROM $USER;"
echo "GRANT $PERMISSIONS ON $DB TO $USER IDENTIFIED BY '$PASSWORD';"
}
grant "my_user@'%'" "my_password" "my_database.*" "SELECT, UPDATE"
打印:
GRANT USAGE ON my_database.* TO my_user@'%' IDENTIFIED BY 'my_password';
REVOKE ALL PRIVILEGES ON my_database.* FROM my_user@'%';
GRANT SELECT, UPDATE ON my_database.* TO my_user@'%' IDENTIFIED BY 'my_password';
(我已将第一个GRANT SELECT
更改为USAGE
。)
答案 3 :(得分:0)
我只是想知道,你有没有运行FLUSH PRIVILEGES
?