6

スクリプトを使用して 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';

最初は 3 行目だけを使用していましたが、次の問題が発生しました。ユーザーから特権 Q を削除してそのスクリプトを再実行すると、ユーザーはデータベースでその特権をまだ持っていました。そのため、付与行の前に取り消し行を追加しました。

次に、次の問題に遭遇しました。「新しい」Mysql インストールでスクリプトを実行するたびに、ユーザーがまだ存在していないため、取り消しに失敗しました。そのため、取り消しの前に「ダミー」許可を追加しました。

質問: これを達成するためのより良い方法はありますか? 私の「実際の」スクリプトには多数のユーザーと多数のデータベースが含まれており、読みにくいです。割り当てたい権限のセットごとに 3 行が必要だからです。1行だけ使いたいです。

編集(回答とコメントからのフィードバックに基づく):

私は次のようなことを言う最短の方法を探しています

SET PRIVILEGES SELECT, UPDATE
ON my_database.*
TO my_user@"%"
IDENTIFIED BY 'my_password';

my_user の可能性がある場所

  • すでに存在します(ただし、新しい可能性があります)
  • 現在、私が彼に与えたい特権を拡張する特権を持っています
  • 影響を受けないようにする必要がある他のデータベースに対する特権を持っている
4

4 に答える 4

5

必要に応じて新しいユーザーを作成し、データベースに権限を付与する手順を使用できます。準備済みステートメントと GRANT ステートメントを使用しました。MySQL 5.5 のプリペアド ステートメントは GRANT をサポートしています。以前のバージョンを使用している場合は、GRANT コマンドを INSERT INTO に書き換えることができます。

使用テスト;

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');
于 2011-10-13T16:30:14.210 に答える
3

実際にはコメントである長い回答で申し訳ありませんが、わかりません。あなたの「3行目」の GRANT コマンドはうまく機能します。動作するはずの 2 つのケースを次に示します。バグを再現するテスト コマンドをいくつか投稿していただければ幸いです。少なくとも私はそれから学ぶことができました:)

ケース #1、ユーザーが存在しない:

mysql> SHOW GRANTS FOR my_user@"%";
ERROR 1141 (42000): There is no such grant defined for user 'my_user' on host '%'

OK、ユーザーは存在しません。

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)

OK、彼には SELECT 権限があります。

ケース #2、ユーザーは存在し、権限も持ってい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 '%'

OK、ユーザーは存在しません。

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_databaseSELECT


コメントに基づいて、それはUPDATEなしでなければなりませんSELECT

残念ながら、現在の MySQL バージョンでは、1 つのコマンドだけでそれを行うことはできません。節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つのコマンドでもあります。

回避策は、問題の 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。)

于 2011-10-13T22:05:48.247 に答える
3

権限を付与せずにユーザーが存在することを確認するには:

GRANT USAGE ON *.* TO my_user@"%" IDENTIFIED BY 'my_password';

本当に付与と取り消しを 1 つのステップで実行したい場合は、内部のアクセス許可ストレージ テーブルを直接いじる必要があるかもしれません。

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';

ただし、これは移植性が低く、より多くのアクセス許可が必要であり、必要なときにユーザー アカウントを作成しないため、おそらく 3 ステートメントの方法を使用した方がよいでしょう。

読みやすさの問題を解決するために、アカウントと権限を含む何らかの CSV を作成し、そこから SQL スクリプトを生成することができます。

于 2011-10-07T18:33:46.647 に答える
0

私はただ疑問に思っています、あなたは走りましたFLUSH PRIVILEGESか?

于 2011-10-07T13:33:52.177 に答える