When you attempt to connect to a MySQL server, the server accepts or rejects the connection based on your identity and whether you can verify your identity by supplying the correct password. If not, the server denies access to you completely. Otherwise, the server accepts the connection, and then enters Stage 2 and waits for requests.
Your identity is based on two pieces of information:
The client host from which you connect
Your MySQL user name
Identity checking is performed using the three
user
table scope columns
(Host
, User
, and
Password
). The server accepts the connection
only if the Host
and User
columns in some user
table row match the client
host name and user name and the client supplies the password
specified in that row. The rules for allowable
Host
and User
values are
given in Section 5.5.3, “Specifying Account Names”.
If the User
column value is nonblank, the user
name in an incoming connection must match exactly. If the
User
value is blank, it matches any user name.
If the user
table row that matches an incoming
connection has a blank user name, the user is considered to be an
anonymous user with no name, not a user with the name that the
client actually specified. This means that a blank user name is
used for all further access checking for the duration of the
connection (that is, during Stage 2).
The Password
column can be blank. This is not a
wildcard and does not mean that any password matches. It means
that the user must connect without specifying a password.
Nonblank Password
values in the
user
table represent encrypted passwords. MySQL
does not store passwords in plaintext form for anyone to see.
Rather, the password supplied by a user who is attempting to
connect is encrypted (using the
PASSWORD()
function). The encrypted
password then is used during the connection process when checking
whether the password is correct. (This is done without the
encrypted password ever traveling over the connection.) See
Section 5.6.1, “User Names and Passwords”.
From MySQL's point of view, the encrypted password is the
real password, so you should never give
anyone access to it. In particular, do not give
nonadministrative users read access to tables in the
mysql
database.
The following table shows how various combinations of
Host
and User
values in the
user
table apply to incoming connections.
Host Value
|
User Value
|
Allowable Connections |
'thomas.loc.gov' |
'fred' |
fred , connecting from
thomas.loc.gov
|
'thomas.loc.gov' |
'' |
Any user, connecting from thomas.loc.gov
|
'%' |
'fred' |
fred , connecting from any host |
'%' |
'' |
Any user, connecting from any host |
'%.loc.gov' |
'fred' |
fred , connecting from any host in the
loc.gov domain |
'x.y.%' |
'fred' |
fred , connecting from x.y.net ,
x.y.com , x.y.edu ,
and so on; this is probably not useful |
'144.155.166.177' |
'fred' |
fred , connecting from the host with IP address
144.155.166.177
|
'144.155.166.%' |
'fred' |
fred , connecting from any host in the
144.155.166 class C subnet |
'144.155.166.0/255.255.255.0' |
'fred' |
Same as previous example |
It is possible for the client host name and user name of an
incoming connection to match more than one row in the
user
table. The preceding set of examples
demonstrates this: Several of the entries shown match a connection
from thomas.loc.gov
by fred
.
When multiple matches are possible, the server must determine which of them to use. It resolves this issue as follows:
Whenever the server reads the user
table
into memory, it sorts the rows.
When a client attempts to connect, the server looks through the rows in sorted order.
The server uses the first row that matches the client host name and user name.
To see how this works, suppose that the user
table looks like this:
+-----------+----------+- | Host | User | ... +-----------+----------+- | % | root | ... | % | jeffrey | ... | localhost | root | ... | localhost | | ... +-----------+----------+-
When the server reads the table into memory, it orders the rows
with the most-specific Host
values first.
Literal host names and IP numbers are the most specific. The
pattern '%'
means “any host” and
is least specific. Rows with the same Host
value are ordered with the most-specific User
values first (a blank User
value means
“any user” and is least specific). For the
user
table just shown, the result after sorting
looks like this:
+-----------+----------+- | Host | User | ... +-----------+----------+- | localhost | root | ... | localhost | | ... | % | jeffrey | ... | % | root | ... +-----------+----------+-
When a client attempts to connect, the server looks through the
sorted rows and uses the first match found. For a connection from
localhost
by jeffrey
, two of
the rows from the table match: the one with
Host
and User
values of
'localhost'
and ''
, and the
one with values of '%'
and
'jeffrey'
. The 'localhost'
row appears first in sorted order, so that is the one the server
uses.
Here is another example. Suppose that the user
table looks like this:
+----------------+----------+- | Host | User | ... +----------------+----------+- | % | jeffrey | ... | thomas.loc.gov | | ... +----------------+----------+-
The sorted table looks like this:
+----------------+----------+- | Host | User | ... +----------------+----------+- | thomas.loc.gov | | ... | % | jeffrey | ... +----------------+----------+-
A connection by jeffrey
from
thomas.loc.gov
is matched by the first row,
whereas a connection by jeffrey
from any host
is matched by the second.
It is a common misconception to think that, for a given user
name, all rows that explicitly name that user are used first
when the server attempts to find a match for the connection.
This is not true. The preceding example illustrates this, where
a connection from thomas.loc.gov
by
jeffrey
is first matched not by the row
containing 'jeffrey'
as the
User
column value, but by the row with no
user name. As a result, jeffrey
is
authenticated as an anonymous user, even though he specified a
user name when connecting.
If you are able to connect to the server, but your privileges are
not what you expect, you probably are being authenticated as some
other account. To find out what account the server used to
authenticate you, use the
CURRENT_USER()
function. (See
Section 11.10.3, “Information Functions”.) It returns a value in
format that indicates the user_name
@host_name
User
and
Host
values from the matching
user
table row. Suppose that
jeffrey
connects and issues the following
query:
mysql> SELECT CURRENT_USER();
+----------------+
| CURRENT_USER() |
+----------------+
| @localhost |
+----------------+
The result shown here indicates that the matching
user
table row had a blank
User
column value. In other words, the server
is treating jeffrey
as an anonymous user.
The CURRENT_USER()
function is
available as of MySQL 4.0.6. See
Section 11.10.3, “Information Functions”. Another way to diagnose
authentication problems is to print out the
user
table and sort it by hand to see where the
first match is being made.
User Comments
If you do not trust the hostnames that may be seen by the MySQL server (after all, someone could be handing the server wrongly reverse-resolved hostnames), then do as described at http://dev.mysql.com/doc/refman/5.0/en/privileges-options.html : Start the server with "--skip-name-resolve": "Hostnames are not resolved. All Host column values in the grant tables must be IP numbers or localhost."
Add your own comment.