下沙论坛

 找回密码
 注册论坛(EC通行证)

用新浪微博连接

一步搞定

QQ登录

QQ登录

下沙大学生网QQ群8(千人群)
群号:6490324 ,验证:下沙大学生网。
用手机发布本地信息严禁群发,各种宣传贴请发表在下沙信息版块有问必答,欢迎提问 提升会员等级,助你宣传
新会员必读 大学生的论坛下沙新生必读下沙币获得方法及使用
查看: 3232|回复: 3
打印 上一主题 下一主题

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。
$ @6 J4 L4 m/ O6 L0 T
( c) k5 p! o6 W# H# x) U$ ]权限系统做什么 0 Q3 p/ u2 g: }: q
MySQL权限系统的主要功能是证实连接到一台给定主机的一个用户, / n) w1 ~! a( H: a" w, I
并且赋予该用户在一个数据库上select、 insert、update和delete的
' V4 a. }% }. ^: v. E: L" V' T# F8 d' `权限。 ( l7 p3 e9 ]3 N, e  B& z: k4 ~
$ O7 T+ L, }" z
附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如
# s( c! D' c/ {9 [* y+ TLOAD DATA INFILE进行授权及管理操作的能力。
* q8 e. @: i9 w* S6 b' ^7 b+ z2 j
MySQL 用户名和口令
) G: s# X6 i' j由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很
" ~5 Q8 u# O9 g4 M- u多不同之处: 7 ]8 Q- T" |  p5 q0 w% |

  C4 K9 r9 |6 e0 B% k1 sMySQL使用于认证目的的用户名,与Unix用户名(登录名字)或 $ Z, c; y( L( F' \( s# r# H: L
Windows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户
' X3 u: Q* W  o名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或-
  p1 d* @1 p! K- v% u3 p-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据 9 }, t& K5 t+ |: w- J
库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名
6 Q' J  o; n" i字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。 ) P! x1 v0 q! J, U7 V
MySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。 & ~% M7 c3 x* a. D, f
MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使 % L( O3 ^0 v$ [7 p* o$ \2 q
用在那台机器上存取一个数据库的口令之间没有必要有关联。
$ U0 Z8 p; ~, [9 PMySQL加密口令使用了一个Unix登录期间所用的不同算法。 ' ~; u( z! F0 z1 z9 j
+ p, ~- V4 n1 Q& J! E6 f. _# A
与MySQL服务器连接
4 Z; U3 h7 n5 x4 t8 L, d当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定 . y3 h" J# M# t4 t
连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql : g7 J1 k  e2 m) p
客户可以象这样启动(可选的参数被包括在“[”和“]”之间): 2 [' V: G! D$ K' g! W  I1 ^
6 M" C8 ?* t$ K4 Y% e: T3 f
shell> mysql [-h host_name][-u user_name][-pyour_pass ] ' ^. I& ~! {0 N" B, m0 X/ A/ p
-h, -u和-p选项的另一种形式是--host=host_name、--user=
5 R# F8 i$ D) w$ a$ Quser_name和--password=your_pass。注意在-p或--password=与跟随它
. Z8 V+ V: O6 M- ~+ {后面的口令之间没有空格。
3 l5 Q1 j5 Z* V# K7 p2 @* i( i; i( n. e( T$ t3 L; V$ P- B* E
注意:在命令行上指定一个口令是不安全的!随后在你系统上的任
- u# R6 Q7 ~9 D7 d5 M4 ]' `( J% f何用户可以通过打类似这样的命令发现你的口令:ps auxww。
' [1 F, l1 T4 Z; I  V- t' _( {; U) p
& U. X0 n0 a  C( }3 q. D- V+ M对于命令行没有的联接参数,mysql使用缺省值: ! V! M1 z1 o, K2 q7 P% z5 \
8 Q) H+ z# o% R# I, D6 V
缺省主机名是localhost。
& L) V1 Q9 v7 T$ h; f1 T缺省用户名是你的Unix登录名。
, f2 Q0 O; G7 z1 g# l7 c5 e如果没有-p,则没有提供口令。 : H: m: {: f. ?% P9 `& ~0 p
这样, 对一个Unix用户joe,下列命令是等价的:
1 u5 W) D3 M, Q/ ^) L
0 |+ A/ ^1 J8 ^: sshell>mysql -h localhost -u joe
1 C4 _# F' g  t0 b* g& Pshell>mysql -h localhost
# p1 A+ l, [1 Lshell>mysql -u joe
7 p' n+ F4 W7 u8 R( J3 Sshell>mysql . {- b1 o5 N) N+ |$ t( |% ?

8 R& K! ?6 v% l7 {$ `$ @2 B其它MySQL客户程序有同样表现。 : }& S  }" m6 O) N$ I+ R2 u
+ P& g( W7 W. z
在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺 - Q( P! N; c, T
省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这
* P2 d4 x3 M4 L- o* M) ^可以有很多方法做到:
( n0 B( m! f) V8 D5 n0 U/ s
: T5 n6 {4 w& O. L/ c! E6 W你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定 ( O4 e. M* f! G( d
连接参数。文件的相关小节看上去可能像这样:
8 n; S/ `* `  ~$ e5 ?6 T( a- p[client]
2 \: e; j# H2 {2 l8 l" e* rhost=host_name ' h4 M& f# a9 z+ W
user=user_name ( A+ r4 h2 j; O2 r
password=your_pass $ ~3 l4 v4 H, l5 H+ |# t
; {. v; D' `$ ~9 _7 R
你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL
9 J% H5 L5 j) e5 ~用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是
3 M5 o: Z6 B% s; d  z' c/ V这不安全) 。 ( t% G8 B- S+ ^) A3 f6 A
如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配
' X  B2 |% I: ?  j& z$ C" f' j; @置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量 1 e2 t+ J  v, s8 Q2 o0 c# i
指定的值。
1 |. o+ L/ Y$ }& W, Y% a( ^
+ M8 L. t0 {; j8 ^; ?0 u$ P使你的口令安全
; H8 ?* Q7 I& j% L4 I3 s- e% J以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。 ' O" ]7 q& U8 j2 {3 D" H
当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法
$ M. j2 Q! q% Y的风险评估: # l& B* a9 Q7 q. g; a
! s9 ^1 B4 o! m3 E( p( {- q$ Y, {
使用一个在命令行上-pyour_pass或--password=your_pass的选项。
; f! e, U- C  R, ^  e. L这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见,
- k" X- C0 n7 E. f) ^它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化 6 W& O$ E- K. z0 `( I9 }9 A8 L  D$ g
顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可 # d/ T" w  Y5 N3 f9 R
见的。) 9 H! ~. c4 ~- F$ v" ~, U6 ^) V4 ]
使用一个-p或--password选项(没有指定your_pass值)。在这种情况
$ _; U# l) d! A+ D1 w& T下,客户程序请求来自终端的口令: , Y& o: M! y) P8 u* {

8 ^1 h+ M" a' }2 O% z9 `6 e9 ?2 rshell>mysql - u user_name - p 2 r7 [3 E/ r& A: B5 Y7 P
Enter password: ******** - W& b( g7 D: p$ N+ I: N- P% O
8 Y5 |# B$ r4 S9 [* j
客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见
! m% F6 ]0 ~0 e2 H它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你 9 U' H* d1 Q; _3 C- y
的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程   M4 U5 b7 l% R* Y
序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就
% O5 P) b; b: s没有从终端输入入口令的机会。
, w, m; v6 P0 h" v
3 j% w$ M5 c) a5 E4 u; ?, S在一个配置文件中存储你的口令。例如,你可你的主目录的 # U% k2 }8 h5 Q1 G6 R; e
“.my.cnf”文件中的[client]节列出你的口令: ( J3 ^6 {7 |( t
[client] ( K- |. ?9 w4 H9 t
password=your_pass / c  n( g( k( S2 t. {
2 }! ~; F* }" j9 f5 \- S
如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或
" Y5 y& a7 e$ S: I5 b可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。 1 W0 H! V- @9 A0 q% b7 R+ n, n

0 |3 R1 |7 w$ S- e3 s5 M你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极
: d3 H7 O& q$ x2 }: B% d/ e不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项; 6 ^' J" N+ n( k7 N, [, L/ y3 W
如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有
5 |% c; A) F5 A3 p/ \  g  L9 t这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智 7 ?5 E9 W5 E7 Z+ b& |$ C1 ]
的。
7 w  L+ n  W3 p7 `9 F总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
. E9 D, x( p1 h( J8 H.my.cnf”文件中指定口令。
& i! z& c1 Z% X- C/ N& V# x% D% a
MySQL提供的权限 7 e" L: h0 C+ G0 a
权限信息用user、db、host、tables_priv和columns_priv表被存储 . n6 M6 s% C$ F0 }( o
在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限 5 S% j% @. u9 [  V1 P6 P+ h9 a# m
修改何时生效所说的情况时,服务器读入这些数据库表内容。 - }" b- x: d  f% P( v
: Z4 J/ S+ L6 o' s: u+ ~/ J. g
由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表
, G0 h& P6 S- q! o, F列名称和每个权限有关的上下文:
) F7 c# H8 c: `3 _* H* F$ H4 e9 \权限 列 上下文 select Select_priv 表 insert Insert_priv 表 update Update_priv 表 delete Delete_priv 表 index Index_priv 表 alter Alter_priv 表 create Create_priv 数据库、表或索引 drop Drop_priv 数据库或表 grant Grant_priv 数据库或表 references References_priv 数据库或表 reload Reload_priv 服务器管理 shutdown Shutdown_priv 服务器管理 process Process_priv 服务器管理 file File_priv 在服务器上的文件存取 . x4 ?' l9 \2 G1 t& ~
select、insert、update和delete权限允许你在一个数据库现有的
% u7 N, W( _+ ~6 {) o& Q' g% R表上实施操作。
& c" u5 J. P# n1 ?7 y- u, |7 F
1 s( A8 H$ \8 t+ n* H* tSELECT语句只有在他们真正从一个表中检索行是才需要select权限,
! T  O8 H3 ]5 ~你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存 1 r; u/ ]) j" E% ~) D( Y: A( d. K
取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器:   _& r) Z9 j: [- Q# g
$ g5 B6 e" C" _% n1 G0 H
mysql> SELECT 1+1; ' P6 X/ x7 C) ?4 D
mysql> SELECT PI()*2; * R& Q6 O* {7 C( W" H! A4 t

% r5 @0 r0 ?9 A* ^4 l2 Gindex权限允许你创建或抛弃(删除)索引。
4 Q2 w; P* h" B9 R( Z" k3 R0 v1 P6 i5 K8 `! ~: J
alter权限允许你使用ALTER TABLE。
0 Y0 C5 v& ~6 N8 B% r9 w3 g8 l
7 H# O. j  R5 W# e1 E$ r# Ycreate和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的 9 H+ F5 J$ e3 H- [6 S6 O
数据库和表。 % V" C6 M' X& ?; a) A0 d
0 T) d- Q) F$ E5 H2 I* D5 l
注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃 2 {  q- \, Q% W, ~+ w% h
存储了MySQL存取权限的数据库!
+ e  M% @/ `5 k; ^
6 I7 V9 p' D  B5 Cgrant权限允许你把你自己拥有的那些权限授给其他的用户。
' y: T! [! S" v! F% X8 k  t$ `
9 m8 [8 K- L3 x; T2 j6 Efile权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句 ; E) E) V7 ?  D, t5 {
读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务
3 J3 |' C8 L) r5 p7 Y器能读或写的任何文件。
# z/ r& C$ \/ B: c. P% \# c% Q4 J6 C% d" L
其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示
$ q' z% g, f3 u2 tmysqladmin支配每个管理性权限允许你执行的命令:
; D* M( L' @" I; O优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill 8 [! I2 k7 r% u
reload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开
# [3 v0 x9 L" w  i0 u6 r: F和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-* 1 j9 `# f( M( c$ ~, F. E- |2 G
命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 9 i4 J: X2 D. \1 ^; E3 o
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的 + m* d* X0 P8 ~: k. h8 E
选择。
9 k! w+ }' a# S" k1 N9 }4 h2 B( G  U1 Y) D: z: m4 L
shutdown命令关掉服务器。 " q: @- x9 k! T7 L; t+ Y& L

- d& f& z# `% U! Lprocesslist命令显示在服务器内执行的线程的信息。kill命令杀死服 7 D4 T3 I6 ]% A) ?0 O5 V& R
务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来 / |! H  q' \7 [% n7 g9 p0 `
显示或杀死其他用户启动的线程。 : g4 ~# g6 s$ g' |  ^

5 C* l9 D4 v; d( u, T总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你
8 K9 w) W" M1 Y  {. y' O应该在授予某个权限时试验特定的警告: 1 ^! Z' F8 `) f" h8 @* [( m& f8 y
, a; K/ i1 M2 l5 Y* v/ r4 M
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并 2 e, Z5 }: j7 M. B, O
有grant权限的用户可以合并权限。
  M" d3 P" I9 y. Yalter权限可以用于通过重新命名表来推翻权限系统。
/ Z3 M7 q$ t, G% R+ f0 w9 ?file权限可以被滥用在服务器上读取任何世界可读(world-readable, 5 s) y4 _0 X1 P( a4 T8 f# {% H
即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。
! J. M; Y2 Z$ C. ^0 s2 Zshutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。 - q6 }! f4 m) T' ~) e5 z8 R
precess权限能被用来察看当前执行的查询的普通文本,包括设定或改
7 x! K" P1 l: K$ O变口令查询。
) w9 G' Q5 y! {) K3 ]" x4 X$ L在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口
  U+ \2 U; ^3 I/ z. P- Y! d! m$ a令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够
" v1 t) O# _1 Q" n* _/ ]$ y4 ]的权限,同一个用户能用不同的一个代替一个口令。)
- i3 R& t0 d. Q& c有一些事情你不能用MySQL权限系统做到: 3 R1 k4 b! u' S# T5 D, d
# N( l! j+ d# L/ t
你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹
+ g+ `& E7 j. Y( j$ F配一个用户并且然后拒绝连接。
& h7 d7 |& {5 ?% K9 u' r你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建
9 K; c1 q! m1 \- K; z- E3 i( J或抛弃数据库本身。
; w6 E0 [( ^3 S2 |" N. B8 A权限系统工作原理
. p" i. P/ n2 E1 D% z; _1 ^* h  nMySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。
( e/ n6 i3 o$ W  a* d9 k当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用 6 g& O# `& S+ l. Y
户名来决定,系统根据你的身份和你想做什么来授予权限。 & Z+ a; x$ H, R5 F; Q( V

4 ~4 J: N( z4 d* DMySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假 2 k5 S9 k# z% b8 O6 Y- A$ J" ~
定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov 6 D7 D4 g% p& @/ Q5 X* k: I4 w/ f8 J
连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区 ; d" ^, L, r+ O5 ^* t- C4 y
分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov 1 X- D5 g- E2 G
连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限 9 M+ O0 m8 B9 Z. N
集。 ( A4 D, a% c8 M4 h. j

' v; K: p' y% V8 sMySQL存取控制包含2个阶段: % x8 |8 u3 d) r0 m* e

$ J! M0 o! G  h/ T; i阶段1:服务器检查你是否允许连接。
. K- o( c- @2 N  C1 b; z" i阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够 3 J( G3 @8 Z1 F8 l! U6 ^; k8 M
的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛
, A9 b3 m+ [& R4 h+ e  H. N弃一个表,服务器确定你对表有select权限或对数据库有drop权限。
; m; p- h7 F# J8 K3 o/ i服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host
3 _, k; e3 m, h8 _2 N8 X表,在这些授权表中字段如下:
5 u" X9 ], C& f& f; ]表名称 user db host 范围字段 Host Host Host User Db Db Password User 权限字段 Select_priv Select_priv Select_priv Insert_priv Insert_priv Insert_priv Update_priv Update_priv Update_priv Delete_priv Delete_priv Delete_priv Index_priv Index_priv Index_priv Alter_priv Alter_priv Alter_priv Create_priv Create_priv Create_priv Drop_priv Drop_priv Drop_priv Grant_priv Grant_priv Grant_priv Reload_priv Shutdown_priv Process_priv File_priv . G. s" l7 j+ t
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外 1 O. o- M8 z3 E- N& k8 G6 b
参考tables_priv和columns_priv表。这些表的
8 G- |! _  b4 p+ f! Z4 e字段如下:
6 ~( i7 D) i( ~表名称 tables_priv columns_priv 范围字段 Host Host Db Db User User Table_name Table_name Column_name 权限字段 Table_priv Column_priv Column_priv 其他字段 Timestamp Timestamp Grantor . D6 X2 ?* z7 e
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
5 ^( C# t* b* a# P+ p8 u$ _* _参考tables_priv和columns_priv表。这些表的字段如下: * H% {( W' ?+ I9 |5 ?& J7 R
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
$ j% R9 s+ f8 ?6 Q1 d7 t9 T在user、db和host表中, & L& \  E2 x; X- c
所有权限字段被声明为ENUM('N','Y')--每一个都可有值
; D4 E0 E/ M" S" @; L  D6 Y0 U'N'或'Y',并且缺省值是'N'.
% M: S/ q$ S% g3 L  s2 [0 A' J在tables_priv和columns_priv表中,权
: Q! p$ d/ M' H1 J; u限字段被声明为SET字段:
* u; y- }7 k2 c' P4 l8 l( i表名 字段名 可能的集合成员 tables_priv Table_priv 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter' tables_priv Column_priv 'Select', 'Insert', 'Update', 'References' columns_priv Column_priv 'Select', 'Insert', 'Update', 'References' * {0 k* q$ @, r. ~; o1 {  ~1 o. ~% M
每个授权表包含范围字段和权限字段。
! G# Z1 t# A5 t3 i4 f& R$ T5 n9 D8 b; |
范围字段决定表中每个条目的范围,即,条目适用的上下文。例如, ( t5 j( o$ y1 l, q! @, n
一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于 % {+ J8 N; J" z9 `3 |* z3 `) n
证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条 + m2 X) R/ {! n
目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'
* \, F+ W  e" F将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。 4 e7 S' Q: N1 I1 ~: P. B
tables_priv和columns_priv表包含范围字段,指出每个条目适用的表或 7 m6 p6 J2 J$ {
表/列的组合。
' i3 y, }3 D% i0 Z) J, }; j* o' w4 v& }" K2 n
对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
6 B9 _- V5 `4 cDb和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以 / `- b4 K6 O2 `; C: j. o
后版本是忽略大小写的。
3 V: W8 g5 @; {5 m5 ?
* s2 I& m$ m5 u4 D权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务 0 e' A9 k' T6 Q1 P9 _  w7 @; E
器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规
9 g) G) R* \( v则在6.8 存取控制, 阶段2:请求证实描述。
8 ~4 d; I# ^& v0 S8 U5 q
5 r: o! ^( T4 A) S范围字段是字符串,如下所述;每个字段的缺省值是空字符串: 6 Q5 s: C2 @0 C' j
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))   _8 I+ w0 @$ j* ~; `  e! a( g
在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一
- j# d. L7 W4 F个都可有值'N'或'Y',并且缺省值是'N'.
. M3 ~! O* O& ^4 C9 r" l: B
% v4 Z! p2 S" F2 s. u在tables_priv和columns_priv表中,权限字段被声明为SET字段:
; e; @  _- P9 x& j$ Z' K) Z3 }表名 字段名 可能的集合成员 tables_priv Table_priv 'Select', 'Insert', 'Update', 'Delete', 'Create', 'Drop', 'Grant', 'References', 'Index', 'Alter' tables_priv Column_priv 'Select', 'Insert', 'Update', 'References' columns_priv Column_priv 'Select', 'Insert', 'Update', 'References'
* y% g( g3 @( z& _) j0 ~, ?简单地说,服务器使用这样的授权表: * I$ g1 |* Z0 ^& f& U/ W/ c+ s; C
$ Z/ f6 }0 J9 i, v7 c
user表范围字段决定是否允许或拒绝到来的连接。对于允许的连接, ( a; q4 B# q2 h
权限字段指出用户的全局(超级用户)权限。
# U- x7 F; T5 l) j) sdb和host表一起使用: . u5 D9 f4 l( M& \" h* D# [
db表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定 0 b0 B- y$ z, T3 b! \9 k
允许哪个操作。
. p( [& P) ~3 X9 P3 s) A当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩
  a! W" j$ V: w/ T' e$ M% U4 [展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个
2 J/ w+ l0 b! \( u: n3 O! |数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移 0 k3 C$ k) j6 S, n# K; k3 u
入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。
; `: I3 U. H2 n8 B2 e% f( {! Ytables_priv和columns_priv表类似于db表,但是更精致:他们在表 6 N2 l! w- I" R4 F, M& G- W
和列级应用而非在数据库级。
! W  `' _+ c! @1 o- b( K注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是
! r4 E$ {$ @& ^因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由 2 V; R( p4 L" b4 I) [; E+ z) o
在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是 + k$ C( l0 ]$ m) T: _9 ]2 y
否执行一个管理操作。
; M4 M4 g+ D5 D  J1 T* t
2 Y* ^' D; Z/ |file权限也仅在user表中指定。它不是管理性权限,但你读或谢在服
" \3 [# A# A6 b; L" [务器主机上的文件的的能力独立于你正在存取的数据库。
# `) A/ s* t7 Q2 H2 e" j4 S2 |6 ]6 b
2 _" k  g' Q2 P" Q+ T, u/ A+ Q当mysqld服务器启动时,读取一次授权表内容。
4 z% {. k  s0 R1 x& N7 |  n5 p
当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一 7 [" t1 Y8 y+ H6 J" b, }8 R9 t( z
个好主意。
1 U% t, C" P( o
/ P3 {# d/ ^* u! b一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给
. m  V6 y! g' J. C% XMySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意: , ^. ?! r7 }' K* [& M- g1 |; `9 `
mysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。
& `5 {' @) ]2 z- M& {& M* F9 m! p' k
存取控制, 阶段1:连接证实 + T* q- K0 r% q: O* w, P
当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能
$ G- i2 [$ Q7 O通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全 # i3 g* U! ^# h+ I! n2 n
具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。
! c$ U+ y( f4 I2 H0 c. Z& \4 ]6 O3 K! k; y- |4 _3 }1 U
你的身份基于2个信息: , ]) d0 j- b  @

$ D% q* P8 l  e0 B4 v你从那个主机连接 # N% m, J0 [7 R  v4 c2 @
你的MySQL用户名
8 v% q+ u$ X2 W" h, V" t身份检查使用3个user表(Host, User和Password)范围字段执行。服 7 c$ }& g5 E+ Z; e: \
务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的
+ d$ S& ^4 s2 j) F. z" Y& O1 w9 [口令时才接受连接。
+ ?/ L6 i4 H& g2 x! @2 \- p; S2 ~, D" r- c# ?% P6 w1 d
在user表范围字段可以如下被指定:
/ e& F1 a1 Y& |0 z% ~& X6 b% d9 V) A" u9 L2 c' l5 a  ~' g
一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。 . ]9 s8 ^) i: ^1 u4 T
你可以在Host字段里使用通配符字符“%”和“_”。
6 z( r  w1 s% S, F/ c1 u% `一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些 . G  o$ T% S6 i- l, h% B; g
值匹配能创建一个连接到你的服务器的任何主机!   j) c5 e0 W' ?
通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何 $ F* x7 X/ _6 U; }3 ?3 D  B
名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为
( ]* x' E# ~0 h, {9 S是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空
7 F5 _" D% r4 C/ O( @白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。 * ]4 c" x* d4 l/ }3 X4 m
Password字段可以是空白的。这不意味着匹配任何口令,它意味着用户
: _5 ^+ k4 m& i3 A必须不指定一个口令进行连接。 ; ^( x& y9 Q+ _( C' A2 R
非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本 4 P0 x( T. `0 |2 g5 C. r% X
格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用   s0 G0 h  g4 T2 `' r
PASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他 % K/ A7 L" P8 p' n$ j2 n# g( c
们匹配,口令是正确的。
/ E2 `8 W$ H' X/ {' h; S4 B
3 W# j! F: d- }& E下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来 2 D9 T- @( s8 o6 Q7 F0 m
的连接:
2 \8 x9 j# L  m% M  H
: d: i7 o4 V4 eHost 值 User 值 被条目匹配的连接   w3 {9 v# p, `/ a' \5 ], \
'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接
+ a* _  V; h% d'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接 $ f# L7 f! S5 j4 _# ?
'%' 'fred' fred, 从任何主机连接
( g" p  M6 D; i. B/ b- t, R'%' '' 任何用户, 从任何主机连接
$ p; _5 z3 h, l$ K& J; N4 u- e'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接 8 x9 V, n: W0 Q8 h0 x
'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许
& l* p; R1 }4 x% ]7 S! c无用) , |( X) g2 |/ j: |
'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主
% [% ~' \9 _8 x& [# Y机连接
5 o" x4 T! k" V'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连
0 D( \# V# d8 I/ X% N- Q: Y; m  w. {' i
: I) H5 J" E/ R/ m9 f$ F: A  w+ y
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子 8 Z/ c. M5 R9 j6 N4 t) ~( D
网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机 7 U5 A( ?7 Y& g! B% r. b
为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以
8 u0 Y# j; _5 H1 B; n数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的 5 Q5 W- ]9 Q0 g, h. ^
主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配 + q5 @0 {) Q$ D
符值。
. D. K* }) I& r1 {# H, x/ h  [8 E- K4 S. g1 V
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由
8 G/ b! O$ M8 c  Vfred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配,
# o) i+ m2 G# [  s服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来
6 j+ H6 H: ~# k: a3 _  Q解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一 & [5 K; ]: K1 O6 y6 ?9 y7 K
个匹配的条目被使用。
& `& z; M. d) f5 u: X# C" v* R$ B+ p" a& ^8 y. c8 S2 v
user表排序工作如下,假定user表看起来像这样: 4 k4 u  y; P. s# ?5 n

% e" T% G1 T( ~4 p4 _) ^; e' I1 j; d# d# O. T6 W
+-----------+----------+- 2 u0 a4 V3 e$ F1 c- l
│ Host │ User │ ...
' G# G' h6 S6 X+ x: F" ~+-----------+----------+-
6 ~- i# t, `2 c2 n. n9 z' v) C│ % │ root │ ...   p1 J  r+ P( o9 j4 u. |* V8 `
│ % │ jeffrey │ ...
  G2 o9 V9 n! g  c+ ^# ~  t( J) |% s│ localhost │ root │ ...
% W4 V+ M& S; E0 j) P5 k│ localhost │ │ ... 1 }/ ^. [' {1 z3 ?9 `/ i' |
+-----------+----------+- " j& o$ D- }+ d( O9 p: f$ q
) E" ?: j; t% {" ]
当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在 & E1 h5 o3 R5 q5 W  l+ B
Host列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以 3 ]3 d" V$ [) k+ U/ X* \9 b  k: ~
最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且 7 Y% v9 [/ C% z
是最不特定的)。最终排序的user表看起来像这样:
7 C) |8 b' Z1 [/ \  z: K( v/ a2 K8 y$ ]& u) _

5 v( t; W: ~3 N2 `+-----------+----------+- ' d4 |6 N  b6 Z% f3 q  Y
│ Host │ User │ ... % @$ I2 }9 E; u0 S( k- _1 L
+-----------+----------+-
8 K0 J+ U+ e- U* q6 k│ localhost │ root │ ... ! A' X- P& s3 E8 p+ v
│ localhost │ │ ... , z. w9 p3 [# `  e4 a6 _
│ % │ jeffrey │ ...
6 `% y6 l' \% n! G, ?│ % │ root │ ...
$ y! F: ^6 ]6 @; u2 l2 C+-----------+----------+- 2 `* k/ G' Z( O8 H, \1 a

5 A. g1 Y+ h5 X. S- v当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹
# O( o; K. x1 P) v# q配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目 ; ]- w4 a4 u, C, z9 n. W
首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/
; E! q) t5 H& V& A) ['jeffrey'条目也将匹配,但是它不是在表中的第一匹配。) + H# h; p2 a* m! }* f2 L# ]

( ]; D! H( j+ l" Q这是另外一个例子。假定user桌子看起来像这样:
6 @3 ~2 A2 l! t5 V( f, R
! h( R& ^+ D! [+ U8 R" l4 s# c( r3 w+ T! @
+----------------+----------+-
0 _  m5 `. R) y2 B8 }& @│ Host │ User │ ...
7 P* ~2 C" ~* p+ ~" c* O: a( n: s& n1 k5 A+----------------+----------+- & `" e& i8 C( u( f  a' f  [. \
│ % │ jeffrey │ ...
  c; h1 {2 M7 R% F, ?- [1 a! O│ thomas.loc.gov │ │ ...
3 N8 |2 O0 n- U& R% k+----------------+----------+-
( e* M/ o2 {; F$ T. Q3 u- W0 k) x
排序后的表看起来像这样:
1 N$ O9 T( O5 J: Q
% x  L( v# j3 }% o2 P, ~; K" Z6 V+ v0 c) b. K! `9 ^* j) W6 k
+----------------+----------+- # P6 I, A4 x) A# Z9 i& z
│ Host │ User │ ...
/ X( G+ L) p2 g; P+----------------+----------+- 7 r( S8 V/ D4 e7 @4 C( J" [! A% r& G$ o
│ thomas.loc.gov │ │ ...
; |2 i2 {) K* q5 p* ^│ % │ jeffrey │ ... 8 Q# z* B5 ^8 u2 t
+----------------+----------+- 4 s$ [  v& {5 i+ m8 j: d2 l; u

+ X% |; r! ]  t5 r7 l一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由
3 J% h# f2 W; `: Q8 vjeffrey从whitehouse.gov的连接被第二个匹配。 0 K+ z2 i3 C! c; S2 ~* m9 J

* f: V9 |0 t/ P+ w: p6 A) o普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找
) ?9 K9 Q. Q, E6 D% u匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。 $ J! L* Y9 ?% c% G# _9 g- l' a2 D. q
先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没
3 p; I7 ^% S. H3 f5 e; _被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹
, h; |9 G# I* ~7 Z4 d2 Y配! & L# Z! _: G/ @* h9 c# ^5 @

; Z2 a! m* X( W) S$ R1 \3 j4 X+ `如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个
: F5 A: l' t$ _, V匹配在哪儿进行。
* t3 T/ m& y$ `5 K9 ~
  k0 b% w+ w, _, o) {& _; J存取控制,阶段2:请求证实 * B" Z* i2 h0 |8 R7 l. [* H
一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个
; f0 x  }, z  A请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作 7 _( y& ]+ \/ k& d
类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子
0 _0 R- r4 Z' k* zuser、db、host、tables_priv或columns_priv表的任何一个。授权表用 7 D. O  Z; r* X2 J# E
GRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参
0 A/ n# n7 j) T) J" J# I考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。) ( W/ @8 X- I- ^

. p, H0 m4 y- E7 Zuser表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库
; ?; F1 ^# x4 I  ^是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器
, F: ~: R5 p# l  c主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
/ Q  N5 n6 Q0 t# O) P3 B& ouser表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户,
$ y8 O* p) `* C  q  ?你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权,
5 g5 F4 q" V+ ~$ e使用db和host表。
/ c6 e# w, R, h" I. ~, Y- {( C0 n: B6 s3 [6 B4 l
db和host表授予数据库特定的权限。在范围字段的值可以如下被指定:
4 }2 d6 q- v' C) S9 |' K
6 F3 Q% k" M6 o8 e3 W通配符字符“%”和“_”可被用于两个表的Host和Db字段。
5 E  @) {# ^! f7 i" H2 B) H; b在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 " v+ T& ?& B2 K% P% A
着“对进一步的信息咨询host表”。
' J5 X% B/ u1 z  k/ ~在host表的一个'%'或空白Host值意味着“任何主机”。
9 u/ ^4 o4 g/ }/ ]7 W4 h在两个表中的一个'%'或空白Db值意味着“任何数据库”。
* ?6 t- Y( p4 X( E, ?' W6 [/ @' d在两个表中的一个空白User值匹配匿名用户。
! v7 ?# t, s6 L+ h$ \( Jdb和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host
/ n. Y+ d! Y$ U- [: d; T6 f、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于
' n- s8 I/ J1 q9 E5 s" Suser表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 1 D: B2 O/ {( E$ ^& X/ A
匹配入条目时,它使用它找到的第一个匹配。
/ Z, ~" a2 l* h% d. D( ~  s% s. j, g5 i7 d3 s
tables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可
8 P* P6 M2 W9 f$ k2 R# g& Q( O以如下被指定: # I! O9 u2 w: x; s

$ ]  \" N) T9 E+ Z" n通配符“%”和“_”可用在使用在两个表的Host字段。 7 `5 A- b3 z! @& w
在两个表中的一个'%'或空白Host意味着“任何主机”。 , ?0 _, R- s$ c& E3 }/ r
在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。
: g% D% ]+ ?1 e- etables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于
6 q% u$ A+ X* g: H; sdb表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。
" k6 L2 S& l3 |# B% W
. [0 S$ k% z/ Y* l; v请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这
+ B6 F# T( }0 z( D& s! h里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是 9 k$ P% d& p# O3 e2 i: z" S
不同于使解释更简单。) , D, ^2 Y: m5 r, s. T5 t0 ~2 I
( v6 T9 f) n% W. }0 o
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是 ) F7 `' h. M+ ?; g9 j  B7 x
唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。
% c! U1 V8 d3 c, ]9 T例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授
* K, E5 W8 h- [( f; s0 |$ c予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含 7 @1 O* i( V1 m7 {: e1 l
Shutdown_priv行列,没有这样做的必要。)
. \+ D/ r! K2 S2 S7 s2 [/ x$ H% U" t0 ?2 q7 O* \: Z
对数据库有关的请求(insert、update等等),服务器首先通过查找user表 4 m' p% k7 O7 _9 w; z$ k5 e
条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授 2 R2 ~: S  H' {: G- {
权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用
4 e/ M1 _4 G, k7 u2 c2 }5 t户数据库权限:
) u% l, P( w& t0 u( Z% v  p" i: F
' ?" @$ n" l: O. H5 ~6 c服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连 , C% T, L8 F7 H4 {
接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有 ( J7 t+ H# X3 z( r# N. z) @
Host和User的条目,存取被拒绝。
' \# ?5 L5 W; Y  {$ G+ w. {/ [如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用
' H+ I. ?* w7 T  a户的数据库特定的权限。 ( J5 {0 ?7 i0 S5 `3 q5 d6 n
如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被 8 N  t0 ^2 \1 _1 a8 T  f4 _! _
允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和
3 p3 x2 J3 S7 k. |+ PDb字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数 ) l- @& y- v- K2 S$ q! u
据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交 5 _3 c' D4 r( C9 V+ y
集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host 7 p" M5 }+ Z1 n2 \) t) {, I) |  N
表条目按一个主机一个主机为基础地有选择地限制它们。)
: s% q5 p2 j0 i9 G, e在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
/ X; O" {& F! W" H; e由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 1 W* e6 @+ v! {, W& Q
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到
8 v5 \! }, [2 f7 n/ g; \用户权限中。基于此结果允许或拒绝存取。 $ P0 [: I* V1 w  [0 {1 |7 K! {
+ k5 s. E$ @* k8 b
用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结: 6 j7 n+ ?8 V% d7 R/ u

& u" I# m7 h: H  O1 Yglobal privileges ; n: }* M: J( W0 B2 H
OR (database privileges AND host privileges) - B: T5 j( Y8 n$ N
OR table privileges
' B0 L, B* U( F: f6 ]$ t, Y. LOR column privileges
) h$ d' g- _+ I( @
  ~& {. U- C' j- y! w* z: Y它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不
+ D9 V9 @( ]3 l够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能 ) E. R: Z8 r  U4 z( ^. H) ]
要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都 2 q3 I) y' l: i7 _
要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 $ `: t5 ^1 q! `5 w2 p% m* q
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把 " a% u/ K" n6 S4 U1 G7 K" |7 b
两个表区别开来;两个条目授予的权限必须组合起来。
3 n6 ?6 _( J8 J; ^
* g1 }1 }% N! O" qhost表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本 8 \0 q+ F5 B+ G8 B3 C# v% N8 x
地的网络上所有的机器的表,这些被授予所有的权限。
; U# |8 T$ g% ]
: u! a1 C3 A" d1 P你也可以使用host表指定不安全的主机。假定你有一台机器public.your. 3 x/ q& D, n. M; F4 R8 V: P# P
domain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允
8 t% s' t- x' k) Z: P- l4 h" ~许除了那台机器外的网络上所有主机的存取:
$ T* G5 K% a% q" ]$ ~
" v8 \9 q3 `- _  \0 @7 ^2 r
5 A) C$ r( Z. @6 q8 I+--------------------+----+- $ J, [6 R+ y$ P: ]0 y) Y
│ Host │ Db │ ... 1 W& ^" P9 ]9 R# h/ v" b) z
+--------------------+----+-
2 z" f& S5 o5 m4 w: x/ }1 M1 r4 S4 ]│ public.your.domain │ % │ ... (所有权限设为 'N') & O/ t. N( D5 g8 d
│ %.your.domain │ % │ ... (所有权限设为 'Y') 5 w$ m& R: Z+ `- j# x. w
+--------------------+----+- ) {8 `$ J" s5 E2 M2 o0 q# h9 r7 d2 ~

1 ~$ c1 C) S1 y1 p6 q7 v当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保
0 j% _6 ]) J8 |( M4 ^1 f6 s你的存取权限实际上以你认为的方式被设置。 ) I2 s. k- ~5 s: f9 {0 s
+ h: K  U: _2 ^' x& S3 C5 g
权限更改何时生效
+ T3 A5 \  i* T  p当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。 . k: I& L* x% M- V; T! I5 s0 s0 u! A

8 I; K1 y7 l* h用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。 ( v: |. s1 z% L
/ l2 [! K' W1 A$ f: I8 m5 ?* |. A! T
如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH - p+ S- `- @& _" x* L2 j
PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否
1 v( ?6 ^; _1 H" f' y则你的改变将不生效,除非你重启服务器。 , Q+ [2 B7 a! t2 `0 d. X

# T2 Y7 D, q' |当服务器注意到授权表被改变了时,现存的客户连接有如下影响: 2 K& ]6 i7 u- a# B5 b) n
3 Y2 `: Y: a3 A/ p  ?. Z
表和列权限在客户的下一次请求时生效。 , [* u3 H/ O* C3 z
数据库权限改变在下一个USE db_name命令生效。
. h' G. r3 |1 Q4 `/ e) L+ X全局权限的改变和口令改变在下一次客户连接时生效。 ( g% x$ `+ L' q/ k) L
) f+ O( w% L; n
建立初始的MySQL权限
5 ?: T% T, D3 R* {在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。 1 z! c6 H! o% t* `1 U4 J7 N2 a; y
scripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列 . x/ }  p6 X" f2 l2 U' x" g8 A: {
权限集合:
3 {/ @3 c- P6 z+ Y) m1 A
) X9 {- w' R/ y5 m" a' z* d5 jMySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主   Y" j: h  ]/ M, K) m: }- j1 y5 N0 y
机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行
: Y) U! J" ?; p8 c0 I; |9 W- O: i连接并且被授予所有权限。
: f0 F( X4 {. N( _+ a1 J$ T; `一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库
% u. m: j, Q9 Q0 S做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视 - V6 S) [- M% l0 D( K
为匿名用户。 3 ^) ?" e0 A$ ~; i
其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或 5 u/ n# N  S/ D6 ]& h6 i& @
mysqladmin processlist。
; w7 v6 t+ x' E2 A6 ^2 \- z+ d注意:对Win32的初始权限是不同的。 , U4 x- ?) v9 s& Z/ p+ w

7 j: p$ q5 I: u' g. ]7 o3 `* ?% [既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户 * W8 j' C3 U0 M, C: P
指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令):
' n2 e2 C+ J2 [$ w
$ G; \; i$ u6 f* K! E, }shell> mysql -u root mysql " a8 d& o1 Q, e% z" \
mysql> UPDATE user SET Password=PASSWORD('new_password')
, ]: F" [0 x& g" w( sWHERE user='root';
. Z: E. N! f1 \* B, |( J5 Z3 Xmysql> FLUSH PRIVILEGES;
8 e5 H' l& o' i7 A5 P2 Q; Q( W
) Q3 M  E/ a2 V* t* i在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句:
/ y7 p4 X7 D2 k1 H1 d) ?  T3 B0 u( x9 A5 I! W
shell> mysql -u root mysql
$ Q" s* q- l3 emysql> SET PASSWORD FOR root=PASSWORD('new_password'); * @' f' x0 C& x+ Z9 |. R2 j
6 V8 m( ]  M4 d6 L
设置口令的另一种方法是使用mysqladmin命令: ' a& q) u& d2 V5 T3 W: t$ _) |1 H

8 i; r- x( z2 Y  _. ?* _$ z' x6 ashell> mysqladmin -u root password new_password 0 b( ?: H3 L7 R& q
1 ]; R. ?: B4 C8 h0 l; C  e0 ]6 a
注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器
4 F$ P* J0 z3 h" z' Q3 w再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。
' X6 q  k( `5 }! \9 S7 `! |3 v4 W0 I3 h% w" ?3 N8 b( F( ~* t
一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个
- `' o1 K6 d* J$ Q. f: i# z口令。 $ d  _4 i, r) [8 |7 W2 r8 y
4 |& W' U7 ~! y, x, A7 r7 Y
你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它
6 h" R: }& k6 u; C或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。 4 ~2 q8 j' e: X0 C9 V; i

) x  V0 {7 X) n  W* |$ u看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它 3 p3 Q5 f0 M2 }+ s$ S  H9 Q
作为一个研究如何增加其他用户的基础。
7 Y! {* J7 f5 q: I* T% P' Q
( _/ v0 H2 c) \; ^; U如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db . |5 X) Z5 j7 u2 t/ O! ^* ^
之前,你可以修改它。
# x5 J& f; o6 t  \( s8 [1 D9 U$ a1 {8 r" G9 m& X0 D7 {9 a
为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”,
4 _' l; ~' @' B) a4 m& R“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,
* V- J: K# e) P6 C* F4 C) F7 R当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能
' t, [# w. [  `4 M; O- K在首先编辑它拥有你想要的权限之后。
/ A1 K& A3 A0 M5 p8 S0 u; f: B+ h1 b, ?* G1 W/ Q/ B' @# P( U
注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果 $ U* k; {1 s' n/ E2 U
你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。 " i7 A, m; D/ v" o: D
8 l. @5 v; F3 B0 B! ?0 l& w$ D
向MySQL增加新用户权限 " w! Y9 ~; |3 ^+ S% M
你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授 * [9 h$ F; |" x' K6 V) W2 Y
权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。 ) q) y, o) h3 U
1 r2 \* k2 [5 `# P: g9 o
下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前
  Q1 r! a& E' |0 j9 K2 O的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台
* c+ j. Q7 _8 B- x, G3 M机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有 1 @: y# c4 F, K
insert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下
& M) G/ i  X6 m7 Y7 t的mysql命令指定它。   q- F1 M/ w9 ~  I- U$ c
, \, R8 I$ L6 T
你可以通过发出GRANT语句增加新用户:
" a  G0 a5 D$ G4 d/ J  H. o: C* p" J  L6 u' ~& ?" A
shell> mysql --user=root mysql
, ?) I; g/ u( k* jmysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost
  F3 x/ J! `6 V5 L. eIDENTIFIED BY 'something' WITH GRANT OPTION; % T3 @, p$ T; x! Y
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%" " P( w4 u! w, H" x
IDENTIFIED BY 'something' WITH GRANT OPTION; # q6 C' y, @! m& V% [, y% b
mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost;
* [! x+ C8 Y7 Zmysql> GRANT USAGE ON *.* TO dummy@localhost;
. c4 J' n+ P6 \4 P9 Z5 w
2 f1 N! U8 L0 O. ?( n$ D这些GRANT语句安装3个新用户:
6 l9 j" N: i4 }/ V
- z9 q) Y# V  F# I/ xmonty
& F7 C9 i" s$ O% ]; h- B可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个 # l# x' J5 {( X0 ^5 Y- P( t9 s6 r
口令('something'做这个。注意,我们必须对monty@localhost和monty@"%" " S0 A9 O" D4 f6 Q
发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
. h; Z/ S! M6 Y$ L在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为
+ p9 @( Y6 t8 r它有更特定的Host字段值,所以以user表排列顺序看更早到来。 * n3 d( J# u! ~/ J" v  g
admin + k: u1 V, f7 m0 c! `5 s, s" L
可以从localhost没有一个口令进行连接并且被授予reload和process管理
4 P4 K! g( ], f$ I2 n权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和
6 a# d1 j: F( ]0 Kmysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有
% k! |  J( U+ r3 u3 m关的权限。他们能在以后通过发出另一个GRANT语句授权。
: `* O1 Q. r/ ?. L( t1 t: t" Hdummy
1 ~' ~: j( k7 x0 H6 f& q% W" b# {  L可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设
: M* X# Z: u3 f9 e置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以
- v- F2 x, I2 r' @后授予数据库相关的权限。 + K5 |2 W/ e' m( _  R2 }
你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服
3 f' z0 [; h* G& r1 F# `务器再次装入授权表: 8 f' l4 w; \* R: H
' A4 L3 h3 J6 J/ P2 A" k! a
shell> mysql --user=root mysql 2 L) N: u* K  Q; v
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD " W4 V# }% ?/ G; v
('something'),
/ g# G: k$ ]: n' V- Y& q'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', ; P+ [8 ]- y' j3 J+ V
'Y','Y') 6 ^! R* s# Y2 }; D. D8 ~
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'), 6 I( S/ c8 I; q8 y# N3 Q
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
( i4 L2 e0 `1 E, w" w7 c+ q'Y')
2 c- Y) y2 z0 ^. ]2 V8 [8 T! ~mysql> INSERT INTO user SET Host='localhost',User='admin', , k( @) {0 Q# x
Reload_priv='Y', Process_priv='Y'; , L2 [2 t2 m* v1 N1 G
mysql> INSERT INTO user (Host,User,Password) ! n. v9 {+ E5 G$ c; |! w
VALUES('localhost','dummy','');
. a; v$ s+ T7 c! p4 ^  ]. o8 x4 gmysql> FLUSH PRIVILEGES;
* g+ X1 W6 Z0 K) s1 J( f0 i
3 h" X8 y8 O* y4 e/ C* U5 p  Q" I: w取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
/ w9 ?, I& e1 K" K# t9 l& F) G3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版 0 {- c: X0 @* Q7 B
本具有的更加可读的INSERT扩充的语法。 , Q3 D4 x& {. a0 D4 \

3 Y( o$ g) ?$ a6 ~" t注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为
: [% X: O. ?, K3 ^+ g$ q1 d  q'Y'。不需要db或host表的条目。
) [$ s' h- A- ~( L8 A1 v$ `9 A* j* d# S, a
在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户), 1 ^% J9 ]0 ~) d7 b5 o; S
因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
3 }; T/ Y4 k' _; d
4 ~; v$ M. M7 {8 }+ i! y下列例子增加一个用户custom,他能从主机localhost、server.domain和 6 U8 i8 J* y6 ?4 k4 m
whitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从
5 k; @& S. g& W6 S, k' a  n% kwhitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他 ( ?8 P! t) \% [6 s9 o9 f
想要从所有3台主机上使用口令stupid。 ! U; g! U* {# o/ q; c
# M; U. [8 N9 {5 R
为了使用GRANT语句设置个用户的权限,运行这些命令: ; @( a8 f) ^9 r9 d* b

. y% P+ s7 A! [6 [9 z9 ?6 Kshell> mysql --user=root mysql
/ w- S& C8 T; h% Pmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
* Q# L2 Y" ~! f0 [ON bankaccount.*
$ |7 @: `8 K0 ^5 aTO custom@localhost
4 A9 S$ f& Y, X2 ?IDENTIFIED BY 'stupid'; 3 G5 x$ r, l  R
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP 3 w: A9 ?& z4 H6 c6 h9 K( ]
ON expenses.* + D! x+ m0 r% J$ M- Q3 H* A
TO custom@whitehouse.gov + w4 N# _$ B5 x# m3 e4 O
IDENTIFIED BY 'stupid'; , X' c2 G1 T: h$ {# |/ g" Z
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ' T. ]6 n1 l5 h1 T* {- n$ n
ON customer.* . `3 b$ w4 L+ y$ ]+ N' ?  `
TO custom@'%'
, Z# H6 o: P6 U* [" Z2 k( q( KIDENTIFIED BY 'stupid';
! n% |1 M8 K) ^
4 p: X0 V5 V/ r% Z通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时
) P: Y( m' ]4 I' vFLUSH PRIVILEGES):
+ j" U, m5 ~8 B) S3 D! b9 x/ j7 X  e
shell> mysql --user=root mysql
9 [0 j4 D$ u/ `1 d9 ~mysql> INSERT INTO user (Host,User,Password) / `& Q! Y  W6 t% J( i3 V- u
VALUES('localhost','custom',PASSWORD('stupid'));
# b- r) L! H. Cmysql> INSERT INTO user (Host,User,Password)
1 x2 e- t$ |6 S/ s# j! `VALUES('server.domain','custom',PASSWORD('stupid')); & b9 V0 C# ^' @1 E" M
mysql> INSERT INTO user (Host,User,Password)
7 Q+ W0 e$ l8 h' d1 HVALUES('whitehouse.gov','custom',PASSWORD('stupid')); 5 ~: N: F# ]8 _" G* A
mysql> INSERT INTO db
$ x, s0 O5 b; L(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, + a/ J9 E" U8 V+ N
Create_priv,Drop_priv)
. i9 d  }* r0 ~0 G" q8 YVALUES 1 v2 e: k5 F! M6 g% j
('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y'); 9 E% |5 F! Y# o% i" V+ i
mysql> INSERT INTO db
: F/ _( E8 E# s1 F: h6 ]5 U' {(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, ) V" q7 }) O. x/ L* k+ Y4 W
Create_priv,Drop_priv) + n& E: H7 }* M( Q. ^4 |& N
VALUES
4 W# p4 S3 G; P$ c- N('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y'); / J+ ?' S( a! D" {+ K
mysql> INSERT INTO db . X. y. ?+ \, |7 d0 ^! f
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
8 r. m8 [; J* l, ~Create_priv,Drop_priv)
) e& c, O. `  u) S+ b2 K9 QVALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
7 }0 _6 @/ r8 `( T0 Y! B: {" u# qmysql> FLUSH PRIVILEGES;
4 R' _3 g: t( J2 y" b) e! t1 }6 G
头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机
; Q/ y% h1 J5 P! i进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT
9 v( C3 i: M) \/ i( {语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限,
! y1 F) O; t! K% M. @但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告 : m  s& ^- L7 i) w+ b* D
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。 + c1 f) t3 B2 M3 S% v
; l6 w/ ^' X9 O. E! P: y
如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发
! l: ^& N, X) L; o! p; Y$ G, d出一个如下的GRANT语句:   X& m' w; |4 e% U6 u& z6 @0 B

2 y1 l2 M# y* x' S# A) Emysql> GRANT ...
  e& l% @0 {, s9 ~ON *.* 5 Y+ p3 R/ ]* @' X! j0 c7 n5 T
TO myusername@"%.mydomainname.com"
' U2 w  O2 E+ U3 t+ iIDENTIFIED BY 'mypassword'; , K& s0 I- h& b( K0 d% C; n4 v

$ T% y5 N6 x3 X2 x2 `2 |为了通过直接修改授权表做同样的事情,这样做:
; w0 t- e- |% j* {- q. a9 p) R  A
, C, U- O; B4 P6 e! h$ Hmysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', ) j5 |. O& i' H- L% T8 t
PASSWORD('mypassword'),...); # t9 Y8 J5 z7 d
mysql> FLUSH PRIVILEGES; 3 i9 n6 K) ~9 @" Y  G, _
: [1 u5 Y9 y& {6 A) c
你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变
2 M# b! h- H  v7 ]和更新值。你可以在MySQL的Contrib目录找到这些实用程序。
9 F1 |& x: e, B  c5 D7 q' i3 v% h9 J' W7 R' A
怎样设置口令
& l# j& b% \. p6 z在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存 ; N3 ~6 }0 @% b$ W9 b: G$ _
储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以 3 q9 X+ [* g$ J" P
加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图 7 l& C# E  L% j  Y" ?) M& k
设置口令:
) m) T" |$ N# Y% o7 i) l3 o
, o$ q  o9 e0 J" V7 `3 @' eshell> mysql -u root mysql 8 \+ l9 p5 s: [" W- v4 ~
mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey',
6 i& e. T. w7 D' h3 O, v'biscuit'); - r; u: y  |! s& C( U2 `; H6 x% b
mysql> FLUSH PRIVILEGES * L/ |( ^# w( R: |2 X3 j% m

3 M7 s. Y- B& w( z结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用
& \1 p6 }5 O! u6 z+ I6 d这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服
9 j: y5 A" g' v9 }5 W2 V9 W务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是
# D0 Q% h/ T! s, v# i! h3 P'biscuit'),比较失败并且服务器拒绝连接:
; p6 n' @5 C1 ]' V3 x' ~$ r" H1 f
shell> mysql -u jeffrey -pbiscuit test ; O( t1 d  G$ w. @( }& q
Access denied ! H6 Q1 S& |, d$ s3 p

: l- G' s+ W9 u  S. N2 P% A因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样
( h7 A! N$ \  x* z0 J( [被指定: ( O% A6 K- S+ t  w; I

1 R# O/ E1 B4 \4 [0 ^mysql> INSERT INTO user (Host,User,Password) 7 i/ S4 W* R: y/ K4 D' g5 ~
VALUES('%','jeffrey',PASSWORD('biscuit'));
+ t/ d( J' f" M8 s
  W4 k7 V; j; ^当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数:
; v) e- H* M- |2 c
; H( o2 [5 u3 f$ Y% Y) t3 dmysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit'); 9 o2 c8 D4 M0 I1 T! q- l" H6 q
( Z6 ^5 I# z3 \- ^# v
如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口
% o( X- X7 v0 u! b# n令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指
6 E1 a/ j, [, f# s) p7 N5 y- i定一个口令'biscuit':
( O  X2 ~* {7 m% V8 A% J' S6 A' e% W# M: w/ g
mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
+ n! E# `$ W0 U7 q( \
9 j- }+ `& \/ J3 ^# X; X! F
; U5 @# ~5 d( y- |9 b* ^- D$ b8 b9 E6 c+ \6 ]9 G
shell> mysqladmin -u jeffrey password biscuit
9 M! q% }- o% j! x! M# }+ s- [注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应 2 G( t4 p! `, s
该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix
& u* c3 a% f1 _7 O+ W& I5 c口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。 4 z9 C$ |( N, o& a/ u' L

& T( j9 P6 ~9 hAccess denied错误的原因
: W/ A" \- i- P/ _& F$ ~, F0 |  e当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 ) @, {; N, v7 a: R$ k. x0 B
的表指出一些你能用来更正这个问题的动作: ) ]* h- \+ ~9 E0 i' R
* j3 A1 w2 B  S1 d
你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容 0 z! X& D; g6 W0 w
吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初
7 @" `3 }/ a; U2 X始权限:
! z; t4 |: I1 Y+ d- O7 Y( Ashell> mysql -u root test
1 U- T5 U, o5 c* v- q" A; u
2 O! V- ~& V; F1 `服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件 . Q6 L) K% ^- {
“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安 ! l! ^, [/ K+ \) }# T! `; D
装根目录的路径。
, W2 Q" [5 g' D& h2 ^0 ~+ K8 m& K: q" E7 p2 {: [. v% [7 r
在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可: & q7 R0 P, @' a
shell> mysql -u root mysql
/ s* o1 c$ g: u. l0 o
6 y' D3 ?  ^! ]" `$ g服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个   T* |/ @9 F% Y7 [. H# \$ j9 G- ~7 j5 _
安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如
) g5 [/ _9 B" J9 {果你作为root尝试连接并且得到这个错误:
, z+ y0 R; h8 y/ Z, P7 z) f5 ?6 f/ D. }3 g5 W1 W, S
Access denied for user: '@unknown' to database mysql
% B. r4 X0 I* Z' [
- w- X" u, |  m* Z* M0 A- ]这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld . ~1 }6 k" f$ P6 l4 f, U$ }6 ~) k
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项 0 [6 s! U! H) n' t, z5 J
重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机
- t% T! Z# m  }& |" i9 O3 J2 y增加一个条目。
" z( ~: Q6 b0 t( b! Q: @" ~2 ?
2 l: m. f4 v, \, s$ d如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以
2 J* ^( M5 _) n后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在
# t3 ^) ?- |+ y0 ?( T# cGRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。 ' c( I9 g# U6 b: e0 N2 U+ I
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被 # O$ \+ ?4 H+ C
忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin
0 a3 n$ z% }6 g' u5 {( hflush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被 + Q: v7 S# }, @0 s# p$ r- E
重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗
; I$ h8 H- A1 {* ~4 H, s8 A5 t(flush)权限以后,因为服务器仍然不会知道你改变了口令!
, X  l! c% n- M& o; }如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变
; K6 R9 p8 z8 t3 O  T了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权 2 K2 U, x( T( I/ Z6 Q( `7 z; x2 x: f. ]- @
限改变何时生效小节所述。
3 B2 w  n4 u) u1 ~+ c0 w) r为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变
8 ?* @' N1 q3 p3 v3 D" i4 nMySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的
+ P, T' y+ _) B+ ]9 R+ c' J- S改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权 # V6 T1 G; V6 O/ W0 ]/ w  ]
限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务
, {+ d7 c* ~: h8 l6 W  u: R! d' N- M器开始使用授权表,而不用停掉并重启它。
" E1 H' h7 r; e9 r5 t4 h如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name . x# l% G& F+ e4 w# N! T
db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用
' w8 b* M. o1 r' r' C9 ^mysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令
6 s  S: H# s* {0 H8 C之间没有空格;你也能使用--password=your_pass句法指定口令。) % S: }  }8 c/ G) e* O- q, y8 I
如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句 , R' L9 x+ c/ E
设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语
: M9 {8 ~7 C+ [' `, u, x句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。 - T# s! P4 p, R- N
localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 1 W3 i( _$ M3 `% y
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系 0 m* P' f" v  A; x2 @0 r( Z. G1 S5 Q
统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT ) q* J" W# V5 a6 c" j1 G% w# C1 D
-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确 0 m, |& k. B" c" c) |. W
地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你 0 u; P* |* o8 m! Q
必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一
, r  V' J- S# A台的主机上运行一个客户程序,这也是真的。) $ O2 c$ ~1 z4 q* _
当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个
' S, G8 H0 X) P% Q/ K6 P* _Access denied错误,你可能有与user桌有关的问题,通过执行mysql -u root 7 W* |; A6 q4 L
mysql并且发出下面的SQL语句检查: $ D2 I1 N  R: A( D% s" R. Q5 }
mysql> SELECT * FROM user;
+ @! v7 B$ R7 F! N9 Q; G. x, M' E7 N8 D$ c+ F' z
结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户
7 }: D1 k5 T1 l& a7 G名。 0 k: c: Q! a' ~# Z  b/ s* G+ I
3 r" L7 k) s7 Q' H( B) t% _
Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图
% n, J2 d( c* ]8 z: c用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一
7 D6 P& \2 O% |; K8 ]. i* R5 X个条目,正确地匹配在错误消息给出的主机名和用户名。
0 p+ k7 V6 V7 ~- q7 y如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列
3 j0 \8 z3 S$ _8 C/ ?* S1 h, S错误,那么在user表中没有匹配那台主机行:
( [' u/ C7 ?$ M8 k3 K5 uHost ... is not allowed to connect to this MySQL server # I" ^, R+ Z4 J) g3 y) Q2 Q5 m
5 H" Q$ X/ U# G: |; R
你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试 7 t  f0 m' m9 o  V( i$ ?5 ^
图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且 9 D7 |7 B6 D& X! F4 J
你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为
+ ?! G& m7 {# u7 sHost列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从 + h4 I1 B5 r; g! C' m
客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。(
0 y# C- i5 K' [6 M3 [- N; G: Z然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则,
7 N' |! z& j" t- w, @你将有一个不安全的系统。) ! r7 @: ~$ X) r
+ s  H* f. L, n5 L; w
如果mysql -u root test工作但是mysql -h your_hostname -u root test $ B7 V! J. f& N$ b& K
导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的 ) N  E- u/ v7 f# |, v
一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统 4 `) p  {) k5 L& U5 G' D' Y
的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有
. K) T% K$ H; {* \5 M$ I一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet. ( ^$ c: ]" |7 p9 D6 Y, L$ i
se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作
4 P" }7 `& K* w为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符
3 @( g+ ^, D0 W: [, ~如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)
0 p$ e3 b# `: G# d/ L如果mysql -u user_name test工作但是mysql -u user_name other_db_name
* j; @: Z) g& X. s. N1 f4 _$ r不工作,对other_db_name,你在db表中没有没有一个条目列出。 3 g0 p+ B. j0 q
当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其 8 e9 d! J, J+ f/ _6 h: T% Q7 ^6 I
它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
+ Y  ?& R, u( d你没有把客户机器列在user表或db表中。
' y- p5 A& T8 g1 x# S# e! i如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host 2 [9 p; G3 ]" i$ H7 D9 i  Y
包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用
0 D. n9 ]4 E4 _2 D5 n) h7 iHost='%'和User='some user'插入一个新条目,认为这将允许你指定localhost : s9 n* T2 ^* p7 m: O
从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost' 1 |( U# C* e, m0 x1 A) n9 u8 I' p
和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从
$ Z5 Y8 Z5 ~, L2 |. a- t# I3 D- nlocalhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和 8 c, f* x( q+ E
User='some_user'的第2个条目,或删除Host='localhost'和User=''条目。 9 ]* x) j: Q" ^# |- ]9 y' l$ `  J
如果你得到下列错误,你可以有一个与db或host表有关的问题:
8 o6 M9 C. ~; c8 e7 V( x6 HAccess to database denied
) O: _4 a/ V3 T9 P- _+ x4 k3 {5 P
如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多 + t9 {/ y% O7 e# B  j* v, J
个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ... 3 o1 s) A! A- M: B4 ~. |5 X
INTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可 ! c" Q, X: E* M5 Y
能启用file权限。 - p' C7 R# Y2 @

5 Y  r. K/ P, W) x. \: _: x2 e2 d记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果 * V4 A7 h  w4 V4 Z6 P
当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,
) k# M* u( n( b: c检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围 & C5 e7 q4 Q* E% C8 d
的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当 5 c& f+ ?; z4 `2 u
你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选 & B! P: u( P! _- p# O) m9 Z+ n$ o+ h
项文件里指定一个旧的口令!见4.15.4 选项文件。
: Z0 k1 R$ G" s, _如果任何其它事情失败,用调试选项(例如,--debug=d,general,query)
9 u$ t4 W; ?' p* s; E4 B启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每
( S3 @& ~! n! [6 Z/ I$ `个命令的信息。见G.1 调试一个MySQL服务器。
# U3 Y$ [! x8 X如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 ; S9 @9 b/ \( [1 p4 V' c
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump ' e7 L; y# ~5 J5 U7 |! ]" X
mysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一
  N4 _9 @9 N$ R5 N( B* V* [8 I4 T0 P8 R些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。 2 U+ {' z1 D2 }, @* y
怎样使MySQL安全以对抗解密高手
9 M2 ^5 E' c: \( W当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文
, p/ J4 {* s, B, h. `* V在连接上传输。
. _* \5 l( `& V  }, I# O
/ L6 c: X2 c" p  p+ }2 k7 R8 |所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可 9 ~4 J/ o: ^# _9 v. y8 }
使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全 7 W9 h9 b2 g: g7 |9 w9 A% z
,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服
4 Z: K" {7 ^& q/ r3 I  d务器与一个MySQL客户之间得到一个加密的TCP/IP连接。
1 C/ u/ s0 s* J) r& _$ j, Y& G- u( d$ e5 `
为了使一个MySQL系统安全,强烈要求你考虑下列建议: * [5 ^. J$ r/ r* H7 M# o( t  d) C' X

! ]( \2 ?' G4 _; c5 o. P对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简
! E& ~( s' R+ }5 Q单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器 & H  C+ N7 r3 R; E
应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通 9 U' x7 {: v9 S0 Q4 @
过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令, ) r# m1 M! ~7 W# M
象这样: 0 y) e9 L" ?4 f3 a
shell> mysql -u root mysql 9 P! S' ?5 y8 ^5 O! B2 W5 D
mysql> UPDATE user SET Password=PASSWORD('new_password') : r% ?4 z) C2 Y6 k
WHERE user='root'; * l* q7 F; I+ U/ z: D# e$ C9 Y
mysql> FLUSH PRIVILEGES; . R8 J, T6 V+ S! j/ W

7 ~$ `" K  U8 M7 @" S# r不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行,
- _! v9 G  c) x3 A你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户 2 \) P# Y* b" c, M2 d2 D
运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix 7 s) J* g/ I# x! E* j% _/ h
用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。
0 T* L: q* [. l$ C, t! i通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行 + I9 ~3 d/ e8 b& U. u7 G
MySQL。   K! e: x8 X2 ?+ H7 _# y- a( I
如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本 8 i# M6 R7 Q/ x
只能对root是可读的。
2 E; D8 }- i$ i4 u检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用 8 V3 B# f3 Y0 Z, V8 Y: W
户。 % R7 D1 V9 |# J/ f" C9 H7 M
不要把process权限给所有用户。mysqladmin processlist的输出显示出当
7 f$ @5 H# \* R% O# I8 j3 F前执行的查询正文,如果另外的用户发出一个UPDATE user SET password=
+ V4 h1 s( d" t  v& hPASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。 + e- w7 y7 }6 l6 t4 l: J0 |+ _; o
mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用
4 G$ J) [1 A7 C7 I$ L户能登录并检查,即使所有的正常连接在使用。 " W7 S. |: l2 E3 x
不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
+ s- y3 B+ M  P* i+ w进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ... 1 T! U8 g8 P) M, Z& [+ A: Z6 G: v
INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 * @, Y8 i1 d5 t$ q
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文
9 B; P/ ?7 d8 o; L件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数
* V% P/ a; ?/ L  A# J4 O据库表,然后它能用SELECT被读入。
5 K6 e* v) U) W) R3 L$ n如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则 ! d; P  K& e+ T$ H
上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常
5 M, T, i: h8 g; _& `小心地使用包含通配符的主机名! 0 A! H3 E# O' C: M8 I! a% A
下列mysqld选项影响安全: ; I8 t, M$ P1 j8 a

& O3 r. V" ~3 E7 T" q9 |5 v* K--secure 1 m7 F. m6 U# g+ I1 C( \
由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来
3 _# x9 }$ e$ `+ k的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也
' v: F4 ~9 D2 D7 V  y% S5 f增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
3 Y0 m$ y8 m. V它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。
8 e- y; P  f# L( u--skip-grant-tables
" K) b: G: ^) j  t+ H2 O这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数
+ u# H3 h0 `7 u7 R: }据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器
& g( J8 r' j  G5 j, W再次开始使用授权表。)
8 T( J8 f( _/ j) P8 G" A, A--skip-name-resolve
/ i, k  I# r0 a主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。 ; b) ]- B& f$ D, j( u3 [
--skip-networking 5 H; p+ P, t6 k/ l2 S8 b4 B6 k
在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
* ]# F1 b$ o, m& @行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不
5 K/ h/ b& @! T1 x6 g$ ?. n- G支持Unix套接字。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博
丧心病狂 该用户已被删除
2
发表于 2003-7-26 16:39:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
其实我也很想买了看的,可是我是版主,不用钱。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

该用户从未签到

3
发表于 2003-7-26 16:52:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
讲什么啊?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

该用户从未签到

4
发表于 2003-7-26 20:02:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。# r) T; T& _* l$ G/ |
汗。。
+ ^. z/ w* A2 @+ f水平不够,消化不了。。
; r6 {+ u- z6 ?  s0 h2 h不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩 转发到微博

本版积分规则

关闭

下沙大学生网推荐上一条 /1 下一条

快速回复 返回顶部 返回列表