下沙论坛

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

QQ登录

QQ登录

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

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。
7 w2 f$ \$ y6 J# n; h1 [
6 t& Z# s1 h: w4 m: q4 z权限系统做什么 - \4 o7 f, |* i. i
MySQL权限系统的主要功能是证实连接到一台给定主机的一个用户, . G; F) m. ^2 _) q  m% l1 _
并且赋予该用户在一个数据库上select、 insert、update和delete的
5 Z, b2 S, f! Z权限。
, D! l) d# N2 g& z5 `
# ?  P3 t  ]9 E9 d; l附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如
5 u; g$ d+ g/ ~- j7 |. c8 l8 rLOAD DATA INFILE进行授权及管理操作的能力。
# o8 M$ I. T6 x8 S9 q. j* z
) X; \: s% V8 b4 g: A- i4 oMySQL 用户名和口令 / ~0 F( B) V, t" k: i
由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很
: E  V# t" d: d9 B( P多不同之处: 9 j' D) X# X* A, {& x' ^
5 x. p' {5 C) H
MySQL使用于认证目的的用户名,与Unix用户名(登录名字)或 " ^% J6 E* K  b) G1 V; T; J
Windows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户
: Y$ `" E, g2 Z3 P名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或- : e. ~" w; e  o+ _8 i0 b
-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据
% O" G8 D8 o( t; f5 w) E库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名
) I0 K6 ~7 W- `! |# P字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。
) m$ S" G8 D8 p' Q, ]: t' }8 YMySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。 7 R6 c. P% f; q2 g. R4 _! a% H
MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使 / H1 O9 `4 l6 w1 E0 C. d# x4 }9 Z
用在那台机器上存取一个数据库的口令之间没有必要有关联。
$ E, d! c3 z1 W, }MySQL加密口令使用了一个Unix登录期间所用的不同算法。
* s7 F* _1 Y5 L/ J5 v, [6 g; _0 ^: N) N) {% P
与MySQL服务器连接 % N2 J% X  _5 F5 l6 f
当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定 ; W7 \+ [  a$ y+ W4 }6 \( k
连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql ( L& d  h7 m  V' c+ ?( W8 U; _( a
客户可以象这样启动(可选的参数被包括在“[”和“]”之间):
# g! v+ m7 O! p8 T5 w) f, Y' h
- Q' I' k  Q+ a% P$ E4 Wshell> mysql [-h host_name][-u user_name][-pyour_pass ]
3 [6 r+ _6 i" j% O-h, -u和-p选项的另一种形式是--host=host_name、--user=
* o) C5 {" k# O# p* Buser_name和--password=your_pass。注意在-p或--password=与跟随它 4 ]- }# r7 ]/ F
后面的口令之间没有空格。 4 {/ X) _8 Q0 \! I; x; r3 t

; i( T6 A: N" l( k注意:在命令行上指定一个口令是不安全的!随后在你系统上的任
* Z* M5 `* p# _" [2 K何用户可以通过打类似这样的命令发现你的口令:ps auxww。
% \( t7 X8 {! t& v, l8 o  F4 J, }& E5 }/ Z0 U
对于命令行没有的联接参数,mysql使用缺省值:
4 \& Q' M1 B( M7 {+ |) e
; R6 Z/ d( e/ B+ w$ H! F缺省主机名是localhost。 8 }! `6 h; U* b) l
缺省用户名是你的Unix登录名。 , H" o+ R* U- g1 R. [
如果没有-p,则没有提供口令。 ! x: Q( n9 p- C2 h, ~
这样, 对一个Unix用户joe,下列命令是等价的: + q! X% }% S2 X# @3 \$ b

3 @9 E# t4 @: h7 Qshell>mysql -h localhost -u joe
& j! E* X- ]6 n7 |- cshell>mysql -h localhost : a$ X4 v+ U7 @- q* V- P
shell>mysql -u joe # L0 P% g7 r6 b7 l* Z( p
shell>mysql
0 T+ O! X* i/ b* f  H
2 q! k6 V$ \% B) R  H- s5 k  ?其它MySQL客户程序有同样表现。 % r2 f" J6 M$ g( s& z
6 O8 Y! L0 ]: @/ D9 a; s% @
在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺   m% }4 C( _' f' J( B; K8 W7 p
省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这 - C: ^5 m, ]3 D  a! P
可以有很多方法做到:
: b2 ]1 P0 N1 ]4 [( M* a0 v9 J. Z7 d9 Y. X
你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定
; I& t( Q! ]$ Q" e" s- B$ j连接参数。文件的相关小节看上去可能像这样: ( K  p! Z+ `2 e, v5 L: @) B6 h
[client] 0 m) n6 O% [5 Q# O# g  |
host=host_name 9 E: I9 r; k! q3 a3 D0 ^; v
user=user_name
8 i2 S* n/ a! tpassword=your_pass 3 z  L5 _6 P. i; L& F" e0 C

% d9 o! Z! d) x5 f7 O0 C7 r你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL ( `- c6 m' s8 Y6 X
用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是
! U0 c. Z: d" E( P这不安全) 。
8 O0 m' b) J0 m0 b( }& _( o如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配 0 A8 J, p8 W3 \9 a5 V! `; u- B8 w
置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量
* p- h4 I* {% X9 e指定的值。 ( t! K4 _4 D$ J6 C

  n: E& ?- `& D# Q使你的口令安全
8 o% w0 K8 R; l3 O! T" \以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。
2 }6 D3 p' P: P; x0 W: c- l# ~当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法 : R* `! M# Y, q% Z8 \
的风险评估: 2 a2 j. Z, m, ?

- I* X$ V& H; O使用一个在命令行上-pyour_pass或--password=your_pass的选项。
# f9 `  N4 G7 @% p' _4 X) ]这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见, , A$ E6 M- ~5 T+ O5 H9 s
它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化 * X! }6 \( q" N' g( `0 L
顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可
$ N1 p' T# f9 |- |4 U! K$ ?见的。)   Q3 n5 G9 v2 x; ^( V
使用一个-p或--password选项(没有指定your_pass值)。在这种情况 % S) ^& Q' p- O
下,客户程序请求来自终端的口令:
% q! g+ Q# o/ g& b
0 [. o! V1 D( B6 ^shell>mysql - u user_name - p # z3 x2 A# Y# I' c- ?
Enter password: ********
1 C) M: u$ M. d/ c8 r/ @5 q. B! X! S: c. e) z# k8 V( A
客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见 : d+ v6 z$ z3 ?- T) ~/ {
它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你 9 C! w& q& m* y: z- j( t' f
的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程 ; F8 S3 G% w6 l' S3 o% }
序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就 ) x! g5 G; Y4 U8 D9 ^' x
没有从终端输入入口令的机会。 + {' Y; ], H# J" ^( i) U( W+ o7 G7 v

+ ~  K0 i/ ~$ e7 v在一个配置文件中存储你的口令。例如,你可你的主目录的 " i6 B% D3 M' g
“.my.cnf”文件中的[client]节列出你的口令: , v8 \/ Y* d3 W! O
[client] ( [$ b; L, m2 h
password=your_pass ; z; I& \6 F+ f- Y* p/ n
9 n4 ]1 P- x% w4 O$ i( n) ^; B& [; G
如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或
5 [  n+ @# z7 _$ n! S, `可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。 ; D/ U. U0 G# \  @# A4 w

7 u$ F# Q6 O' n" K7 _你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极
- }( n; B+ p! L8 t$ x1 {不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项;
5 B- L" ^8 m5 `# Z如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有 0 D, i: s8 G! r$ A# z
这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智 1 w  m# s( H- U$ @+ [
的。 % ~( c* D, _$ f% L
总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
1 Q* |1 O% Y! x, \9 o: J8 h) M( n.my.cnf”文件中指定口令。
8 }8 V9 a( t+ s# u! {" K
3 {: z# n" ?( J7 [8 G' lMySQL提供的权限 9 I# `2 ~3 b% L  {
权限信息用user、db、host、tables_priv和columns_priv表被存储
: ~) o3 C8 H5 ]3 N$ f) s; g3 L在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限
* S# p, s5 E% O修改何时生效所说的情况时,服务器读入这些数据库表内容。
! X3 W5 M, R( a0 e- r3 Z* X9 o7 r+ @5 f& @" R# \7 u
由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表 " p8 K+ G: V. ~. s5 Y7 }
列名称和每个权限有关的上下文: $ o. ]; w; S2 \! l
权限 列 上下文 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 在服务器上的文件存取
( ?& e  S: Z" q* D% O3 C# eselect、insert、update和delete权限允许你在一个数据库现有的 3 Z' B/ f* J; l: K0 `: D, x
表上实施操作。
# A6 {5 `; b4 X' t: e/ ~0 y8 `) o; t; M
SELECT语句只有在他们真正从一个表中检索行是才需要select权限, + _" d8 i# @/ h- ~
你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存 - s7 }7 {! M0 ?) z
取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器:
# o  L- J0 Q. D( y- P& i* k8 i) ^' v# x) w. d
mysql> SELECT 1+1;
. h' s% _4 E  \# r4 Hmysql> SELECT PI()*2;
: ~' `' k4 ]6 y  u% r9 }
( d- D4 |1 V" w# n+ `index权限允许你创建或抛弃(删除)索引。 ) a2 z' m# `/ Y' Z0 v; s
9 C; _; g  x- V
alter权限允许你使用ALTER TABLE。 , V. R" Z6 x) G' n+ ^
$ |/ F3 T5 n1 @. q% p
create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的
' y3 ^4 e, P) E数据库和表。
) p* D! f% H, D8 w  b5 j, a, M/ e0 Q! B7 P
注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃
" V3 s6 a4 E$ r$ g3 M0 Z存储了MySQL存取权限的数据库! 4 A8 E8 @& {! H( k. s5 |

; `) i4 T: `- {6 Q5 \/ hgrant权限允许你把你自己拥有的那些权限授给其他的用户。 9 N7 @: b, O" z2 R; A

% ~/ t" D2 t! A1 D& w- Y$ q1 Xfile权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句 6 P0 j5 V, m0 z$ h. v2 ^/ V
读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务
0 z% p8 E- {) q' _器能读或写的任何文件。
. N" h' E. j$ N2 W3 k: p& M, h; z& w0 ]3 E: Y
其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示 ! S% F) @5 M8 Z+ `
mysqladmin支配每个管理性权限允许你执行的命令: : p! x' ^; k+ d$ H! g8 [3 i+ o
优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill
6 D& x, t6 v0 r5 g1 Ireload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开 2 A1 @" ?7 n, h
和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-* , ?* ~- J4 V1 ?* d9 T# W  |3 t% h
命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 " \; x2 n& a) C1 }' K
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的
# y% J: P7 e) b, t: Y* w8 `1 x选择。 & N, D" w! q4 |- a7 p

( ~5 I0 R$ P' z5 pshutdown命令关掉服务器。 4 G4 W! x; ^, ~# `( ]; {1 t
3 f0 ^9 ]5 L* E  ]4 k3 E
processlist命令显示在服务器内执行的线程的信息。kill命令杀死服 ' n% s0 s) N  C; ~; [
务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来
/ O: C2 b* [; ]& |: h9 \( [6 d显示或杀死其他用户启动的线程。
1 O( Q* L0 \: H) E2 |( n8 \, A
& g/ a0 h4 W# E" W总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你 9 Z$ m, u! w% R- J8 A2 o  T5 q
应该在授予某个权限时试验特定的警告: - ~( B; n  l& l+ m/ _

. k* x) o" Y; D- m% P1 K7 agrant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并
" f9 b$ L  ~; E有grant权限的用户可以合并权限。 5 S: H! M3 ?3 A1 k3 k
alter权限可以用于通过重新命名表来推翻权限系统。   L2 `& T; P9 v  r+ j: ^
file权限可以被滥用在服务器上读取任何世界可读(world-readable, ' s" s8 G+ G9 K9 W5 U
即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。
1 |' u2 c& o. W* Ushutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。 4 T9 H/ u+ o1 p; M! j& p* x8 b" M
precess权限能被用来察看当前执行的查询的普通文本,包括设定或改
$ {* M+ O# ~. P变口令查询。
0 d0 X* O% v: E3 S# I在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口 ( U6 Q3 h8 a& n. S
令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够 9 J+ t: d. e7 l; t; Y0 ?
的权限,同一个用户能用不同的一个代替一个口令。)
6 k: u+ K* |, m) ~1 T3 h  Z3 z) |有一些事情你不能用MySQL权限系统做到: 7 u. E; V! y- G% o) N% |

; Z& D- B5 S) a6 `你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹 ( s- G1 W8 Z2 [" d
配一个用户并且然后拒绝连接。
0 F! ?) d4 H# w; Q: \你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建 # ~7 ]: _9 ]9 a  k4 a) Q' z
或抛弃数据库本身。
( ~7 f6 W# x; ^' V权限系统工作原理
& Z3 c0 i1 s1 a3 e! s/ R1 Y1 mMySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。 4 F+ ~- _' M  ^6 p1 l9 A6 d; p
当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用 / R9 [( k  p4 ]+ t& Q
户名来决定,系统根据你的身份和你想做什么来授予权限。 ) U" T7 q$ z6 F3 m

: g- k. q" {: O) u6 H) R2 MMySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假 - O' B  w1 u; c6 W) Z4 u
定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov
& ?9 Q  J9 b! i1 o4 N9 \连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区 # N3 m# X+ I; H' g
分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov 0 X0 w/ h# f) o1 N: _% y. m
连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限
4 P) i7 g/ R, L" Z) D集。
2 I; K" N( @! [/ c) `2 Q/ Y7 D$ S( W7 N& l; N
MySQL存取控制包含2个阶段:
" h* |; J6 V" m, b8 M1 c* Z4 Q
阶段1:服务器检查你是否允许连接。
& j* o% j& g" ?3 W2 `/ Z7 Q' x+ p阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够
1 U8 \, Q" ?* P: a  T* P的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛 / T& {7 Q6 L$ w5 Q, \+ b, u
弃一个表,服务器确定你对表有select权限或对数据库有drop权限。 % w' e4 d9 n- v3 C+ j* O6 {" h
服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host
  w3 y6 a2 |: k3 A( z( G表,在这些授权表中字段如下:
! k; L  h& \3 V) u% }3 h表名称 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
1 q8 l+ i' d  \0 T# C: U# ^3 y2 C4 p对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外 5 I! B- l! x/ \4 @: R/ d
参考tables_priv和columns_priv表。这些表的
. {; n" z' O; n" }0 [. T) A9 G+ U字段如下: : Y, W" p* A, f1 ]; |2 W
表名称 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
( }3 Z5 D9 P0 X) \) q对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
* U4 ~9 Y+ U$ k  z4 G参考tables_priv和columns_priv表。这些表的字段如下: ( o' [; v, ^6 m
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
! P, b7 H" D$ j5 f- @在user、db和host表中, # D! Z: `" N* U2 J- G9 E  h. o
所有权限字段被声明为ENUM('N','Y')--每一个都可有值
8 M$ H! M* |) Q3 d. p; @6 ]. j0 a'N'或'Y',并且缺省值是'N'. 3 V) s" @" |1 ^5 J' G; f4 G: i
在tables_priv和columns_priv表中,权
( ~3 `! ~4 t: n+ B! _- V$ E限字段被声明为SET字段: 9 j& y1 g* G& Y' x) t$ d
表名 字段名 可能的集合成员 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' 7 l) w2 U3 E  |! d, K+ Z
每个授权表包含范围字段和权限字段。 ) b6 D3 V- G4 E' t3 X2 m

( l- X8 H" y. R+ u1 @范围字段决定表中每个条目的范围,即,条目适用的上下文。例如, & z- e4 I) ]$ M
一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于 6 @4 U$ r3 I( w' Q/ ~
证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条
: O- _9 g+ V2 P2 y/ s目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'
3 z; T2 y( S/ Q  h$ U将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。 - j" P2 H( M1 R( W- L" w3 |
tables_priv和columns_priv表包含范围字段,指出每个条目适用的表或
0 A& H) X0 ?; r表/列的组合。 + R/ m5 l3 E% R2 r# B! Z1 d/ w
! ^, R. S. g  O, D/ X
对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
4 P- S* o2 x) {9 \Db和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以
" E1 e7 T; w6 j1 ~, g4 x后版本是忽略大小写的。 $ _) m- z/ w0 {3 a

- E$ D/ e3 u- z7 r4 T$ X权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务 7 |, K& f; A# [9 j, e
器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规 8 O: [* ~% M6 R% o9 u
则在6.8 存取控制, 阶段2:请求证实描述。
' g* Q* D9 \6 c# r. i, _2 U/ i; z* [" y, }
范围字段是字符串,如下所述;每个字段的缺省值是空字符串: 3 N$ J; X3 Z! @4 q7 N
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
; b+ n( c* O2 d在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一
1 G  _. p9 O* S" _% Z" p- _4 ?个都可有值'N'或'Y',并且缺省值是'N'.
2 i/ a% i0 R* a& _8 p' J' X& u* f% N2 L# ~4 I# _9 }6 H- b
在tables_priv和columns_priv表中,权限字段被声明为SET字段:
2 r6 n4 o) y% }; T3 D表名 字段名 可能的集合成员 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' 1 X* L+ a% k7 n2 }1 b+ J; P
简单地说,服务器使用这样的授权表:
8 ]7 x2 V% p4 ~) n5 O+ [
: \3 s' `  u% A( t8 Quser表范围字段决定是否允许或拒绝到来的连接。对于允许的连接, 9 k/ ]' g- r+ C, _. H5 i# o" D
权限字段指出用户的全局(超级用户)权限。
! `/ L6 R* j4 K( Cdb和host表一起使用:
* a6 M- q& D4 tdb表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定
3 h5 s' D9 G8 b! f8 N允许哪个操作。
1 D) D1 K/ O. I( L当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩
% P# ?9 {" M( P( \1 V展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个 - V( o% N' c$ z# w' G1 u
数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移 * B6 H, M" a% @3 h1 h3 X! d
入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。
2 b  _7 S; \  j8 G5 p- Y' o( Htables_priv和columns_priv表类似于db表,但是更精致:他们在表 & H$ ]% \6 @5 L# j6 v! a8 O! G
和列级应用而非在数据库级。 % Z" c5 B6 D5 m' H9 a8 {
注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是
2 Y2 T8 \  F9 C  o因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由 * w+ }0 f& }3 t: ^! _: ]5 u
在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是
7 l7 V, s: _% _$ V; P否执行一个管理操作。
9 X; I" y( p' i) z2 {; m/ _4 y/ J$ v, }
file权限也仅在user表中指定。它不是管理性权限,但你读或谢在服 . q% P: S! F2 \9 M, s
务器主机上的文件的的能力独立于你正在存取的数据库。
- `8 v4 V: W; W# f3 z$ g) q' R6 T" B1 W+ d8 M
当mysqld服务器启动时,读取一次授权表内容。   x* s; y# s9 ]

# d  {, v+ }$ J7 P当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一
2 G& U" \4 L% \! k个好主意。
) H1 \+ W: G0 L8 a# o; m0 e8 A
% H- O. e1 @! `( U一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给 : Q3 e- ^  g5 N7 {1 b5 j$ w
MySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意:
& H5 J+ U1 z+ l: S$ p  cmysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。 5 P' B* ?2 L) `, g5 l* k
; |- t+ B% x9 \6 q& g+ _2 d3 ]- A; z
存取控制, 阶段1:连接证实 " v8 I, ]+ R8 l7 l9 z, x5 i6 B
当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能 6 C+ u+ i' |7 ~) e
通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全 4 q# [7 i1 D/ A' p" H( A* n+ U, Z
具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。 , i3 O) f& v8 P# ~0 C
6 G1 q3 ~  b+ o- C$ i$ P
你的身份基于2个信息: . n& ?7 Y3 H, D* N+ U% `1 n

3 ?5 x  y- n# X0 A; e你从那个主机连接 2 K! R0 f& S  W2 X9 M
你的MySQL用户名
$ T9 }4 k. `5 k- r" C身份检查使用3个user表(Host, User和Password)范围字段执行。服
  A( G# u: [% c8 Y7 |务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的 / M6 j5 o$ d5 s& b
口令时才接受连接。 ( a4 V5 i4 g$ ]8 z* K
% k* K- B# N3 E- K. g9 X7 d
在user表范围字段可以如下被指定: + H& |, @0 F/ l
3 n6 N3 ~1 T! X9 W& I/ Z
一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。
) o% I) ~& d+ x, C# x2 w你可以在Host字段里使用通配符字符“%”和“_”。
8 X% X: r# l+ |一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些 5 l! T: K$ ~# g5 D  n7 A
值匹配能创建一个连接到你的服务器的任何主机! 1 G5 B! _0 F" t% `+ F
通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何
! b/ E4 h! Z8 L6 K$ I1 w! B; i名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为
* Q, {# V* Q9 {+ n, m* C8 n是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空 0 ~0 z3 p  M% {5 o
白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。
' @! P$ l) ~& X# L" f0 a8 ]& sPassword字段可以是空白的。这不意味着匹配任何口令,它意味着用户
) p0 q$ K; [- N2 ]* L必须不指定一个口令进行连接。 2 G  Y+ o7 D+ g' [
非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本
7 P3 i- P; X) Y3 e3 A0 u格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用   f: ?; z0 \9 \3 p* w* X5 S
PASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他 2 L; Y0 v/ _# I9 I6 j
们匹配,口令是正确的。
) c; n! z! g. n& k" U- Q
! F1 r  `3 @2 K( a下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来
) R+ c: w. G4 g% k6 u; X' t0 e& Z的连接:
' ?' ^; Q3 \) r7 N( e) Q
1 ?' O# |; V8 Y3 U& }' q& h7 IHost 值 User 值 被条目匹配的连接 5 k; q. x# z8 R& N& h8 M' `# h
'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接
) I1 P; X8 t8 W4 P$ ~$ h- H'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接 0 A3 Z' ~" B6 l; C
'%' 'fred' fred, 从任何主机连接 7 n6 K6 g- R; H1 V" n
'%' '' 任何用户, 从任何主机连接 . y( ~6 A  v- H% g8 v" S
'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
4 l* C7 }5 U8 {, y, f2 k4 g'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许
7 u4 h4 l+ S1 L/ o; b无用)
, N7 G  k4 J, ~  n! n'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主 : |, ^  F0 t& W  T# m3 K
机连接 7 v, u/ w$ q1 c# v6 G
'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连 & e& Y* A" }0 d- n

3 V+ s& z/ c! W/ P/ w/ a/ ]# D5 ~; E. t! i
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子
4 h) A( T3 W; }7 j7 }( J5 Z/ D; x0 i网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机 + S5 T5 D9 O* ~5 D2 J0 u  ~/ v/ [- s1 M
为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以   ]8 [# P" P! ?9 _" f& L/ B8 f4 v/ i
数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的
; w2 d" T" q" d主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配
9 B/ q, v% o+ q符值。
% f# N, ]& X2 z0 }. ?/ D. ?1 r9 s- U* t: t( G
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由 ) `+ I0 q7 Q4 y' H
fred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配, / L2 i, `* o3 Q% l, o
服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来 4 k7 z4 |; c, H" h0 ?% b  n& D" A6 r
解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一
5 t! _& C9 j- `* b+ y6 s( G个匹配的条目被使用。
7 J' H( c4 t! m5 n) u+ m5 ]) A! [0 l& p- m4 {
user表排序工作如下,假定user表看起来像这样:
. v7 P  i% L* s( K) ~! h! N
3 v/ p. p2 A7 R* H# x  \' B7 O; s- {* ], O2 O; B/ w4 ]' E
+-----------+----------+-
4 B8 N4 ]: X/ U$ N* r$ D3 \│ Host │ User │ ...
2 }/ f! _. Y' n' x8 y+-----------+----------+-
: H2 g2 m4 y: }│ % │ root │ ... 5 S$ E. y7 ?8 \6 e. I* w
│ % │ jeffrey │ ... . a/ [2 w5 ?" m
│ localhost │ root │ ... 5 }2 v* _9 p' b% _/ y$ o" X+ [3 {
│ localhost │ │ ...
( B* E0 F; U: r: a- I3 T+ C+-----------+----------+-
7 w& O6 I, }! w, J1 a
6 |, a" T* B6 f6 K, B1 n! |  T8 e当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在
+ x; p1 x- L( q- i* Z+ g. i" rHost列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以 / X! b  f7 l2 a- ^
最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且 * ^& }# l+ K, }. g) Z" i: d; }1 d" ?
是最不特定的)。最终排序的user表看起来像这样:
2 ?% U/ D; q) N9 S( {1 @- h
! l0 H- e" k. `, S0 q
1 G3 M1 C% t7 `" y6 D+ Z9 D+-----------+----------+- 8 X( \; _% D# d! h. L" K6 u6 B" n
│ Host │ User │ ...
/ W4 `! J1 h5 w( s/ s" X+-----------+----------+-
' F8 @4 N: W  p+ T4 r2 s2 X; F* C- I4 |│ localhost │ root │ ... - a0 [) t7 l$ }' `( H' S
│ localhost │ │ ...
3 k& p9 R3 c0 L5 S7 G. {9 y( ]│ % │ jeffrey │ ... ) Z6 B4 U. U& R# d2 `' i
│ % │ root │ ... 7 h9 R: _4 ?+ V1 G$ R
+-----------+----------+- / A; s' J  q: ]

! g5 Q( A# e7 k) O; n' _  ?当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹
' F; M* k& N# \( H5 ?& E配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目
8 C- ^4 M9 G4 K6 \- Z首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/ - g' s  H+ [/ g% A4 D7 @5 p4 t
'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。) 7 T: T$ R% W: h. y( I9 i

; r' ^0 o: ^$ A! X( ]8 M8 x这是另外一个例子。假定user桌子看起来像这样: ' r" ^! I- Z5 H* y+ n# t5 E9 I

. A, u, L/ S, t" N0 m$ ]& O2 [" w) K9 S
+----------------+----------+- 5 ]9 E$ g% u( @- U3 ^9 U- Z. ]
│ Host │ User │ ...
7 I' C: Y# @# m8 J2 U* b+----------------+----------+-
# j2 R( a+ N" v$ B# o8 J4 A9 p│ % │ jeffrey │ ...
( T6 M- O& |) v  e6 p% ]. X│ thomas.loc.gov │ │ ... + ]1 m; b* z; U1 Q7 b
+----------------+----------+-
* X8 d# D$ K& z4 b! G
( l- [- s0 A! v5 K% h排序后的表看起来像这样:
& z% Z2 B; Z4 K: C7 ]- O8 G2 `( A5 M1 A6 {% x- P
! c; m/ G( V: w( g, ~
+----------------+----------+-
& j6 \# L" r. `" f& B6 W+ l│ Host │ User │ ...
7 Z4 Z8 n, ~7 v, Z1 I+----------------+----------+- ' P/ |3 u. a' I8 i
│ thomas.loc.gov │ │ ... + M+ o2 j' ?: L7 n+ l+ z0 f$ l: F& G
│ % │ jeffrey │ ...
1 @) B* ~& [5 n# D  r+----------------+----------+- ' p- T2 S9 D# s

# k. V9 o; k# x4 ~0 B一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由 " F" g& c, D, K- r
jeffrey从whitehouse.gov的连接被第二个匹配。 ' E: I2 W# t- `) Z& [& S

. O+ ~8 C4 \/ J* i3 S) ]普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找
- P3 e* W) u3 l$ H: ~( ], q匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。
: v6 ]$ e/ H# B# E先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没
8 u6 H5 [" Q5 u3 T! w6 I0 z被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹 : C  M4 [) ~- H
配!
9 \3 |! T( K, i5 H( Z3 I" a8 X* ]) @, r) g/ U- u
如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个
  f" `4 G$ s5 Z1 W& B& n- G; _1 x匹配在哪儿进行。
$ K' t( e+ F9 R4 b' u  E5 s7 j- b& X8 {: z) @# ?
存取控制,阶段2:请求证实 * g! f' {$ y5 @
一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个
7 T6 O; c# |1 c, J6 Q请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作
* O% `: ~) f( x4 K类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子 & R$ v- D2 h9 L" `1 ^, i& S
user、db、host、tables_priv或columns_priv表的任何一个。授权表用 & Z& S* t) f2 b* E3 Y
GRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参 $ b% Y' o9 {8 Y7 q( Q. ?6 S
考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。) + D5 d% S6 J* X0 ~0 W
/ Y7 D! k8 N; e
user表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库 * Q, b: [4 w* S/ S5 N0 D% c" |
是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器 2 j) X% K8 M+ [* D0 y0 A
主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把 9 m9 _6 [" U0 }
user表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户,
# Q2 u4 l+ f1 L* c$ f你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权, ( Z0 a6 C1 O: m1 \4 o2 \
使用db和host表。
. k0 n& H. |9 Y. ~
0 l, O4 [: ~6 t4 E, ~db和host表授予数据库特定的权限。在范围字段的值可以如下被指定: 3 b3 p6 z$ c4 k. H: I+ O
* A& D/ N) @- J* ?; w
通配符字符“%”和“_”可被用于两个表的Host和Db字段。
8 k" y: ?/ F8 \0 Q9 q* W7 N在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 , V3 I" A; \2 D6 e
着“对进一步的信息咨询host表”。 , _6 p$ J+ b- H; U( T
在host表的一个'%'或空白Host值意味着“任何主机”。
, T5 {! g/ c5 g# J- `; o! Q! Q+ ~在两个表中的一个'%'或空白Db值意味着“任何数据库”。   Q' ]: \1 I. u. L2 m( u/ Q
在两个表中的一个空白User值匹配匿名用户。 ! M; u( J8 |( ~! b: ^
db和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host
4 h% J( y4 _$ N; E, G9 _、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于
; q& k9 [0 Z- V8 Nuser表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 4 r/ Q5 J* }/ }& T
匹配入条目时,它使用它找到的第一个匹配。
) b; w8 ~! Z& W+ O
" [; N0 E8 f8 l! a( V0 e3 c6 K0 Wtables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可
( F& v3 ]$ E" g) Y% `以如下被指定:
% J9 x: S# ]7 u! \2 |3 T7 M1 A& z6 |& n$ d3 W) F
通配符“%”和“_”可用在使用在两个表的Host字段。 1 b2 _2 |4 J" R1 b, [
在两个表中的一个'%'或空白Host意味着“任何主机”。 / p6 Y3 n: T8 p! X" p$ Q2 e7 D6 \! |
在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。 " N. B2 l- V" p
tables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于 3 N  `+ l6 \7 E8 G9 u2 b0 s, c
db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。 $ B" T4 z* G$ e! y+ w' z2 ?$ m
6 ^% S4 N% e- ^3 A# x) _
请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这
3 [9 p+ j* c% V; W; b8 v/ z/ g里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是
0 u# u3 o7 m' D2 k7 l, N$ G不同于使解释更简单。) 9 p. t: N* x8 z% R4 H
7 o. M& X  R) @# S
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是 5 J. ~0 u/ [* U8 ^4 w0 `2 q1 ]: I7 A
唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。 8 z" k7 G8 a. [3 n
例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授
, q8 a, n2 E/ J1 k& w% T' o4 \, N予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含
8 V* g4 U( E; tShutdown_priv行列,没有这样做的必要。)
' S, z& P  y: h, Y; O/ m8 k  c& H- K0 O. [- T: Z) k( q0 L2 u
对数据库有关的请求(insert、update等等),服务器首先通过查找user表
, F! A( o1 }4 s) q. i条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授
3 t& X$ l4 J8 ~权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用 ; D7 q1 u% E8 ]% a8 t( `
户数据库权限: : y6 Q# P+ J5 h8 W& N# O
8 a* h6 X- v6 x* ?
服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连 4 U% z% L3 i- n
接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有 * Z$ ~8 F# Y1 F  n5 x4 x
Host和User的条目,存取被拒绝。
" p* a" ?3 ^0 B; v' j! X  Q3 J( g9 v如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用
# C$ N* G3 E+ ]) o- N& l& I$ I2 |户的数据库特定的权限。 + f1 Q8 w) k! F: r
如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被 , P3 J! F' V. ?) d& U
允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和 $ `( b+ z1 t/ [1 w  Y9 `
Db字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数 : b% _7 R: Y/ M
据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交
( N+ `8 p$ ^. @4 _" F: o1 z集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host 9 R3 F. m; J/ ?( w) L* q/ x$ A! H
表条目按一个主机一个主机为基础地有选择地限制它们。)
6 T! [) p! d; n* A- J& |) f0 n在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
2 s( x' Z+ G' r+ q% a由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 , l( `6 K% ?) m, M
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到
% T% _* J5 [, I5 ?用户权限中。基于此结果允许或拒绝存取。
  f% c9 H8 y! ]& x$ F1 y
2 n. N0 y2 p6 C( U用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结:
! K* S$ X. I3 h9 P
# X& s) g9 K* R$ g: bglobal privileges
+ ]) e: D; O. z& x, aOR (database privileges AND host privileges) ! L! g* n/ D1 b' B8 m# z/ A3 i
OR table privileges
1 r; @% [' I) Q: W0 C  XOR column privileges 5 d+ `2 ~" Y* @% K- g

6 r7 R+ d+ t; b. o4 M- f它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不
* u" R4 u, @7 `- Y* O/ v够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能
1 K1 u1 z- u: U, j0 ]! {& N# ^要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都 5 b2 N7 J  D* `9 ^( s
要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 * R$ ~! i+ c9 W! Y4 |% W+ ~# D
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把 ' A* ]; q( R# J" w( j) E1 G
两个表区别开来;两个条目授予的权限必须组合起来。
% |7 w+ x' m; {: D% C5 K7 r- q9 v
) r9 G* r/ Z& F9 _3 Ahost表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本
' V+ V) r. ^* |( E0 l, _* F地的网络上所有的机器的表,这些被授予所有的权限。
: D& K2 \% w$ |% [+ ^6 j/ K/ u7 g( G
8 a) M$ K4 V  M你也可以使用host表指定不安全的主机。假定你有一台机器public.your.
' _5 P$ G# P9 A4 s- r9 mdomain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允 5 ~: t5 e2 U: |
许除了那台机器外的网络上所有主机的存取:
+ N. W; s  n: q% _+ I8 B) O' Q4 v* {7 H  U
) ^, w9 _1 ?1 o  F+ A
+--------------------+----+-
# p+ n) J% g! Z. e( g: R│ Host │ Db │ ...   ]8 y, C- N3 }' C
+--------------------+----+-
3 {  a. U; d+ F  |& N# }! N│ public.your.domain │ % │ ... (所有权限设为 'N') ( o2 g; f( Z+ o5 k5 y4 m, Q, u
│ %.your.domain │ % │ ... (所有权限设为 'Y')
- e' d5 L; D# c# o+--------------------+----+-
/ D6 Z2 |3 W, W4 D1 t( {. h6 B+ o1 x$ P; J
当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保
$ F2 K# B2 i) N你的存取权限实际上以你认为的方式被设置。 " F- X& l% n- M# Q& s

1 |: w, d9 f$ Y5 M权限更改何时生效
: b) K* r  a& ~7 j' ~当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。
, b$ A  Z. h, H, m' m+ V
. c! H: p; Q' o, U/ F$ E用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
8 U  y3 I( f4 u) ]& M
* C4 q! }3 X! z( [! P# n如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH 7 R2 K2 Z6 D' P; c2 s5 M9 w
PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否 * A0 X; A6 m- |; w: ]2 a
则你的改变将不生效,除非你重启服务器。 9 D- Z$ I, ~2 p1 G
# _8 J. v7 s' a) U  `
当服务器注意到授权表被改变了时,现存的客户连接有如下影响:
0 U8 ?* |- n4 n- q; F% e/ h5 ?9 p0 H1 n7 z* W$ q' h  H2 F
表和列权限在客户的下一次请求时生效。
: e3 Y0 `+ H- h/ e数据库权限改变在下一个USE db_name命令生效。 9 z4 D2 s- q* N, a) f
全局权限的改变和口令改变在下一次客户连接时生效。
  M/ ^( F8 y0 F. t; l8 B+ f4 l% E; f
建立初始的MySQL权限 # m, N5 l  G9 _# w* v
在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。 5 K9 e# W( O8 F  w' |5 A. t
scripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列 1 U' C7 g; W% Y- n. ?
权限集合:
0 z' R/ B1 U; f* v- d7 M$ k" y
0 J, R2 M7 l5 h+ b- \3 a6 eMySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主
# R7 _' f0 O- S6 v7 D, H; n机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行 / c6 i* `% U7 M% C! c4 N
连接并且被授予所有权限。
8 `8 T. B, h0 F' n一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库 / O6 ]% w% G3 C* o9 B2 X
做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视 % J! H- C( b% u
为匿名用户。
* }9 d' X( E; u/ x  [其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或
; u8 g2 u. N& f8 emysqladmin processlist。 2 X# G1 w# M6 c! ]/ B
注意:对Win32的初始权限是不同的。
7 N8 j) K- @  O- c8 U* n3 e. s- a6 z1 `1 ~) g* {8 N
既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户
9 J0 C5 ?, y; S) ^6 t$ q: ?指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令): 1 I& w& Z. e! B3 N

& e8 C2 V/ q2 [2 o9 Oshell> mysql -u root mysql 6 L# a( u# l2 o" M  n& E0 C
mysql> UPDATE user SET Password=PASSWORD('new_password')
# n( P  G5 ~' u8 `/ h  cWHERE user='root';
( R- x0 y; Z' A) Omysql> FLUSH PRIVILEGES; 8 @& O5 x& M3 q3 ^$ D$ A* b
. t+ N/ s% |  a
在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句: + ^1 f  {9 O- ?/ V1 x5 s
# B' P7 c* l) y4 w
shell> mysql -u root mysql 9 t7 A. y2 v6 _- C8 J6 o6 M
mysql> SET PASSWORD FOR root=PASSWORD('new_password'); 4 ~: O/ ~7 R4 r1 F
% F/ T- \/ X) ^: [
设置口令的另一种方法是使用mysqladmin命令: ' E. P6 ]+ K' ~: r. U; i% A  v. b
0 W' a0 h: T! V' e  I3 r
shell> mysqladmin -u root password new_password
$ _" ^. P& F8 n' h( o. R+ U
7 [3 I3 v/ V+ {" b& N) b2 e注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器
$ e9 Y: G4 r7 z" Y# v  X& M再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。
( y+ z! ^! [& U) l& v: E4 H# T) c8 B5 z6 x1 ^" n  ^
一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个
1 L: T* K* f1 m* i口令。
$ Q% O) Y/ [6 P2 }& b. r) U+ M8 g3 W3 w4 l" _
你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它
3 J7 ]5 e/ L4 K2 f5 r或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。 * E+ F5 {0 t! z2 P

: T: U+ N3 a2 c, a看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它
. W6 v9 K7 d: A) B作为一个研究如何增加其他用户的基础。
3 l5 C3 o2 W& Q8 }! h+ y# u( P) L5 Q# J. L9 U; I% K
如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db
6 I0 B8 b1 M0 ]0 J之前,你可以修改它。
- j" c4 g7 C0 ~, g6 G4 J. G
+ G8 p: q% ]+ D! S- ?+ m1 g0 C为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”,
) i4 t" u7 v; f/ A; @& ^3 y“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,
8 f' r6 W1 ]$ Z8 V! K当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能
( P9 Z4 d) Q+ n  R" m) K在首先编辑它拥有你想要的权限之后。
# G; u, U3 J: ^, b1 A$ {' p; w& I. c$ O8 a8 n. T0 y
注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果
9 s$ a. K9 {" ^8 \  c你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。
6 p& p" J/ {0 V6 `. ~  h( Q0 _# i: p3 |
向MySQL增加新用户权限 ; O2 l4 C% G) e: X+ @6 J1 j
你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授
/ O2 F: Y- ]) F4 P* J权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。 * l1 [" W- w. w5 m( q. G2 F
) U7 v, u: D( {$ h/ R7 ^. g
下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前 ; I, _! r% E# e! Q
的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台 # v4 N7 Y( O2 s' ^% X% @
机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有
* B$ X- ]& f. {; F! ninsert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下
7 m" x* K5 v9 n0 O. ~的mysql命令指定它。 ) I3 W- C! m' v+ @( d0 d

0 e; `  \, S9 Y: h$ [/ s! ^你可以通过发出GRANT语句增加新用户:
8 t0 C. o- k8 o4 q' W
4 V! U8 b/ W, wshell> mysql --user=root mysql 9 U3 _; n1 k9 G
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost
1 H7 C& V3 J( O- L; M. ZIDENTIFIED BY 'something' WITH GRANT OPTION;
( M. B% B( V) k" z2 G" D( Nmysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%" & ~; R  t. d2 o+ s. ~
IDENTIFIED BY 'something' WITH GRANT OPTION; 6 q6 t# Y0 l" ^3 ]+ g; C5 P
mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; 6 ~, m) V" S- B* W4 p" n) T! J
mysql> GRANT USAGE ON *.* TO dummy@localhost;
" e$ {  }. L3 Q! C' @& ~
# F' U, B4 v9 C这些GRANT语句安装3个新用户: * ]0 B' r0 P6 s) s' M& P) V2 h5 l
& p& n# _7 S! u" C. S
monty
5 I6 Y9 _; ~4 d/ R可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个 ) c# q% O; ]( F' }9 Y0 ~! {
口令('something'做这个。注意,我们必须对monty@localhost和monty@"%"
) a. t' d* T$ L* }' f发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
; ^% a1 l  t# }# i在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为
) ^6 u& K  v# n+ P它有更特定的Host字段值,所以以user表排列顺序看更早到来。
, @8 q/ `9 f$ Hadmin % B' a/ E: u4 O
可以从localhost没有一个口令进行连接并且被授予reload和process管理
' P/ `8 n' h2 S* R; X8 ~7 s权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和 & |6 ^3 ]; J* N
mysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有 8 J: U: y- L4 z% X: E0 K9 W
关的权限。他们能在以后通过发出另一个GRANT语句授权。 % I7 w/ [& t/ t" Q3 T
dummy 7 F/ t, o1 Z% z4 V/ c7 r
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设 8 `1 x" Y+ \+ x+ K9 @4 c: e+ s$ X
置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以 ' @( G) ~3 q, q- \0 U
后授予数据库相关的权限。
$ F; @0 a, z5 G+ H你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服
. B; U9 ^9 `8 L7 U务器再次装入授权表:
, Z" o. j/ d3 K8 x. i5 F! e1 Z, V- O
shell> mysql --user=root mysql
  \: @% _& [' C3 H+ f) o+ m. omysql> INSERT INTO user VALUES('localhost','monty',PASSWORD
% q& A: C% U, R6 i' _  {('something'), # u. A! d  J7 n
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', 9 g/ }! C1 D3 q8 A" u; _
'Y','Y')   |+ a7 x6 N4 }3 \9 a9 m- y
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'), ) t7 F' L% j# E5 O% y8 Q% D3 e
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', ! ^: [7 U' V3 C' W
'Y') * |4 r: _% P) Z( A( v9 s
mysql> INSERT INTO user SET Host='localhost',User='admin',
( S1 p1 X' ~  L; y' AReload_priv='Y', Process_priv='Y';
9 I1 G$ I( m6 `; @* S4 {mysql> INSERT INTO user (Host,User,Password) # l8 y1 a+ t; n. Z* e6 x* S
VALUES('localhost','dummy','');
$ F( h: F* F* D) o: h+ u8 pmysql> FLUSH PRIVILEGES;
  g# A& `9 S! f% @- u
/ F: h2 x) p# o取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
& h3 j' ^6 R' S1 ~, |. |. r5 \3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版 2 S$ ~' X" d4 f+ `$ R* B# B5 b- K8 V
本具有的更加可读的INSERT扩充的语法。 4 j0 U+ ^' q1 G4 p2 g

+ h4 T+ n; P  K" O注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为 * Z$ t7 }+ ~2 ^& W
'Y'。不需要db或host表的条目。 * [; ?* a4 a: Y/ t* w

. j3 }6 r* \3 M; \在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户), 3 j( E1 ]" X; C! K5 Z
因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
! A; ^0 B2 X5 D  e9 R4 s  T+ K  c( @0 B6 @# E6 `* S) }
下列例子增加一个用户custom,他能从主机localhost、server.domain和 4 k; j( V8 _8 g" y2 L# r) e
whitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从
$ U- x/ Y& U$ d* u  n9 _$ G" Wwhitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他 . l& S# a' i4 ^3 X. M
想要从所有3台主机上使用口令stupid。 8 u9 `" \- ~/ J
- R: J5 p( J8 k$ D' C% I9 |
为了使用GRANT语句设置个用户的权限,运行这些命令: 9 v3 P: B. K$ `8 C5 d0 R% m

4 d+ |4 K6 s4 C& @* |. [shell> mysql --user=root mysql 8 @6 X1 ~+ A$ c3 Y9 G
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP . G, d$ E4 F1 r6 k; Q
ON bankaccount.*
, j2 R- Z3 R  aTO custom@localhost 8 a4 K# w7 }8 {& J( w* L
IDENTIFIED BY 'stupid';
  C2 q8 J' K! }mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
+ K& _! h+ c/ b8 M3 C) A. a" A( N) D: cON expenses.*
( S; C4 @4 y' q6 d. QTO custom@whitehouse.gov
1 ^( D8 d- H( o! \$ |  _, DIDENTIFIED BY 'stupid'; 3 b7 V4 J- k- z# k
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
% V+ ?# V3 i5 R' ~' FON customer.*
* F; L4 \: H% S: ~7 LTO custom@'%' 8 s. c" A( j8 k+ T* j
IDENTIFIED BY 'stupid'; ( h& k9 @  ?3 m" V2 q

- z! u% j# q1 |# P, a0 c# Y3 O- v. |通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时
' F& [5 F6 j; g3 G9 m( |# u8 hFLUSH PRIVILEGES):
9 e& q, M* x2 L) ^( m, v; V' F& Q& l
shell> mysql --user=root mysql / i6 c: Q0 u' N8 D& N( d7 c# A
mysql> INSERT INTO user (Host,User,Password) : s; j0 B' R4 A* L! Y
VALUES('localhost','custom',PASSWORD('stupid'));
" \) N) m8 o, g) J+ B3 j! Hmysql> INSERT INTO user (Host,User,Password)
  Q( h( ]( ^. ^- Z; O, QVALUES('server.domain','custom',PASSWORD('stupid'));
; y4 ]/ l7 N2 f* j  Qmysql> INSERT INTO user (Host,User,Password)
5 v' i, {* G  O) KVALUES('whitehouse.gov','custom',PASSWORD('stupid'));
, \5 F! V/ v- g! y0 }6 J0 a$ y. S7 cmysql> INSERT INTO db
, _4 T' i3 l" s(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, 8 R# q5 K4 E) F$ p
Create_priv,Drop_priv)
: n& l! C2 K2 s: y3 e0 z0 {5 r7 ?& RVALUES 4 W1 e* e5 B# E! \, A! k  h
('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
2 f. H, h2 ?+ q$ w  [# q2 M- g. dmysql> INSERT INTO db 3 t; d% S7 O' G: l. M- u
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
; \! z& q' S: I, v6 uCreate_priv,Drop_priv)
  t: r/ ^  G% z9 V& }$ H8 X& S. iVALUES
4 D' W0 Y1 c( w. a('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
$ B# Q: N' S4 G9 T4 A' W& v. f9 ymysql> INSERT INTO db * o' ~8 y! @& |$ L/ V# i
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
4 y# ~9 d- k0 S; ]! H- ]Create_priv,Drop_priv) $ _* ~$ ]% E, q0 y( [
VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y'); , f* E' e8 |9 m' ?0 c* _
mysql> FLUSH PRIVILEGES; 1 w7 H: P" u* `( w  P

. s0 G# R% i% p头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机
  Z. h3 a9 O' G" W5 c进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT 1 i, p: I" q3 B& Q, B) D+ _
语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限,
4 z# b6 L0 d* D8 h但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告
: q0 t1 K, d+ j知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。 ! F; X$ O; M/ ]' s/ |4 |0 V  g

8 N4 L6 K3 c1 d/ H& K2 C1 a如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发 % C: c4 \# ^1 E7 ^) W0 j
出一个如下的GRANT语句:
+ G0 x* C( k8 V& \3 m6 @( Z9 e. ?1 M9 A
mysql> GRANT ... $ O# Q- @6 _1 M/ T- ~& d
ON *.*
/ }1 o" I) j1 j6 n  f% {; v- u% t: u* UTO myusername@"%.mydomainname.com" + S8 s6 S6 ?3 t8 y7 e
IDENTIFIED BY 'mypassword';
' J  T8 U3 n; U4 w* a8 P. k7 j* y% C$ h
为了通过直接修改授权表做同样的事情,这样做:
  b  g8 D2 @9 Y; U7 Z
" U8 R# y5 g: i* j. F3 Ymysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', ( j1 p/ v& S6 ?% p2 I  ]
PASSWORD('mypassword'),...); 9 J. J) [0 F6 ?  S1 }  @1 ?7 ?  n
mysql> FLUSH PRIVILEGES; 9 \7 m( }$ ?5 i7 g" n

3 |- N& `/ l6 n你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变 ; U3 D2 u9 w( \& l; J& B# \
和更新值。你可以在MySQL的Contrib目录找到这些实用程序。 9 A* ^6 O3 C" t3 P+ O3 p
/ u) L5 J2 ^$ ?; H  m& Y
怎样设置口令
' A  H8 t( h/ V6 z$ s. g. ^. Y在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存
/ H9 V$ H& m" y# Z" U储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以
2 ~, K( M: A( }0 \! |; f' B( k加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图
2 Q# p- g) R0 X" n设置口令: ( O& w  n8 n8 x8 o# t3 ~: j5 h  L
! [' }; t, v0 `# v: s
shell> mysql -u root mysql * h1 J6 s8 B, o
mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey', % {  o( c2 U. U2 B7 n
'biscuit');
# y5 l$ x  i' n6 g7 i# M& R: Qmysql> FLUSH PRIVILEGES   C/ G/ q  p. u. f
, s& d; O4 `" @% ]' l
结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用
- t7 P0 j# P% A# Q这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服
! O) D6 h( J5 {' B$ J9 @+ ~务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是 , _2 l5 G* e, g, Q% w( }
'biscuit'),比较失败并且服务器拒绝连接: ) M2 f4 [) z% M! t9 y1 [1 {

- B. T1 h/ M9 v+ [) [) Cshell> mysql -u jeffrey -pbiscuit test 9 r4 q# r3 A1 q7 O9 U4 a% O
Access denied
" r" W3 I5 }- }5 @# N/ y% G2 P& _3 q' i. r$ u
因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样
( s: u. U# J- K$ W被指定:
" N- j& H- j0 h' a! r3 K- F# Z. v9 A: E# V
mysql> INSERT INTO user (Host,User,Password)
: k5 H9 ~; g* W+ p7 KVALUES('%','jeffrey',PASSWORD('biscuit')); # h1 U/ R/ S5 U: N. c! [6 w

2 u2 E5 b" _# A' V# v当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数: 8 r% e; o: x  L
& {% C! G: x% {7 l" a9 H
mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
6 r$ ~% }4 S2 @: X, m2 H$ L( Q& n' c& U, Q: i; ^# Z
如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口
% M( c1 _/ }. t3 ^" Z$ I令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指 ( R( j8 o: \: M# G/ S( ~
定一个口令'biscuit':
# j/ s1 W; |9 Q; W; y, N
6 a0 l$ W6 B! R) V8 kmysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit'; ) ?; m; V# E* q: ]! Q
1 r" B: l7 D& i- K4 M
2 E% ?3 I0 O! y9 G  t9 E$ U: e
$ c) q7 ?1 u# j' S1 N. o# g
shell> mysqladmin -u jeffrey password biscuit
$ R* f* i/ ~; \2 y4 d4 I9 ]: z注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应
2 C: R# \. Q$ @该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix
+ t3 C! Y4 o  l口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。 8 R* s& O9 `* y0 d& A' ?6 c4 _
3 `; v  y8 \2 h
Access denied错误的原因
& W2 g' V2 |, @当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面
7 }2 z4 ~+ X5 {8 F, t8 x7 n& R的表指出一些你能用来更正这个问题的动作: 5 h2 |( j3 ~/ @) x: J$ y

  b/ z5 b: d* m' |- r你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容
* ?; i, I3 \+ V3 M  M' ?& I吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初
$ `" [- @1 y7 i$ `3 _' P# h始权限: 5 T7 s* m. C6 _
shell> mysql -u root test ' h: r, B; u" N
" m6 a* I+ z6 q" ~
服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件
8 n/ |5 ~! Y# w7 s/ Z& i) ]“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安
4 Z7 z- m: r/ e$ u) J装根目录的路径。 1 Q% U+ E8 Y% b; j) ?% G) L+ v
# `# S8 j/ Y  N6 f# @6 g; }  V
在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
4 E3 V7 O( U* v% Q' L2 Oshell> mysql -u root mysql ) E# |& H2 y: H9 y

# i+ `- N. n. C1 [; ^- v: `5 ^1 U服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个
8 W, v6 y4 w) U7 `安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如
# V5 Y+ U) h6 C, j果你作为root尝试连接并且得到这个错误: 5 H% C. F, Y/ Q0 x3 K7 `% p

0 R; z; o: H' I  c8 H3 YAccess denied for user: '@unknown' to database mysql
% S+ P& x3 Y7 ?1 y# T( t6 W5 E- {) g
这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld 9 t% t+ |; T) A
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项
1 z- U$ @; p5 c" ]3 m重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机 9 C8 C( G9 ]" i# g) ^) I
增加一个条目。 ; @4 G8 ^- |, A" x$ Y$ p" e

1 H% ~6 z, Z0 N3 ?, o3 d如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以 ) Q2 ?9 [  N, j2 D  U% T
后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在
4 J' I! a: m8 w& y+ q% r  Y3 hGRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。   J  z9 o8 z2 f5 P+ C% q, v
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被
  v: N% ^2 y9 B1 H忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin 4 \5 i: c* H+ p! N1 A5 q
flush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被
* u8 y) u5 Y# ?+ u4 W9 Z重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗 5 n. n& u6 \4 t8 e
(flush)权限以后,因为服务器仍然不会知道你改变了口令!
' A8 }4 }/ H% m如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变 / J: i+ b; i% N) `( k% a1 `+ Z2 M  F
了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权   Y" m1 Y/ c- u  N5 C
限改变何时生效小节所述。
8 B% ]& f2 }" `为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变
! `) H: ]! s- LMySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的
" Z- x* Z3 }/ Z7 R2 q改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权 0 E0 Q8 U: ]2 g2 o
限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务 % I7 x$ {0 P' a% {: s
器开始使用授权表,而不用停掉并重启它。
, w- ?- q% ^% f' R6 U如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name
; U2 E# b# l/ v; |5 Adb_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用
% v$ l- P% e1 q5 amysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令 9 j, W5 P8 X+ _" i! C
之间没有空格;你也能使用--password=your_pass句法指定口令。)
, Y, t' p" j- ]; P如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句
' E* e0 ]( S6 `/ R% G7 T设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语
9 I7 y1 i+ h4 {句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。 . f/ e3 G, Q' J+ G% B
localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 2 G; X3 @) J9 t
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系
6 z& w; k3 q" i  C$ o统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT - _. t) g" L# T2 O$ V
-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确 6 B* c3 S1 z) u
地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你
' w: {5 Q; a5 h  A1 S. `# p# N必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一 0 L* u8 D* V3 x- o2 _: N: ?8 i6 V
台的主机上运行一个客户程序,这也是真的。)
7 d: W7 m& s* J; W当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个
4 {! Z: n. w# N+ ]: A; t( f& H- QAccess denied错误,你可能有与user桌有关的问题,通过执行mysql -u root
& m0 P/ y0 d/ i; w  _6 nmysql并且发出下面的SQL语句检查: 0 }1 j  Q2 U# e3 F( |" S) k/ }5 d- F
mysql> SELECT * FROM user;
; ~# ~( {, |; u( |9 b. i& L
+ o3 C3 d. a) H. z; L8 `2 u: ^0 I结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户
9 y8 D  C% ^  X" v4 q/ l名。
2 b, c9 e3 N2 M/ R- C3 H" |  q/ e/ X7 ^" X* I
Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图 4 U1 s5 B6 f& @* n
用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一
$ b2 P& [) ?- R. t4 d/ ^0 k' V个条目,正确地匹配在错误消息给出的主机名和用户名。 7 H0 `6 i9 y* g
如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列
' t& h4 j! N1 E+ c, M  j! t( O! p错误,那么在user表中没有匹配那台主机行: , b, E9 R$ ?/ x2 I( b
Host ... is not allowed to connect to this MySQL server
1 c5 }; \2 B) X8 h
+ Q2 @6 N% ]. q# o8 F  e! M你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试 ! Z4 b7 x! f, m
图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
# u& ?8 a! }/ m& j; s& A1 c: j你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为
8 s. g! n' n& OHost列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从
$ B8 C7 r; {, U$ @: y" q客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。( ( A# C7 F/ L3 a8 d% b
然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则, 4 C% E" k) V9 C% Z6 `
你将有一个不安全的系统。) & v+ l9 B& g) U* l& l0 Z! e3 c
! X  \4 W" O, }% T
如果mysql -u root test工作但是mysql -h your_hostname -u root test 2 J4 J5 k& [7 s# Y
导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的
" s. O* N, o9 Y1 `一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统
; h+ c: t+ M* q的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有 7 D! k- ]! k; H* q
一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet.
+ \7 e7 Y7 }7 p; ~7 [se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作
; }9 a5 Q# \1 K7 X" G$ d& @为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符 " h& N" N2 Z; ?: {9 R
如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)
1 t6 w' H0 z9 {1 d. r! g5 r- J& l如果mysql -u user_name test工作但是mysql -u user_name other_db_name 9 F* X: \1 I. P4 w/ w
不工作,对other_db_name,你在db表中没有没有一个条目列出。
4 B, ~" b8 p" G- @  ]! d2 k当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其   G7 r+ [5 c( q; P1 B
它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
3 Q  ?3 s* N9 F你没有把客户机器列在user表或db表中。 6 N7 [& h% i$ a& {5 `+ D- Z4 r
如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host
* P/ b% c, w9 i* p包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用
9 q4 e) Y1 V1 |! F$ eHost='%'和User='some user'插入一个新条目,认为这将允许你指定localhost 9 v7 Z% L! }- D
从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost' 9 _6 {& Z% e0 |, E1 l
和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从
$ Q  h2 S$ @& U: Jlocalhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和
( U+ u  b3 U# k$ wUser='some_user'的第2个条目,或删除Host='localhost'和User=''条目。 & a' V- b  b" C' q5 b; Q+ J/ T
如果你得到下列错误,你可以有一个与db或host表有关的问题:
, j$ X! O- a- ^0 E8 Q2 y2 T0 j- wAccess to database denied
5 T" t% ~, e" i" w( |, r- |- N! x4 N) H5 Y
如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多 : x9 }- [0 ^6 r9 ~# }. Y  p. B
个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ... : m8 C  i; K& v
INTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可
/ l& q# M2 o( `( k% r5 y3 C能启用file权限。
. [' |8 b: ^6 [2 r; S5 a4 Q. z
8 z( D4 f3 H5 g& r# _/ f- G记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果
; k" s; h2 Q( r* F; I) x当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数, 2 G. {+ I. D0 h4 \
检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围
; F, j( h' x5 F9 W% u% F% r$ P的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当 ) P& J5 |" b# w
你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选
: X7 x- V/ a  R( X( H项文件里指定一个旧的口令!见4.15.4 选项文件。 9 `' ]7 B- j2 r- T% S
如果任何其它事情失败,用调试选项(例如,--debug=d,general,query)
( f* `1 Z+ A( T7 D启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每 ) }9 Q' n0 _/ J$ K! t- s, }1 s
个命令的信息。见G.1 调试一个MySQL服务器。 + F9 p+ ]( s& Y4 |5 y
如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 % X- ~- k+ X4 |: w% |
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump
/ D2 Z8 J% i* @* fmysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一 ; q# P4 e6 `; o
些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。 # ^- P% Q, i' r" m2 |8 ^
怎样使MySQL安全以对抗解密高手
! R9 b* o" {" o) D2 e+ F( C' z当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文
, D2 w1 k7 e9 R' d* J: ]6 t# P* }在连接上传输。 & q% ~' n: x9 k9 N( t
' L( z* R7 f; {( w: Q* {$ v8 B
所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可
' H1 k" G  b6 k) m4 S/ _使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全
( p. R* j. u/ Z. n/ N2 {,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服 6 \. P/ Z; i1 x* Y
务器与一个MySQL客户之间得到一个加密的TCP/IP连接。 / a6 N' K) k5 U% }! U7 s1 F- w) S, `7 ]

! x* o2 N& \  B! H- i: H为了使一个MySQL系统安全,强烈要求你考虑下列建议: 0 l- _( `3 h* T  q/ N. b; V

7 [& ]1 B  O" N1 m  C- Y! n8 w对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简
2 Z4 p- c  P% ]$ d0 h3 V  W7 O单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器
8 d! p- H9 U) e( S* s3 ]) O应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通
( I( J  j8 p* e过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令,
" i6 i1 b2 p+ D( x; p% `象这样:
0 I; F* m+ a$ S( ]3 N5 e( cshell> mysql -u root mysql
5 r: W& a& w4 d$ L) v* Xmysql> UPDATE user SET Password=PASSWORD('new_password') % U) a0 n5 e+ G. P" y' i
WHERE user='root'; ' U- ?7 p+ z& J4 N
mysql> FLUSH PRIVILEGES; 9 s' v5 Q' e) M" \
) |; F9 W5 s+ z. I
不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行, . u, r- c0 x* Q9 y6 Z7 l2 v
你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户 . h: }/ v4 h, q7 V0 R  H9 Q
运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix - Q+ V3 u% [0 p" E
用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。 ) |# @9 Y9 \. X
通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行
* \% G4 m' e  k- ?+ W5 lMySQL。 8 \) L- ]" J" K9 x
如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本
5 Q& h: F0 E. g只能对root是可读的。
% R: t! K9 ?- r4 ^  ]; q$ x3 P检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用 + B. @5 x, J! l* P: K6 k
户。
- b( }; u5 v: P9 F; r$ z+ P不要把process权限给所有用户。mysqladmin processlist的输出显示出当
, L( b2 v, f8 Z) [6 g+ B- L& B前执行的查询正文,如果另外的用户发出一个UPDATE user SET password= 8 j3 W$ C. f6 y5 V) X8 j* \3 z
PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。
' x4 w8 ~% U; H7 G) \$ H' Z+ D* [mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用
9 Q: F2 j  x; t1 J" E7 G户能登录并检查,即使所有的正常连接在使用。
: R5 o* L& a! u6 P; `- L& p( H不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
+ Y! E2 M# }  b& g' Y7 {进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ...
% T4 k$ J# u: L' q# t4 |6 @INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 9 A  \, b/ E3 I5 Q+ h* S: h
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文
# V1 s6 R5 Y# b件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数
" O/ Y& ]% j( I" O5 Q! F据库表,然后它能用SELECT被读入。 ; X' r2 e: R, E' t9 v0 w
如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则 8 y& C' n$ \8 M
上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常
6 c! U0 x. e- j$ a/ B. U' R) i小心地使用包含通配符的主机名! * A$ x9 ]: B& B
下列mysqld选项影响安全: + R. l. r% _- P: l; e7 ]: p

) F4 ?  o3 T3 ^7 q--secure + g1 |8 H$ W: x9 x) [; p; R
由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来 ; G$ ]0 w+ J2 c3 j' i. `  q5 W
的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也 + e: ], H; k5 ~4 q
增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
, D% V! n% n, u; t7 z; `- t" i它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。   N6 s3 \, i- i& m
--skip-grant-tables
* U+ U. ~/ e, U5 ]这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数 0 a) ?6 R0 {7 S" a3 e
据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器
4 ?0 z! P, ^3 W- F0 |( W/ p/ L- c再次开始使用授权表。)
: }/ Q2 f' }# i--skip-name-resolve & X; g# R# h, e% l$ @+ U
主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。 # @2 P3 n/ y& s- L; {
--skip-networking 6 n8 d6 [1 X! _$ L* N( N& c
在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
. A4 Q( u7 ~% E: m7 R  v+ C行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不
; y3 j0 V5 z2 M# }2 _6 H. H支持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 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。; o1 Z$ \; n: d) L% j+ u& n. f: B# i
汗。。% n* W" n0 D( b' r% L) N
水平不够,消化不了。。
# M  \/ S' f  i) ]" p4 R不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

本版积分规则

关闭

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

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