The MySQL access control system enables you to create MySQL accounts and define what each account can do. In MySQL, the concept of "account" is tied to two things: a username and a hostname. That is, when you connect to the server, it checks not only the username that you specify, but also what host you're connecting from. One implication of this concept of an account is that it is possible to set up separate accounts for different users who have the same username but connect from different hosts. In SQL statements that require account names, the name is given in 'user_name'@'host_name' format. It is also possible to specify a pattern for the host part so that the account can be used for connecting to the MySQL server from several client hosts. For example, an account name given as 'maria'@'%.example.com' would apply to a user named maria who connects from any host in the example.com domain. Several types of privileges can be granted to an account. Privileges should be granted according to how the account is to be used. Some examples:
The MySQL server bases access control on the contents of the grant tables in the mysql database. These tables define MySQL accounts and the privileges they hold. To manage their contents, use statements such as CREATE USER, GRANT, and REVOKE. These statements provide an interface to the grant tables that enables you to specify account-management operations without having to determine how to modify the tables directly. The MySQL server determines what changes to the grant tables are needed and makes the modifications for you. The following discussion describes the structure and contents of the grant tables and the various SQL statements that help you manage user accounts. Section 34.2, "Client Access Control," describes how the server uses the grant tables to check access privileges when clients connect. Note: When you install MySQL, any initial accounts specified in the grant tables should be given passwords. The procedure for doing this is covered in Section 35.5.1, "Securing the Initial MySQL Accounts." 34.1.1. Types of Privileges That MySQL SupportsYou can grant several types of privileges to a MySQL account, and you can grant privileges at different levels (globally or just for particular databases, tables, or columns). For example, you can allow a user to select from any table in any database by granting the SELECT privilege at the global level. Or you might grant an account no global privileges, but give it complete control over a specific database. That allows the account to create the database and tables in it, select from the tables, and add new records, delete them, or update them. The privileges that MySQL supports are shown in the following tables. The first lists the administrative privileges and the second lists the privileges that control access to databases or objects stored in databases. Administrative Privileges:
Database-Access Privileges:
There is also a REFERENCES privilege, but it is unused currently. There are also some special privilege specifiers:
Privileges can exist at different levels:
34.1.2. The Grant TablesSeveral grant tables in the mysql database contain most of the access control information used by the server. They contain information to indicate what the legal accounts are and the privileges held at each access level by each account:
Every account must have a user table record because the server uses that table's contents when determining whether to accept or reject client connection attempts. An account also will have records in the other grant tables if it has privileges at other than the global level. Each grant table has columns that identify which accounts its records apply to:
Use of the grant tables for controlling what clients can do is discussed further in Section 34.2, "Client Access Control." There is also another grant table named host that exists for historical reasons. It is not affected by the GRANT and REVOKE statements, so it is discussed no further here. For more information about the host table, see the MySQL Reference Manual. If you look in the mysql database, you might also see a user_info table. This table is created by MySQL Administrator, but has nothing to do with access control, so it's not covered here. The grant tables are created during MySQL installation as MyISAM tables. The MyISAM storage engine is always guaranteed to be enabled, which is not true for optional storage engines such as InnoDB. (InnoDB is enabled by default, but it can be turned off.) As already mentioned, the server uses the information in the grant tables to determine whether to allow clients to connect, and to determine for every statement that a connected client issues whether it has sufficient privileges to execute it. However, the server does not actually access the on-disk grant tables each time it needs to verify client access because that would result in a great deal of overhead. Instead, the server reads the grant tables into memory during its startup sequence and uses the in-memory copies to check client access. The server refreshes its in-memory copies of the grant tables under the following conditions:
34.1.3. Approaches to Account ManagementIt's possible to manage MySQL accounts by modifying the grant tables directly with SQL statements such as INSERT, DELETE, and UPDATE. The procedure described in Section 35.5.1, "Securing the Initial MySQL Accounts," shows an example of how UPDATE and DELETE can be used in this way. In general, however, the recommended way to set up and modify MySQL accounts is to use statements such as CREATE USER, GRANT, and REVOKE that are intended specifically for account management. These statements offer the following advantages:
34.1.4. Creating and Dropping User AccountsThree statements create, remove, or rename user accounts:
For all three statements, accounts are named in 'user_name'@'host_name' format. More detail on account names is given in Section 34.1.5, "Specifying Account Names." 34.1.5. Specifying Account NamesAn account name consists of a username and the name of the client host from which the user must connect to the server. The account name is given in SQL statements using 'user_name'@'host_name' format. The user and host parts of account names should be quoted separately. Quotes actually are necessary only for values that contain special characters such as dashes. If a value is legal as an unquoted identifier, the quotes are optional. However, quotes are always acceptable and example SQL statements shown in this study guide use them. To specify an anonymous-user account (that is, an account that matches any username), specify an empty string for the user part of the account name: CREATE USER ''@'localhost'; In general, it is best to avoid creating anonymous accounts, especially ones that have no password. Letting anyone connect to your server opens up your MySQL installation to security risks. The host part of an account name may be given in any of the following formats:
It's allowable to omit the host part from an account name. A name specified as 'user_name' in an account-management statement is equivalent to 'user_name'@'%'. Keep the proper perspective in mind when specifying the host part of an account name. When you connect to the server using a client program, you specify the host to which you want to connect. On the other hand, when the server checks the client against Host column values in the grant tables, it uses the host from which the client connects. When setting up an account, you should specify the client host from the server's point of view. For example, if the server runs on server.example.com and you want to allow jim to connect from client.example.com, the CREATE USER statement should look like this: CREATE USER 'jim'@'client.example.com'; Be aware that it is possible to have multiple accounts that could apply to a given client. For example, if you set up accounts for jim@localhost and jim@%, the server could use either one when jim connects from the local host. The rules that the server employs to determine which account to use in such cases are covered in Section 34.2, "Client Access Control." 34.1.6. Granting PrivilegesThe syntax for the GRANT statement includes several sections. In simplest form, you specify:
As an example, the following statement grants the SELECT privilege for all tables in the world database to a user named jim, who must connect from the local host and use a password of Abc123: GRANT SELECT ON world.* TO 'jim'@'localhost' IDENTIFIED BY 'Abc123'; If the account does not already exist, GRANT creates it and assigns the designated privileges. If the account does exist, GRANT modifies it by adding the privileges. The parts of the statement have the following effects:
If you want to give an account the capability to grant its privileges to other accounts, add a WITH GRANT OPTION clause to the statement. For example, if you want jim to have read access to the world database and to be able to create other users that have read access to that database, use this statement: GRANT SELECT ON world.* TO 'jim'@'localhost' IDENTIFIED BY 'Abc123' WITH GRANT OPTION; To find out what privileges a particular account has, use the SHOW GRANTS statement. It displays the GRANT statements that would be required to set up the account. To see your own privileges, use SHOW GRANTS without an account name or with CURRENT_USER(): SHOW GRANTS; SHOW GRANTS FOR CURRENT_USER(); To see the privileges for a specific account, specify that account name in the statement. You cannot see the privileges for other accounts unless you have the SELECT privilege for the mysql database. Suppose that you've set up an account for a user jen who connects from the host myhost.example.com. To see this account's privileges, use the following statement: mysql> SHOW GRANTS FOR 'jen'@'myhost.example.com'; +----------------------------------------------------------------+ | Grants for jen@myhost.example.com | +----------------------------------------------------------------+ | GRANT FILE ON *.* TO 'jen'@'myhost.example.com' | | GRANT SELECT ON `mydb`.* TO 'jen'@'myhost.example.com' | | GRANT UPDATE ON `test`.`mytable` TO 'jen'@'myhost.example.com' | +----------------------------------------------------------------+ The output displayed here by SHOW GRANTS consists of three GRANT statements. Their ON clauses indicate that jen has privileges at the global, database, and table levels, respectively. If the account has a password, SHOW GRANTS displays an IDENTIFIED BY PASSWORD clause, at the end of the GRANT statement which lists the account's global privileges. (The word PASSWORD after IDENTIFIED BY indicates that the password value shown is the encrypted value stored in the user table, not the actual password.) If the account can grant some or all of its privileges to other accounts, SHOW GRANTS displays WITH GRANT OPTION at the end of each GRANT statement to which it applies. SHOW GRANTS displays privileges only for the exact account specified in the statement. For example, the preceding SHOW GRANTS statement shows privileges only for jen@myhost.example.com, not for jen@%.example.com, jen@%.com, or jen@%. 34.1.7. Revoking PrivilegesUse the REVOKE statement to revoke privileges from an account. Its syntax has the following sections:
Suppose that jim on the local host has SELECT, DELETE, INSERT, and UPDATE privileges on the world database, but you want to change the account so that he has SELECT access only. To do this, revoke those privileges that allow him to make changes: REVOKE DELETE, INSERT, UPDATE ON world.* FROM 'jim'@'localhost'; To revoke the GRANT OPTION privilege from an account that has it, you must revoke it in a separate statement. For example, if jill has the ability to grant her privileges for the world database to other users, you can revoke that ability as follows: REVOKE GRANT OPTION ON world.* FROM 'jill'@'localhost'; To revoke all privileges held by an account at any level, REVOKE supports a special syntax (note that this form of REVOKE has no ON clause): REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'james'@'localhost'; To determine what REVOKE statements are needed to revoke an account's privileges, SHOW GRANTS might be helpful. Consider again the output from SHOW GRANTS for the jen@localhost account: mysql> SHOW GRANTS FOR 'jen'@'myhost.example.com'; +----------------------------------------------------------------+ | Grants for jen@myhost.example.com | +----------------------------------------------------------------+ | GRANT FILE ON *.* TO 'jen'@'myhost.example.com' | | GRANT SELECT ON `mydb`.* TO 'jen'@'myhost.example.com' | | GRANT UPDATE ON `test`.`mytable` TO 'jen'@'myhost.example.com' | +----------------------------------------------------------------+ This output indicates that the account has global, database-level, and table-level privileges. To remove some or all of these privileges, convert the GRANT statements to the corresponding REVOKE statements. The privilege names, privilege levels, and account name must be the same as displayed by SHOW GRANTS. For example, to revoke the global FILE privilege and the table-level privilege for test.mytable, issue these statements: mysql> REVOKE FILE ON *.* FROM 'jen'@'myhost.example.com'; mysql> REVOKE UPDATE ON test.mytable FROM 'jen'@'myhost.example.com'; After issuing the REVOKE statements, SHOW GRANTS produces this result: mysql> SHOW GRANTS FOR 'jen'@'myhost.example.com'; +--------------------------------------------------------+ | Grants for jen@myhost.example.com | +--------------------------------------------------------+ | GRANT USAGE ON *.* TO 'jen'@'myhost.example.com' | | GRANT SELECT ON `mydb`.* TO 'jen'@'myhost.example.com' | +--------------------------------------------------------+ If you use REVOKE to remove all the privileges enabled by a record in the db, tables_priv, columns_priv, or procs_priv tables, REVOKE removes the record entirely. However, REVOKE does not remove an account's user table record, even if you revoke all privileges for the account. This means that although the account no longer has any privileges, it still exists and thus can be used to connect to the server. If you want to eliminate all traces of an account from the grant tables, you should use the DROP USER statement instead. After that, the account no longer exists and cannot be used to connect to the server. 34.1.8. Changing Account PasswordsAs discussed earlier, you can specify a password for an account by including an IDENTIFIED BY clause in a CREATE USER or GRANT statement. For CREATE USER, the clause assigns the initial account password. For GRANT, the clause assigns the initial password or changes the current password, depending on whether the account is new or already exists. To change an existing account's password without changing any of its privileges, you have two options:
Note that with SET PASSWORD, you use PASSWORD() to encrypt the password, whereas with CREATE USER and GRANT, you do not use it. To allow a user to connect without specifying a password, change the password to the empty string. However, you cannot "revoke" the password this way with REVOKE. Instead, use either of the following statements: SET PASSWORD FOR 'jim'@'localhost' = ''; GRANT USAGE ON *.* TO 'jim'@'localhost' IDENTIFIED BY ''; Be certain that you want to do this, however. Accounts that have no password are insecure. 34.1.9. When Privilege Changes Take EffectWhen you change the grant tables with an account-management statement, the effects of changes apply to existing client connections as follows:
34.1.10. Specifying Resource LimitsBy default, there is no limit on the number of times a client can connect to the server or the number of queries it can issue. If that is not suitable, GRANT can establish limits on an account's resource consumption for the following characteristics:
Each of these resource limits is specified using an option in a WITH clause. The following example creates an account that can use the test database, but can connect to the server a maximum of only 10 times per hour. The account can issue 50 queries per hour, and at most 20 of those queries can modify data: GRANT ALL ON test.* TO 'quinn'@'localhost' IDENTIFIED BY 'SomePass' WITH MAX_CONNECTIONS_PER_HOUR 10 MAX_QUERIES_PER_HOUR 50 MAX_UPDATES_PER_HOUR 20; The order in which you name the options in the WITH clause does not matter. To reset an existing limit for any of the per-hour resources to the default of "no limit," specify a value of zero. For example: GRANT USAGE ON *.* TO 'quinn'@'localhost' WITH MAX_CONNECTIONS_PER_HOUR 0; The MAX_USER_CONNECTIONS limit also can be set to zero to set it to the default. However, that does not mean "no limit." Instead, when this resource is set to zero, the value that applies to the account is the value of the max_user_connections system variable. 34.1.11. Privileges Needed for Account ManagementThe statements that are used for account management in MySQL require the following privileges:
|