下沙论坛

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

QQ登录

QQ登录

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

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。
: u, ~+ {# Z4 e! X4 e
& q5 V1 Z  Z& s+ J, g权限系统做什么
% _5 O; a: t5 k' t8 _* z7 _! U; pMySQL权限系统的主要功能是证实连接到一台给定主机的一个用户,
4 H/ E- o! v  r! A7 n/ E5 w并且赋予该用户在一个数据库上select、 insert、update和delete的 : Q0 w  B! B# ~+ `
权限。 6 j% j. U( u' \' O) m
4 K- \, U- `  @  m  u" m
附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如 # p  G; D  F; d
LOAD DATA INFILE进行授权及管理操作的能力。
0 c9 |7 Z( Q' d0 A0 @% v
" ~9 _# Z4 K5 @7 XMySQL 用户名和口令 " T2 d$ f! {# d$ |2 y
由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很 $ v& T' b; U7 a' t" W" v
多不同之处:
7 E; n/ a' r$ P8 B% A' c" v0 T7 S2 P4 N/ W9 I7 z" x
MySQL使用于认证目的的用户名,与Unix用户名(登录名字)或 ' u2 H, W6 F$ ]) d& p/ V
Windows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户
/ \- h7 N4 f( r9 S) K& C名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或- + Y1 W, k% _$ s
-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据
1 R8 Y- ?- q; w4 t库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名 - N# q! }/ R; }+ Z
字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。
4 J* C# d, z6 U" g5 V. @MySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。
; Z+ m$ a& y! m# x0 M# {MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使 - I4 c( c! K( [
用在那台机器上存取一个数据库的口令之间没有必要有关联。
' G" I. b: P8 {  c: [, f* }4 ?MySQL加密口令使用了一个Unix登录期间所用的不同算法。 5 _" \2 y, f, a

  E9 ^2 O4 |+ P- E- w1 Z与MySQL服务器连接
6 v( L3 L, P1 E# V6 U+ B当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定 # w1 G+ t& a8 g- v: h1 E
连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql
3 l. X0 K& [0 k, g9 p- i6 P- \4 N- g客户可以象这样启动(可选的参数被包括在“[”和“]”之间): . ?3 j7 e  i, Z

, A" z& {" x. s7 g5 Pshell> mysql [-h host_name][-u user_name][-pyour_pass ] 5 d* K- r3 V3 S
-h, -u和-p选项的另一种形式是--host=host_name、--user= : T- ]& o5 j: w: Z7 u* n8 I" g
user_name和--password=your_pass。注意在-p或--password=与跟随它 ) o: F  X. V: Y6 v' T8 t1 ~
后面的口令之间没有空格。
8 s" K7 W/ [+ }+ J+ ?, L" |" G  ~
5 Y( _* m3 P  S9 Y注意:在命令行上指定一个口令是不安全的!随后在你系统上的任 . \$ q/ n/ U' Q8 b. p" I/ Y. u
何用户可以通过打类似这样的命令发现你的口令:ps auxww。
7 H) Z3 i, A/ a+ o8 D+ S/ Q& n, \9 c5 Y3 D+ w' A$ [
对于命令行没有的联接参数,mysql使用缺省值:
6 P; w' `6 N, x; s  \& ~: q7 K* p3 c& Q7 z) |, L- a) ~. Z/ }7 c
缺省主机名是localhost。
% u0 J9 x$ b) }. Z. R  `+ F缺省用户名是你的Unix登录名。
4 K. o: F8 s- ]- U% q5 e3 y如果没有-p,则没有提供口令。
. w. y  z! |9 S' q. W5 R这样, 对一个Unix用户joe,下列命令是等价的: 9 A& i9 _# C$ X: P3 q/ s6 D) n0 k3 c

, x- B* v, V, h; r/ D% h! cshell>mysql -h localhost -u joe
% T1 A. o: \5 _* L2 tshell>mysql -h localhost
" ?2 w/ `4 h1 \! X  P, Y3 z# d( d: \shell>mysql -u joe ' x# Y2 K* B: w3 C8 h- b; `" c6 I
shell>mysql
7 @! `8 x9 I2 X7 d+ s( S
! l+ K$ Z/ F' z, G' |, o% E+ N其它MySQL客户程序有同样表现。 7 t/ P9 ^: I4 Y5 r+ a( w+ B

" w8 ?7 X# k! g- w( O在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺
8 Y7 u! \. j- {+ C( V  h/ T% |省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这 $ Q. s3 D" g* D, ?+ {9 ?( [+ N
可以有很多方法做到: ( A. X8 m& f9 o' A

& ^/ |  x* |& Y7 J% [% @2 q你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定 % N+ D) F- n7 J' d2 m+ z
连接参数。文件的相关小节看上去可能像这样:
8 _8 i' X7 F7 H" Z; z; i7 l- v[client] + t4 _1 o4 y! k, F- a3 o+ l
host=host_name
) P9 {0 r/ {8 w  {5 E! quser=user_name
: F% }8 L3 [9 y8 Z6 W8 vpassword=your_pass
/ f2 r( ~* \6 |4 n6 t! C$ K7 m9 ~' u) v  |$ P8 f. \2 h
你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL & ]% ^- R5 X0 u. W) u6 Q
用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是 & o# `9 M+ d0 b7 Q' W: G0 a
这不安全) 。
- ^! k; C9 a) Q) _3 }5 Q如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配
+ v9 K* s7 U4 G; d; u% W$ R置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量 6 t5 i4 ^2 q# Y7 B( k/ M3 i, I, U+ o
指定的值。
" l0 Y, B, v8 V$ A# u. n5 b7 ]2 M6 h  Y! R4 p: H! f
使你的口令安全 * }7 b* c3 G+ o& V1 v9 h2 h
以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。
' [7 P8 Z& r1 z6 t当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法
: ?: K# m9 t& h7 q5 h' ~的风险评估:
* f9 o4 Y, A+ e! {) p2 G4 C/ u: u0 {+ E6 u& _/ d/ d
使用一个在命令行上-pyour_pass或--password=your_pass的选项。
3 [) y  {. p0 s% m4 X  h这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见, 6 X  I( y0 ]. Q1 f
它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化   }" }9 ?1 S4 S- D- ~& r
顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可 , ^; _- t1 G' d4 X: Z, f
见的。)
& o5 R  A; f4 X使用一个-p或--password选项(没有指定your_pass值)。在这种情况 9 I9 w  S. s4 \3 V3 m+ S7 j) @
下,客户程序请求来自终端的口令: 8 n/ t  i4 h5 c" N. j2 P9 P
# H  e( w# S+ {. z( p
shell>mysql - u user_name - p * @' M- I. a$ d- L( ?5 X: `
Enter password: ******** & \! n! t4 i6 T- u, ]6 P
% B9 ?' M8 w' ]3 v
客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见
# x" C& ^% a4 F$ f: m它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你 * M/ ]  F. ]; P' O# v
的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程   G# q. ~, E+ B: `
序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就 ( f7 C. w3 n* j
没有从终端输入入口令的机会。
- {' v$ \" Z/ H& t0 G2 G& Y
8 \2 H4 p) r% n在一个配置文件中存储你的口令。例如,你可你的主目录的 , F6 [/ S  l2 ~& t- }1 u2 q0 ]( F
“.my.cnf”文件中的[client]节列出你的口令:
& M4 N3 V+ b2 [+ r1 I[client]
2 |2 L1 l5 u3 L  tpassword=your_pass
% o8 N0 j; f1 R6 g; i( D
  H. M$ c2 D2 u* d- E2 x如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或 + m8 c$ W3 o3 c2 }2 s/ `
可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。 3 J- Z9 Q, v, `1 i% U  l5 D
: y* q/ I, S5 N' u
你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极 ; L( P3 X3 V( ^9 \( Q# S" W3 n7 ~/ V) x
不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项;
$ z* A1 U: N! s6 h! D; \如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有 $ c2 \) a5 H( D3 W1 q$ c1 q) Q: m
这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智
/ `9 _( e- \3 P8 Y) q) a' l1 q的。
( h9 x/ p/ f4 t" q总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
- b& P' n. b/ h, G5 {# V2 Z.my.cnf”文件中指定口令。
1 t3 F5 w7 \( _
2 p4 @  y. o% [5 A/ d, c4 T: o5 f% {MySQL提供的权限
4 I3 t+ E# `1 C. f3 [" o权限信息用user、db、host、tables_priv和columns_priv表被存储 3 A3 }9 M- {- K- T6 _
在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限
; E( B; E0 G2 ^  w+ U修改何时生效所说的情况时,服务器读入这些数据库表内容。
+ U6 w( W& Q! i' R+ q3 Y% o7 o. [1 }" t& a% f& c
由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表
7 v! R* p0 W# X2 h列名称和每个权限有关的上下文: : A0 S0 W8 g! ~4 Q
权限 列 上下文 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 在服务器上的文件存取
- [; f) Z* u4 V8 }select、insert、update和delete权限允许你在一个数据库现有的 ) O* k) n( i" t
表上实施操作。 " z" g% v: u3 _2 P( S* p( Z2 Q

5 t0 ^& Q; U3 x' c; e/ sSELECT语句只有在他们真正从一个表中检索行是才需要select权限,
" Y, N; p3 D. H9 U3 F7 o你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存   y3 `, |! E1 O4 A
取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器:
: A' r' j7 r  v7 Z* J
4 A6 P; u* ~( c3 H" fmysql> SELECT 1+1; $ n3 V7 u! q, [0 z1 Y
mysql> SELECT PI()*2; 0 W6 v( B7 B1 v+ \

, I" P. G7 T8 \4 _0 E4 pindex权限允许你创建或抛弃(删除)索引。
- A. F: z8 ~7 \- [$ R6 U3 A4 o: i9 D, ~, W  s6 X5 l0 |: D4 f( U5 Y
alter权限允许你使用ALTER TABLE。 2 u. f# D# I) P6 U
% o5 q& D) [( P! S& X( ~  _) M! i; j
create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的 ( b& i) S+ w% l  \  p) _
数据库和表。 5 p8 H; z0 M/ W$ g0 B0 Z2 E

. ^. S; b+ G+ j3 S$ Z  r注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃
  P- Q( c6 ?( a- j0 M" O存储了MySQL存取权限的数据库! 6 c' Q! ~$ Y* V* u2 X

: M* ~3 l; s5 w/ egrant权限允许你把你自己拥有的那些权限授给其他的用户。 7 c* s8 t* R  o7 r0 A, a6 }
  A2 O* l5 k& F) [/ R/ T' m: [' j
file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句
' O9 Y+ J. M3 ]( ]$ `0 z/ |8 m读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务
& i" l; H6 K9 G7 s5 s6 g2 A- i1 q器能读或写的任何文件。
" _% T! f# F) N6 E# E  h. B& O/ \: a* S3 u  l1 [- ]
其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示 - D& p4 \. I4 l/ N8 g4 a
mysqladmin支配每个管理性权限允许你执行的命令:
- ]1 }* q# g# C* v! w: \: E优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill
) m. }9 V. {. \+ |; J5 L( Breload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开 - ~- G. W/ k2 q
和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-* 7 Z) Z1 |5 J% X7 Z0 d; D* I
命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更
$ P# u6 w2 q9 I& `& G, j: Y5 w好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的 $ @9 P- {5 I) x5 q% f
选择。
% D) _9 u9 K$ Q( _/ X( o
, @$ e7 A) I! G: W( wshutdown命令关掉服务器。
% u# O, u( B* R' m
+ d3 o. p: ]6 [, `processlist命令显示在服务器内执行的线程的信息。kill命令杀死服
! Y0 ]) K9 o3 A$ {! v9 v. p务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来 3 q7 T3 }. Z  g; a9 W% b
显示或杀死其他用户启动的线程。
# U( X! h( u- Q* k( ]# }& f: }3 r& e: t: I* F
总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你 4 {# ?' k! m: _9 Q! s' L" {5 u
应该在授予某个权限时试验特定的警告:
; k# J8 C9 Z$ k1 t3 C) V0 _8 E, o3 n
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并
4 C( b; q$ K5 H) H0 `: c" [有grant权限的用户可以合并权限。
1 m, A4 X( m4 Y3 [! Z% Kalter权限可以用于通过重新命名表来推翻权限系统。 3 F5 a% V, m. D( T7 H" R
file权限可以被滥用在服务器上读取任何世界可读(world-readable, * C. P2 c7 t2 Q
即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。 # F& d; t+ i. a6 q+ x
shutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。
" |' b; M  h( y' |2 Jprecess权限能被用来察看当前执行的查询的普通文本,包括设定或改 ! b$ [+ ?/ r; c9 {6 f- n
变口令查询。 7 N7 D5 [% O7 E0 \1 n, a% S
在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口 $ G" |) H4 \; D' c
令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够
5 m! O$ z' R  Y8 [3 F的权限,同一个用户能用不同的一个代替一个口令。)
; [" V9 l. m- i有一些事情你不能用MySQL权限系统做到:
9 j9 L# h/ J! T7 N/ b; V$ |8 e
( v3 U0 Q- ^# E  D你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹 $ i3 _. e; C9 c7 c5 E1 q" [8 I
配一个用户并且然后拒绝连接。 4 t. G; u' B- M* L
你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建
' Q. J& F5 e9 i1 t或抛弃数据库本身。 4 G8 `, Z& k* r# X/ V
权限系统工作原理
; m  U9 b5 k0 R3 }0 E3 ]MySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。
2 ~- y+ H& S4 V% T5 N, z当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用
2 O2 C$ {. ?  W4 A" ?户名来决定,系统根据你的身份和你想做什么来授予权限。
- Z: S2 L0 `( c( @- c: w$ p" l- y: ]% A) k' f) q4 s2 m
MySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假 3 t, z6 t6 |; c8 y
定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov
  |  n6 R5 I; {: ~+ G: Q" U连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区 0 W# o# |+ o6 L" `
分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov
' i9 z, o0 j/ z连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限
, P' m3 {. c+ L! t0 ~% F' h4 E# E集。 8 H2 ?7 t+ _7 r0 T/ F; H
. F- b2 b) F* V' E
MySQL存取控制包含2个阶段: 1 ]  y' n) F0 A

& Q1 z4 A& o$ {: j阶段1:服务器检查你是否允许连接。 % }9 Q& Y# A' V$ D3 w; K' z
阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够 8 h( m2 P6 D$ P: h! d: n
的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛 % [: D6 H5 m  u- c
弃一个表,服务器确定你对表有select权限或对数据库有drop权限。
5 H& l( b" F; @9 m4 [服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host
- C: d1 h1 A& s- d9 U表,在这些授权表中字段如下:
4 U* @* ^0 f' P# q表名称 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
! G9 e2 `* W" R3 t2 }( B/ M+ k, b对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
( i3 G* y, I6 v' D: @参考tables_priv和columns_priv表。这些表的 0 X7 r2 P9 S5 I1 F9 X
字段如下:
! Q' a- _* @6 o) k: Q$ m2 S表名称 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 ' N' Z7 v7 b2 }' Z3 z
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
7 d% s; J6 K; ?9 F$ l参考tables_priv和columns_priv表。这些表的字段如下:
" u/ ~. c& w% ?- C) M字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
( M9 O, _5 P+ t在user、db和host表中, 2 _, T% h# X) W2 |2 Y9 ~
所有权限字段被声明为ENUM('N','Y')--每一个都可有值
1 K4 Q4 s4 Y( X# ~: j'N'或'Y',并且缺省值是'N'.
5 O0 H2 f0 t; f在tables_priv和columns_priv表中,权
; J0 G, V- r& c限字段被声明为SET字段: $ k, W' _4 k+ M) a( }' s5 q! |
表名 字段名 可能的集合成员 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' 5 `7 t) E: z0 F0 |' y( Q4 g8 S' o
每个授权表包含范围字段和权限字段。 8 b. s) T0 e  @2 l) X
3 B1 k9 X' k8 U4 B1 D- z
范围字段决定表中每个条目的范围,即,条目适用的上下文。例如, 4 r) S0 I: }! F
一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于 1 P- u) x8 ?8 G# n
证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条
* P& L- {! E* V- G; |( ^+ j* V目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'
0 l/ J/ @0 }8 }2 A将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。
: g! z! b- V" ]! F% U; h8 ^tables_priv和columns_priv表包含范围字段,指出每个条目适用的表或
" `9 P* d0 g  r2 Y表/列的组合。
! }/ x" G0 L% q& m
2 u' q" q! Q) t6 O对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
# @2 f+ d, {& m# x5 D5 wDb和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以
1 @! {+ [8 M* L) x* @后版本是忽略大小写的。
4 P/ v' F  A5 _% x% n% r; x. Z* l+ {) \7 g  ^, }" p
权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务
8 ?. o9 g% z' @( ^) x器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规 , V3 t! P5 K& I) m! ~7 u
则在6.8 存取控制, 阶段2:请求证实描述。 $ W# h0 `2 w. S, i3 u; N

# _, s, x  w! o! g; C. a0 e2 R范围字段是字符串,如下所述;每个字段的缺省值是空字符串:
. C1 C: z1 E0 ^! W" P字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
/ ^" I. a1 h! L5 ?在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一
; d4 {- c" {/ F个都可有值'N'或'Y',并且缺省值是'N'.
3 u+ ]+ u; O! N, ?# E
+ Y. L2 |& o9 w' ]% X在tables_priv和columns_priv表中,权限字段被声明为SET字段: - X1 p3 F4 u, A" ?2 v; ~4 M" K7 I  Y
表名 字段名 可能的集合成员 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'
: K( z, \1 O9 O' D5 G简单地说,服务器使用这样的授权表: ( Q) X" F5 {3 p& X! O
& o- ^1 X1 ?. @$ V# V: a, N# A
user表范围字段决定是否允许或拒绝到来的连接。对于允许的连接,
; K/ _+ v5 _  y! b" U# t3 _  q权限字段指出用户的全局(超级用户)权限。
" R2 d, y: @# e$ k7 \db和host表一起使用:
8 K9 n8 I; A2 i" ?db表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定 6 p' {* Q* |1 v+ d- F
允许哪个操作。 0 |& Y: L) c, T; ^4 G
当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩
9 P- \2 Z0 W6 }/ L+ S" @! ^8 a展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个
# F: P% w3 c) A/ [1 [数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移 7 a4 o+ c: L' n. T7 O, `) @
入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。 ! z& Z9 T! N- G5 t  y% Y& d: L
tables_priv和columns_priv表类似于db表,但是更精致:他们在表
$ j2 Y1 g( l3 H7 J和列级应用而非在数据库级。
3 _* W  i" r9 k- E注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是 ( A; S3 b2 d* q3 d! B2 v* _
因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由
* G: Y8 {% L0 C/ e3 y$ s+ ~6 I在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是 9 ?6 a7 T; u  |% M: ~* Q
否执行一个管理操作。
9 e, W  A0 Z- b% W  `1 b7 u# A$ L3 F/ D
file权限也仅在user表中指定。它不是管理性权限,但你读或谢在服
- s2 `; K# \4 f) d/ F务器主机上的文件的的能力独立于你正在存取的数据库。
, z( Q$ e' U* S
0 {5 s! m3 U- Q: ^1 P1 Q当mysqld服务器启动时,读取一次授权表内容。 3 }6 W$ Z' z4 i, I- _% F
5 X- p& \, U" K3 S$ p2 B! d( [8 Y7 D
当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一 1 D) n* E/ W" g6 A$ S
个好主意。
/ E8 ^* I2 [% ~( }0 Q7 H# ^# k; E8 A. S/ h
一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给
8 ~& a) A' R/ U4 S& p) uMySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意: 0 r+ q( o9 e$ p7 O
mysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。 ) o; Z) W. f/ S) M$ l/ C+ O+ ]

- m7 |( e& c2 ]# l8 P; A4 }存取控制, 阶段1:连接证实
0 _3 K5 C, i( u, i" o- S  Q) T' |当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能 ) ?& ?  d* u; D% ~
通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全 . H9 O! f4 S: s% N- W" k* U+ ^8 [
具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。 ) E; v5 N3 u3 o5 _
) j5 t4 R; f0 Z8 C& S5 q$ j4 i
你的身份基于2个信息: " D" y2 l! w& Q5 ]3 S3 l/ i, d' `

% j4 v3 r) W9 Q" X0 z; ^* V你从那个主机连接
* p( o* `+ A4 N你的MySQL用户名
  N- a2 V/ k% Z身份检查使用3个user表(Host, User和Password)范围字段执行。服   o% O' u: L6 m$ [
务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的
/ u3 W6 `3 A6 S3 D7 O. X$ b5 W& x! S3 Q口令时才接受连接。 - R8 N# t* b! \' t
3 C2 x* j, f  [4 M$ a: N' N% `
在user表范围字段可以如下被指定:
: f# k0 D4 Q# T# G4 J: t+ k* T9 M( I1 m3 i9 @
一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。 * b6 M8 R4 b3 ]0 Y* q7 J
你可以在Host字段里使用通配符字符“%”和“_”。 . |) p, M/ [. Q0 T, r. l5 u# N
一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些
' \& Z' U- |4 ^' T3 q0 c9 Z" P值匹配能创建一个连接到你的服务器的任何主机! . Q- t; a+ U. f
通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何 9 y% {2 b  j) G# Q3 L) K5 y
名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为   d4 Z9 z) t" P; Q
是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空
! X9 q; }1 x; z/ n2 E* C白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。 , p1 n* k! ^7 y6 ~" M) p7 B+ D3 q
Password字段可以是空白的。这不意味着匹配任何口令,它意味着用户
. u$ L" D; m) P2 {: [9 C1 P必须不指定一个口令进行连接。
0 g8 D3 e, R; W7 J$ Y非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本 + F  t/ r& q+ m8 i1 v
格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用 5 D: X2 u  [! ]  F! O: |4 X
PASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他 4 X% v" A1 k# q% M, J9 U6 L
们匹配,口令是正确的。
1 s1 }9 `. E3 D  n
0 w0 O) B  m# p) v下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来 # G* N7 O% A; b$ J( U, N
的连接: & \6 [/ B& X' O2 S+ l

$ r9 ]/ c! N& Z( ^/ t* z+ THost 值 User 值 被条目匹配的连接 ; K# X% \! m2 H2 L6 k/ n* n  C
'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接
  i& \: ]( B" q! c5 G! I1 m8 a, ['thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接
4 X9 G  R8 J# k'%' 'fred' fred, 从任何主机连接
. r% K3 r5 h6 @! Y( B% q+ t$ \, I'%' '' 任何用户, 从任何主机连接 6 D( ]( f5 F( x) u
'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
; [- L, R  E. C% M* K! j'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许 ! e' C$ R2 A# q6 i( L
无用) 8 e5 R. m  s, Y  O8 O1 b$ P5 |  A! m, c
'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主
; V& K( p6 C& O7 H机连接
4 w$ G. K; |+ ^+ s  ]% L: y7 N$ ?'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连
. O' D  y5 ^  t7 ?3 H, J& D  x6 E7 r2 `/ k7 {5 y0 y

0 e+ a3 y# S$ Y5 H既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子
1 m$ y9 n. o8 i% i. `8 D; h1 i网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机 9 q: P. b# n/ z! t; o% x% q# k0 x
为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以
# I. E, a5 Y. m% D; W( h数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的
3 {8 J  i& a6 E4 F& H& M主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配 ) Y, M, N. m  Y
符值。 : H6 }# k! J& D+ F. j6 a

. ]8 N. x0 @2 e一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由 3 u' s& T+ s0 D$ l
fred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配,
) s, \, u' `" C( j: h# x服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来
2 H+ _: P. A7 P8 z+ P5 j解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一 " z6 @  W$ |. P  F
个匹配的条目被使用。
+ l; }/ t( p9 p5 \0 R' j7 Y* _/ T7 ~0 _
9 y; W. S" _. Q# q& Suser表排序工作如下,假定user表看起来像这样: 7 S* \8 [% P$ d9 h" E0 X- l
. ~* I/ N5 [0 s7 S2 v
- g9 n" s4 u1 t, m9 }" Y! [" c
+-----------+----------+-
! b5 |: \5 v1 z1 o% ^) j& H8 m│ Host │ User │ ... " P# X% C9 L5 s! k4 z2 x
+-----------+----------+- ) a9 G: A8 o9 X# }& O1 T
│ % │ root │ ... 7 r0 a5 X) O2 {$ e1 |
│ % │ jeffrey │ ... + Z9 l" H: n; ~4 v. }1 T. a
│ localhost │ root │ ... - e; Y# s' Z8 _
│ localhost │ │ ...
- O8 r; e6 ]) C. h# @" \1 j, D+-----------+----------+- 7 V& \+ c+ X) q5 [
3 q9 D* A# B& `) i; J+ s. t" ?- f# E; E
当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在 ! O0 ^( b; f! d
Host列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以
2 Q7 W" O9 ~5 w1 L最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且 ! E9 A3 z! b& k* P9 }
是最不特定的)。最终排序的user表看起来像这样:
& x) J& v4 x" h5 C
* H; a: Q8 S+ [; D$ l, k* u  U- ~6 l, P0 y( i2 ]  v
+-----------+----------+-
  T) y; c! `. [0 Z  N% R6 n│ Host │ User │ ...
, Y  E) X# B: q$ L# Q, U+-----------+----------+-
# B3 C3 P1 {' j│ localhost │ root │ ...
: Y) @- b: ?  A│ localhost │ │ ...   k1 f: c" _8 m6 g7 N8 M
│ % │ jeffrey │ ...
  X6 I- l) {- C6 V3 z2 |$ }- B' \0 H│ % │ root │ ... ; o3 l+ r7 Z1 S, N9 ?$ V
+-----------+----------+- ( Y" O  b7 x5 M. J

1 O3 o3 g4 G! M* e" R当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹 $ @! F( q$ F' y  y) W
配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目
7 A1 d5 C3 R7 v8 Y1 v/ [首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/ ! n( ^% ~7 x2 P+ @
'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。) 3 e3 c: y0 T/ [& E2 A
" |) E( o3 l9 u
这是另外一个例子。假定user桌子看起来像这样: + W, n- I2 p, u1 @
: g8 l% l3 _" T0 q
* \3 h3 p1 j) Q, i- X$ p& y/ F) d) w
+----------------+----------+-
0 H! g) z' Y6 b4 {; [5 @│ Host │ User │ ...
7 U4 [. T) r9 `" K2 i! z+----------------+----------+- , R) o, W. g, ?  y
│ % │ jeffrey │ ... ; c5 ~& Y/ _8 _  O. H  f5 K( b" i. f
│ thomas.loc.gov │ │ ...
  f+ w8 s. r4 _* @- |+----------------+----------+- / k& h' C, c. z
/ h! |1 r# I/ b! ^1 g7 f5 F2 m
排序后的表看起来像这样:
2 |7 B* B. J1 p: X8 e- D2 L* {- t. P$ L4 c- G# X2 E
) g; V' j: x2 y( A" K
+----------------+----------+- 1 P" @1 w) a8 J  k" a/ v3 J/ T2 q
│ Host │ User │ ...
% h: [$ z7 V" q% a+----------------+----------+- 6 U1 n$ P8 }/ M0 g1 s" t0 N
│ thomas.loc.gov │ │ ...
) X& ~0 Q# ?+ o2 u6 m3 j│ % │ jeffrey │ ... - l: D- X' A4 V# R" P7 w
+----------------+----------+- 3 ^' R  P! @4 S# E! N

8 E* {  X$ B8 v9 R一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由
3 g4 ?, ~/ a: W1 Rjeffrey从whitehouse.gov的连接被第二个匹配。
( t+ E3 F0 V( i, I$ p9 {
6 ?0 V, a6 j+ a/ _! f$ l普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找
. ]! R- F3 R) Z! B- e. @/ Q% j匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。 - q  @2 ]5 }; x( W& v4 Q4 [
先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没 5 l5 }( W- s: z) R& e
被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹
5 r7 j  G8 I+ a配!
7 J* |2 N" K5 C9 p  z
5 h! T( k9 w' J# I  ^9 E0 y! z如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个
2 J) Y* E: o- k1 k* V匹配在哪儿进行。
) c; g6 U, N/ {0 v* e" k
# `$ r; [" r, e7 y9 Q% Z2 m! w: E存取控制,阶段2:请求证实
. f* h9 B! l) E9 N: J1 ^3 V一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个 + z9 g' o; w, Y! O3 ~- ~
请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作
+ E: u  l) F0 U2 w6 h9 E2 R; L3 v类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子
- ^# F' {% g) E9 R) u6 Fuser、db、host、tables_priv或columns_priv表的任何一个。授权表用
( W- e( }0 C/ W9 W" U; R4 B; I% s$ {GRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参 7 f: |" d8 E" I6 Y
考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。)
) A. S5 _1 A# U. B& c' E) K! L, C$ h) U
user表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库
# y: k# b) [! @' \+ Y是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器
) v+ W( G4 q: G# T! V0 U主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
& l8 S4 ^& X$ n- ], Fuser表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户, - H% f7 H& @6 c# S, u! {
你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权, 1 Y+ j2 W- `- Z# [  K
使用db和host表。 , l; J+ x. c; a  X) {

! _8 @6 x! n1 h, l0 tdb和host表授予数据库特定的权限。在范围字段的值可以如下被指定: & x( T  s# n$ `' F& l
8 \' r% ]9 {( g# t+ m" K- f
通配符字符“%”和“_”可被用于两个表的Host和Db字段。
1 c% ^0 r* a5 a在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 - {. W; o3 g( V7 L6 |# K0 Z( E
着“对进一步的信息咨询host表”。
* w: u7 Z4 ]& \6 {在host表的一个'%'或空白Host值意味着“任何主机”。
9 |: ^. j6 U; j6 B3 e8 I5 w& z在两个表中的一个'%'或空白Db值意味着“任何数据库”。
: _( |$ O# m" W在两个表中的一个空白User值匹配匿名用户。 1 z3 q8 t2 C5 |& c7 l5 j; }
db和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host
. o0 a' P+ q% W9 Q- a. [- p、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于 6 ]! D1 I: V7 [2 y  r( V
user表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找
+ b& q% G/ V$ M- N  ?2 U匹配入条目时,它使用它找到的第一个匹配。
1 l9 a" T# [# w5 z# `7 f% u7 F3 @6 {
( D( E3 v* K# b% ~( {' O, x/ I5 etables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可 3 M. v3 e: f) S3 D. R
以如下被指定: 7 e3 y6 Z. X- y0 Z7 M- j( F

: o, b+ N* l$ E通配符“%”和“_”可用在使用在两个表的Host字段。
$ ?" G# j+ [" B: I: [! b$ z, S在两个表中的一个'%'或空白Host意味着“任何主机”。
: P& x# l" q! M  \8 Q( X. U在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。 8 X3 X8 C" Z0 k( S  O. s
tables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于 7 y8 U6 ]# _! a' R; l
db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。
+ Z( s$ Q: B( h! x+ E: Y
2 ]0 g0 r# _3 H9 m* {; A2 D+ }请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这 + M3 h3 _0 h, [8 q
里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是 + `( w9 u" J1 {/ X5 v5 Z4 g) [5 r
不同于使解释更简单。)
4 j0 J! ~* W! Y+ T$ c; j! ?+ d; S/ ?1 P9 f5 U9 h3 j7 H
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是
1 n) H5 a/ X) x) S4 c* j唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。 + e1 |& n/ m* }( [( g; h
例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授   l2 ~  s1 |% k9 G+ v, ?- }& s- g
予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含
" C1 r/ Q% G6 \2 p9 yShutdown_priv行列,没有这样做的必要。)
( n: |) A: \3 j
  C& i* K1 N& q. v0 B对数据库有关的请求(insert、update等等),服务器首先通过查找user表
3 k" E2 B- _; J& ?' ]% Y; G条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授
! e# t4 o* R: t' A- F3 g权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用 6 K; T6 _2 {1 {) M' B
户数据库权限:
3 r& ?" j$ R, |1 K7 U0 F3 Y6 r* `
服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连
4 \& {4 o4 B. J接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有
! Q" E# ?4 b5 C1 O+ DHost和User的条目,存取被拒绝。
9 `1 l; k8 u, c6 }7 t, D# F6 g# N如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用
/ B6 p8 b8 O0 h户的数据库特定的权限。
) _5 }6 Y3 c# K3 |如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被
7 b- p! V: |- ^; e4 U' h允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和 * Y) H" I! {8 c* [4 p9 f6 E3 V
Db字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数
/ m( v! A: q3 E6 a) U2 P  N: T7 `0 K据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交
% p# i, k9 B4 d% f2 G1 M集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host
7 B/ i7 h: s7 G; X表条目按一个主机一个主机为基础地有选择地限制它们。) + F8 W2 `2 c& N
在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
% X, }9 {, `$ B# T由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 3 ]# G& `; e: m) {0 @* [2 J
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到
/ I5 K7 {; m6 ?! a用户权限中。基于此结果允许或拒绝存取。
7 }& w2 X: W, c8 e- w5 w8 T7 ~0 N" r
用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结: 6 \+ W. F: R; g  k6 u7 i) @0 `

# A0 y8 r4 y$ U9 |5 N9 w2 ?global privileges 6 o+ |+ y, ^, K: d
OR (database privileges AND host privileges)
7 u" c3 R5 z% Q2 y" M2 E1 `OR table privileges
, ~5 G  w, D# d& V. TOR column privileges # t) l7 W, t, w
* o: m6 u6 F3 O! A6 ]3 k* x
它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不
* O& P& T3 H# ?5 H4 R' g) Y够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能
! P4 d6 I2 a9 s- t" f: R# i要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都
3 [7 H; C0 I7 F* e6 T3 F要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 - x. i9 U5 _) X. y; s3 b
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把
( X/ X. o+ {; ?, ^  B两个表区别开来;两个条目授予的权限必须组合起来。 0 `1 `: c6 \/ h& O
5 o  w) d+ r- X$ ?
host表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本
# @" }9 P/ D* d" ~% @0 `0 p% i( M* t地的网络上所有的机器的表,这些被授予所有的权限。
2 n1 d) n1 x: _. d! E+ A1 }7 Z9 ^; o3 B/ u. J
你也可以使用host表指定不安全的主机。假定你有一台机器public.your.
: s- y# p) y4 L1 k- ?# ^' adomain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允 * z+ ]7 k+ o0 A7 H3 ^
许除了那台机器外的网络上所有主机的存取: 4 _& C5 h7 A1 L0 d
3 x$ ]5 C* u. x  Z  G

; C  K4 U( Y0 r! V+--------------------+----+- ! ~; V4 ]" x, c% s  z
│ Host │ Db │ ...
& S7 [5 p+ F' V) C8 N+--------------------+----+-
9 H0 Z8 C, J3 a2 Y" d" f/ o│ public.your.domain │ % │ ... (所有权限设为 'N') , P: D& m2 t* Q5 Q/ E" I" @9 p
│ %.your.domain │ % │ ... (所有权限设为 'Y')
- I* _% ]6 t0 q4 V8 A5 F0 m+--------------------+----+- 2 v- g- \9 _. m# j) k! a

, z/ N5 f4 w+ o: d当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保 9 A  n* R$ S0 ~1 E" P& i
你的存取权限实际上以你认为的方式被设置。
: y# C; o% M' X5 p/ @/ j( i
8 K; B; N$ @8 R权限更改何时生效
' @9 ^6 B- x  c) l" l2 X当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。
2 k3 i6 Z8 n6 E% i9 Y" z9 G; v! M
用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。 2 ]4 G2 w: p+ ^8 \! k+ V

- R& D5 t% ]* Q& B如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH 7 \6 y% g% B# m  R/ n! |$ F4 o
PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否 2 v3 S# K: m& g4 ~0 S
则你的改变将不生效,除非你重启服务器。
1 X& M* A5 X0 \9 k! X! a8 L' z9 I$ a
当服务器注意到授权表被改变了时,现存的客户连接有如下影响: 1 N! ]' ]( |2 {7 s

6 o+ {# ~. ]$ l: h4 w4 E3 b+ z表和列权限在客户的下一次请求时生效。
+ D( q& H. T$ Y3 x$ F' H8 s# j数据库权限改变在下一个USE db_name命令生效。
* h7 d+ Q* Z2 f0 h; H) l全局权限的改变和口令改变在下一次客户连接时生效。
+ F5 G: `8 @) G! T( @- U  \' P( t# p. ]. q0 G) U( h2 r: ~
建立初始的MySQL权限
4 a' o: H- _7 n9 ^% x0 o在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。
: M1 [+ d/ x: ^scripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列
3 z: i9 X* t; @% _权限集合: , I5 Q2 K6 @; G5 J. ^1 Y7 q

( J2 k" h! F) j) t% Q0 FMySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主 ! x! N1 j! ~) j
机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行
- t8 [- V! r# _& ]连接并且被授予所有权限。 . V1 H1 r; S& m% v
一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库
: I7 b9 t( y7 C; ^做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视 ; F  g, r( {% e8 G" P3 U& O% y
为匿名用户。
- I& a# R4 _2 M! s# E9 \其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或
- b6 h2 @2 u) ?# Qmysqladmin processlist。
4 r) q9 X1 [2 A' F* |注意:对Win32的初始权限是不同的。 , |# c9 S) q' ^3 P6 S" D9 i* c4 ~

/ B  Z* ?& n" A# y既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户 " Q" q3 \  n8 V4 A
指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令): ) T4 q! m) o  C+ L) D: b" E2 \
, m/ j/ q9 d+ Q* P2 C; f
shell> mysql -u root mysql ! |  g+ X0 K: q
mysql> UPDATE user SET Password=PASSWORD('new_password')
" W. G  V" R* X7 V9 @  Y+ sWHERE user='root';
( Z" ]3 ?2 n5 @/ i6 Umysql> FLUSH PRIVILEGES; % V5 O5 k; n& T$ d

6 c- ?: B) a" C' e* m6 O1 T: s9 A在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句: ) f7 {: Z% m& w' H5 n  M

4 y7 B8 _8 ^2 A! D: [shell> mysql -u root mysql # S1 c$ b7 U! Y% A( o) u; y: I
mysql> SET PASSWORD FOR root=PASSWORD('new_password');
: }- r  ?& t: ], n) R
  _4 e6 m8 b4 g& r设置口令的另一种方法是使用mysqladmin命令: $ F' V8 ]$ x! `0 `

! u; t; i5 x/ sshell> mysqladmin -u root password new_password
7 x. H7 e4 t1 T+ c/ }: q+ s6 w; j8 y# I6 Z" B8 h3 w
注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器
+ |  T0 W) U+ w% R& t  e再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。 ( f) {& x1 N  V# t6 x" o

/ z, T6 F" h* p5 r5 z一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个 ; m/ m. J+ T5 t( O5 X6 J
口令。 ! i. M4 L0 }$ W7 l# q% y

% K" ~, `6 y4 r' b. Z你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它 * s9 p7 W! Z3 I
或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。 6 F2 F; Y" Q3 S0 {

$ b7 v; N# D% u7 W看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它 ! o* y2 {  }+ s# f
作为一个研究如何增加其他用户的基础。
# i" C& {7 j. B) M8 H! p
& R. J( B- z7 v5 N) x) g0 c& j" m如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db
. C, S8 x, A7 H" X$ B/ l- u9 G之前,你可以修改它。 ! u: \, c# _: k, ?) t. u6 {

2 @0 n& Q* ]* j. \! b0 {" O为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”, ( C' k3 ^; C% E
“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,
) P) _2 A: [: C, E( z当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能
. ]5 s: h9 _# G% n- R在首先编辑它拥有你想要的权限之后。 : v% O+ |- w( N# g0 F' F

4 k) V' k7 W0 h+ f  ?注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果 ; V2 ^" R. {8 t, _
你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。 6 V+ l" B( y5 {" [/ v& [/ Z

2 z( T5 Z  e' ~8 \: [4 N* V向MySQL增加新用户权限 " }, c3 ?* M9 R+ z9 a4 k
你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授
* S, Z& u( Z. g/ ?权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。 7 z8 `5 V2 z' p( i: m% U+ B4 V( z

4 o' T& l5 o8 e7 P2 o下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前
% s; y( U3 D# W$ ?/ G的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台 ) y) d5 A1 C7 z: O' s
机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有 ; q$ a& V) p: u9 p. l3 {
insert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下 $ o8 J( Q1 b- }
的mysql命令指定它。 ) T0 |" O  ]" u! s" q& q/ t
4 }" A9 V" q  L2 X% b, X
你可以通过发出GRANT语句增加新用户: $ l- Y0 y! h( Q4 `2 h% |
0 n3 l. G- ^4 z+ C; ]/ u
shell> mysql --user=root mysql
% E; m$ B8 i, F7 ^" N& s* N7 gmysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost 8 t8 j' o/ w5 X3 X
IDENTIFIED BY 'something' WITH GRANT OPTION;
/ h2 f* Z" x  B- n5 umysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
9 b9 g2 |7 X- @5 P" i' fIDENTIFIED BY 'something' WITH GRANT OPTION;
- N2 k# G4 J# q# W# tmysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost;
/ `6 r" G: Z# Kmysql> GRANT USAGE ON *.* TO dummy@localhost;
: @' Z- x1 f8 [3 h8 J
5 t$ \+ `+ L6 r: Y6 U这些GRANT语句安装3个新用户:
: U/ B6 f% ?/ D( W4 q8 r: z% d. _( y" J8 k: Y' r( C5 ^5 S
monty 0 ]( K1 E6 c6 [! ~
可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个 ' n+ C( f) @* y' `$ `8 p# L
口令('something'做这个。注意,我们必须对monty@localhost和monty@"%"
5 c% b; `$ P( C) Y- r发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
6 z: B( W/ D. X6 }; u3 J$ i在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为
* X0 E  d3 v) p* J3 [它有更特定的Host字段值,所以以user表排列顺序看更早到来。
' e1 q( f# z- nadmin
; H, t( L- s6 `* s/ \可以从localhost没有一个口令进行连接并且被授予reload和process管理
/ _3 d) u+ Q/ ], P5 S权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和 9 i$ @4 r' Q1 A) c" n
mysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有
$ X6 z% U: O' z+ {. w5 g6 {& H/ r关的权限。他们能在以后通过发出另一个GRANT语句授权。 1 A/ A$ o, u7 R/ O0 k1 y# x, G
dummy 2 t- f# e1 y% q" T5 v
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设
' g1 ]: V9 N/ {# r, h置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以
& @: A  B; ?! l2 h8 J3 o! b后授予数据库相关的权限。
1 h& [7 o( b& |: ]" W你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服
, ^( R2 y% ~# Y务器再次装入授权表:
! E& V- y- E' G: K: o# s* i! l0 ?: _: R8 N7 p7 e* h/ t9 W% ]
shell> mysql --user=root mysql
2 T6 `9 Q  Y# Smysql> INSERT INTO user VALUES('localhost','monty',PASSWORD
7 W7 X" C) {9 K4 F: i6 V- ?- H('something'),
3 i' q* N$ w: `; ^% z8 k3 g'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', # b9 J9 ^5 b+ e9 u, h* w
'Y','Y')
4 H; w' m$ w) J4 u1 e, Gmysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'), ( |6 X. O! b* M8 r; Y( u  a
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', % \9 k) U+ c2 V) z/ y5 ]
'Y')   G8 _8 d, D5 x5 _
mysql> INSERT INTO user SET Host='localhost',User='admin', / U7 \5 d3 J6 n" A
Reload_priv='Y', Process_priv='Y';   z" z6 Y3 M  P  [$ }2 H
mysql> INSERT INTO user (Host,User,Password) ) u/ V$ ^3 ^1 r7 Z/ ]
VALUES('localhost','dummy','');
* [. h& ~5 \# B, j& D* [' cmysql> FLUSH PRIVILEGES;
/ X, K: r' O( ~' [! N- ^# |, M
/ L( C" o- n+ e, c取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在 % R; n6 x: Y, ]* s9 D* ?  \
3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版 3 a( `( y& u; G% a0 F1 j' _4 b- D& z
本具有的更加可读的INSERT扩充的语法。 0 I; L$ m0 q" m7 l. s. F) T

/ _) f3 E0 P1 B" o' r注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为 ! n( |, k% K6 r4 R
'Y'。不需要db或host表的条目。
6 U  ]2 f/ T  |: g3 l  \# Z0 ^. r) W* o3 N; U1 {; e
在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户), & a  ]2 S& L; v& @( J7 z% L+ n
因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。 - ^+ Z. ?; J6 m4 t# @
- u0 P% d" q5 N
下列例子增加一个用户custom,他能从主机localhost、server.domain和
# d9 E9 e7 z# ]+ m# N3 jwhitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从 # f  ~7 A, n# d6 S: [& p
whitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他 + }8 j" d8 V6 V0 C3 ^
想要从所有3台主机上使用口令stupid。
4 }  p. [- [+ @/ ^: G! k' T$ s
为了使用GRANT语句设置个用户的权限,运行这些命令:
6 Y2 [. A% i0 O+ h. W7 K! H4 {! s) ?  v7 z- I  ]
shell> mysql --user=root mysql
4 _" m! M8 q) R' \0 |: ^1 Kmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
9 C2 @: H# }$ z5 y  o. j/ _ON bankaccount.*
: `3 k$ D' k6 x4 u" A: \- sTO custom@localhost
( ^2 m5 i' u  A/ v6 {8 gIDENTIFIED BY 'stupid'; / v/ V1 [6 R* w3 T' Y
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ) o7 Q, R2 B* K  n
ON expenses.* , n9 t  {; J# ~8 I- f% C
TO custom@whitehouse.gov ( ]! P6 p7 y9 C. f0 Z
IDENTIFIED BY 'stupid';
1 c, P, i) A6 ~! Mmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP 5 j: }/ A% p+ u5 w
ON customer.* # u" a  ~8 C* |3 q" r) d
TO custom@'%' 1 s" C! g9 X( ?7 L
IDENTIFIED BY 'stupid'; - g  V, Q% V9 p
6 j2 G; L9 B$ [0 _. Q
通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时 7 j7 m9 _/ \* i5 k8 n
FLUSH PRIVILEGES): * @3 {% L% A/ f( s2 K

  Y5 P$ c2 K* S* H; dshell> mysql --user=root mysql
! b" x5 a3 l+ k% O6 n4 E- m; Lmysql> INSERT INTO user (Host,User,Password)
7 o8 f2 f% T2 pVALUES('localhost','custom',PASSWORD('stupid')); & j' d! T0 w. f5 s* g& h3 k
mysql> INSERT INTO user (Host,User,Password)
, B9 e5 i: I. a; x' j) y6 eVALUES('server.domain','custom',PASSWORD('stupid')); 7 S8 U) f7 _, ^7 i2 k
mysql> INSERT INTO user (Host,User,Password)
; y* m( T; ^0 f# f9 D# tVALUES('whitehouse.gov','custom',PASSWORD('stupid'));
$ ^; F* W2 j$ m1 cmysql> INSERT INTO db , O% {/ P* _* L
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
% c: R6 a. D$ `8 ?% K& ^; vCreate_priv,Drop_priv) 3 G+ h  _# r& [7 S, _( S% {* x' }( |
VALUES
  C- F; R  l- ~! q* \6 J('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
8 C8 ]# m6 o4 Z; z6 ~8 a3 emysql> INSERT INTO db
( a; N, M) Y) c) X/ S9 _(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, - d3 y& i; ~5 n+ o. n
Create_priv,Drop_priv)
7 U8 v" A5 q( B8 n& |  b, fVALUES
# C2 ]8 f% D8 e- b" J8 [0 g('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
- s, F- s9 b$ c) zmysql> INSERT INTO db / V+ o& R6 Y4 H+ x+ A5 p
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, 9 X. Q4 Q- }& c; u9 L* ~; L
Create_priv,Drop_priv)
  {2 X& `; \8 n) ~VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
" U, u2 w0 M9 D/ {& H8 v5 Z) umysql> FLUSH PRIVILEGES;
8 K' d$ A! a; ~: J# r' D
* X8 V$ o7 Q. {2 i$ Q头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机 1 `% |% L) }4 @1 {  {
进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT 0 K4 A. I6 _8 T: D2 }
语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限,
- \$ @: d" X, s, M2 y+ J! Z; \但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告 ) `; S* e/ g+ e
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。
- e. V' v8 B0 |% r' p9 `3 z) V/ t& a' ]! B/ J$ q+ c( j2 b# _
如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发 * U& G: x& o" j: v$ i/ D
出一个如下的GRANT语句:
6 C) E- S2 k* {6 I6 V2 o$ a2 m  i# x& U4 y- O
mysql> GRANT ...
3 x, C" J" b3 B, c, P4 g; ~ON *.* : D8 Z; P1 @# o5 U) t  \4 q
TO myusername@"%.mydomainname.com" $ g) W$ ]! K, j9 M
IDENTIFIED BY 'mypassword';
  g9 S7 @7 q. v+ w# u
3 m+ F% C9 _0 ?6 }& t6 M为了通过直接修改授权表做同样的事情,这样做: - h& F* s% d- s' k
8 o- U$ |* d4 D, O# B9 ?
mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername',
+ [" G& Z. R: U1 \( ZPASSWORD('mypassword'),...); ( A3 n6 d0 v7 ^! j& V# ~
mysql> FLUSH PRIVILEGES;   s; l, S& V) z5 [
& q  Z9 s  l: k
你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变
, R" h) ~0 [0 c9 Q' i和更新值。你可以在MySQL的Contrib目录找到这些实用程序。 & @! W* y# ]+ w9 `

) |! F- n, W3 n怎样设置口令
' I. D6 x5 g2 @- m在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存
# X  Y8 J7 p2 e6 b% C$ p# z储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以   a& q2 M  A. }9 F5 v7 ]( @
加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图
. `" x5 m; y' C& V- {+ x设置口令:
* l! N/ j' }% F/ |, H2 S' G
, Q) v5 G, z. D+ U4 ~8 Zshell> mysql -u root mysql ! U; P  C$ i) p( Q) Q/ S! f. e9 M
mysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey', $ z* I# }1 L. X+ y, b) f
'biscuit');
- _- ~3 \. N1 F# ~5 h  J% U$ I& z8 u9 ~mysql> FLUSH PRIVILEGES ( w. g9 S" v5 I& C+ B2 F

2 I) {1 o9 {, Z$ F. I* m结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用
' v( b& l# h7 i0 F这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服
! B1 r0 v4 `3 R4 R务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是
+ d8 q3 `- e9 }( L, A+ o" ~! f/ U- C$ z9 v'biscuit'),比较失败并且服务器拒绝连接: 8 {, l2 s- u# ]: E4 T0 g6 h8 w! l

: K2 e. w5 j1 D& i2 w& J, z& Ishell> mysql -u jeffrey -pbiscuit test
' N% [$ H) i8 w+ bAccess denied . X. f- L3 _4 r5 K
" T6 y6 k5 C5 F4 W; J; G
因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样 3 a; K8 r' E" y
被指定:
/ p$ k3 S* f  W1 A- X9 K
6 t3 c2 [% e  G9 b* w6 P+ B8 g$ `mysql> INSERT INTO user (Host,User,Password)
! K$ Z& r4 m& e+ J3 qVALUES('%','jeffrey',PASSWORD('biscuit')); 4 @  J  r- ~% _+ M4 o0 K+ u8 x2 A

8 L7 h1 S: F8 w当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数: # Y* e* [3 R8 [" K. G8 S/ o# E

. o* X4 s( K2 ^+ w) Nmysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
9 @4 t" j: |0 Q9 G  Q# V: e2 V, U% ^1 f5 s
如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口
% _5 [1 V3 `1 j/ C令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指
, V" Q7 d- x% Z( r1 I/ _4 v- k定一个口令'biscuit':
$ K, c2 j: G5 w
! e% P/ C1 p' z+ Q& {) emysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
7 R, A7 m. d; S9 ]1 Y3 Z! K; x& \) o
- L. K9 q* _. @9 x1 i" l

% T/ S! S! I2 j' R# Gshell> mysqladmin -u jeffrey password biscuit
9 _. W$ i' e+ e, X2 D# o注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应 % Y, v* Z! u5 b8 a5 m% C: k
该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix ! e& |7 w4 ^2 ~- j) Q
口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。
) h' q( e$ h" [" K' l
1 j, O' A3 f# K: g  MAccess denied错误的原因
9 d+ x9 Y, a- a当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 * q# s' y: q' X3 u" `0 A
的表指出一些你能用来更正这个问题的动作:
9 }  o( d6 U' ^' m3 [( v9 h. }3 U- o
你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容
* T3 }( i% ~9 S! n吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初 8 n9 l- N- n+ i5 ]
始权限: ( C1 V* Q) F' ], O' p& D
shell> mysql -u root test 2 b- u* S; s& g4 B/ }  e/ j6 V
6 R# q: B7 n: E2 I+ ~. z
服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件
' u0 g1 G. S# ^“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安 + _+ W4 E, F  m& L8 Q
装根目录的路径。
( R$ J8 x# c5 m6 Y, j4 p- Y0 ~7 H' n8 z3 C2 W) O& z: ]
在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可: & k- ~- Y1 d: W" X5 ?, ?/ H8 O  c
shell> mysql -u root mysql
! F! ]8 _: N3 o! S- e! f: M( r. W) V$ r2 Q4 y5 U& W' Z! H
服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个
1 ?; e$ y( \8 P& U0 ~安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如 ( s* P: P: I* w& t  ]/ r2 f, E) j6 Z
果你作为root尝试连接并且得到这个错误:   u9 n, e0 M+ l3 N  w) j* a4 r6 m8 h3 B

5 D( E; u$ W; Z% c) r0 @" LAccess denied for user: '@unknown' to database mysql ; `: Q$ Z  p8 n7 c8 J6 B. E

/ l. C/ E  M; v  ?) K1 m( h这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld 0 g% F6 M9 j7 q4 w6 M/ ^9 h
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项 " `- |7 b% y! C" O
重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机 0 n) ^; Z! D6 W% P
增加一个条目。 8 l) J( v5 ?. n7 C

) B* u  ~" O: N7 \$ n% J. U0 d如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以 # Y- |% U* D/ a0 q4 ]# B4 e
后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在
- Z/ n4 B$ K, d9 FGRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。
( k  d/ q$ N* i6 I* v1 b( W如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被 + m% b* c0 K7 x: k3 H, T5 q
忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin
5 D. A, d9 Z" b: y) Zflush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被
7 o- k" o9 B! S, _$ R, {重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗 % ?( [6 c1 s' C, m
(flush)权限以后,因为服务器仍然不会知道你改变了口令!
% Z, O0 Z, J8 X7 f8 X如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变
( B) H) W, {& B. |了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权 8 C" B8 S7 A* I; ^. G' b4 v3 M
限改变何时生效小节所述。 % l1 E2 g7 Z, N; |; \/ [0 V
为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变 ( a2 Z2 G! J- L( h( X! c; _1 P2 Z
MySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的
1 E+ m( [* P, w7 @: ^1 v' p; D9 h0 x改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权 * K" D: v; x  ^% t
限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务
: t; Q8 \  t& O) ^: W: {3 q器开始使用授权表,而不用停掉并重启它。 0 \! P* ~+ o8 G5 }/ V
如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name & n  V% D) B4 I, N  ~6 ~
db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用 . J2 a4 e( _! m3 j" C' N
mysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令 ; r3 E) G) U% o2 X' [8 Q9 i
之间没有空格;你也能使用--password=your_pass句法指定口令。) 2 J8 h; o1 {; W4 u) [+ p7 M
如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句 $ P6 J& F/ H, `4 v8 D% T  q9 a
设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语 & ?3 n* x- `# A
句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。 0 e8 T( K8 K' v: U/ V  u! }5 b; P0 ^
localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 8 f  @* F# E! s3 A( P
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系 7 @( B  T+ C" B
统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT ; N7 l- j/ ?! z. p
-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确 & @& x% F& a9 @% x: m" i- b3 W* d
地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你
& P$ b3 B; h  d8 U) D+ `必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一
  M, I" a6 c6 [3 i8 v! G5 n台的主机上运行一个客户程序,这也是真的。) 7 ]% o: U* O) Y, r
当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个
; ]5 }  r: {3 ?8 W/ o1 OAccess denied错误,你可能有与user桌有关的问题,通过执行mysql -u root
! _" q, b6 ?: m2 wmysql并且发出下面的SQL语句检查:
; V+ J8 n5 d7 C. g( S' B. X. qmysql> SELECT * FROM user; - g8 |# d  A- Y- e5 p

' Z8 M7 U0 g7 `& k- H3 w! i结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户 # Z+ f: s" E1 ?( x
名。
$ f1 c1 M, t0 u4 T5 y+ h4 @3 V/ \* x* Z$ k0 y" K- I
Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图 8 l# e" ~2 T% P9 I
用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一
$ _& K3 c$ h) E7 U个条目,正确地匹配在错误消息给出的主机名和用户名。
; Z4 d% S9 X! u* q如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列
( J" X7 V2 |: B7 y: V6 e# s错误,那么在user表中没有匹配那台主机行: 3 X: \- B" S( H+ F( S: R) k, x4 h
Host ... is not allowed to connect to this MySQL server
8 X* c1 \& c8 J5 A! _
1 u+ r+ o; y6 t# Y( u3 I% E你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试
/ i" y5 y, ?" M6 S0 i9 `图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
7 j) _7 O" k* t8 S你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为 ! Y, t* Q+ c5 @
Host列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从
  V& ?+ `$ j& _( V4 {. l* g7 C客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。( - {/ R/ J+ d; \% e, S
然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则,
4 N& i! \+ x: N2 z5 b7 |( W: G你将有一个不安全的系统。) - p/ g( S5 S2 ]% t$ p; _3 \

4 }, M0 p: m) f1 w% m如果mysql -u root test工作但是mysql -h your_hostname -u root test
, Y% }& T) L5 h- \导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的
9 _) {7 {0 j' N$ n% J; F9 F- }一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统 & k1 N1 r7 ]% G' V& r1 ?' A
的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有 ! O3 V8 u6 r+ ?/ r, I
一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet. 7 O6 d6 f% N# ^4 F+ D7 m
se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作 ( X- m! b3 v$ T/ b6 t' d
为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符
1 M- K* r# ]3 \8 a; _1 T如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)
5 \$ p/ T; J; R# G$ T* Q8 T如果mysql -u user_name test工作但是mysql -u user_name other_db_name
# P1 p, w9 f. Y" Y不工作,对other_db_name,你在db表中没有没有一个条目列出。
. L1 v+ U. O3 A2 O) ?  n, x当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其 & C# @- i9 {0 N$ h% B0 `
它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
0 z, Z; r8 d* W7 ?你没有把客户机器列在user表或db表中。 0 D/ e) x3 u2 I* C% T  B; J
如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host   a) V# |8 ]* _1 M
包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用 - z5 h) F& ]9 R; O& t+ c
Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost + Z7 q4 Q1 [5 m7 S+ T; ?# |5 Q" e
从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost' " z- {, B3 l7 v9 g; x
和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从
* d6 u0 R% [2 L; `5 P* x) R/ w' Clocalhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和 ! }. u5 E+ g: e& D
User='some_user'的第2个条目,或删除Host='localhost'和User=''条目。 ; Q+ O! O! E4 C) v6 Y" Q
如果你得到下列错误,你可以有一个与db或host表有关的问题:
; y7 w% H( Z( Y' fAccess to database denied
1 `5 R9 p) U2 k, M4 ?6 u: y7 ?* i. `& x; f2 c+ p" m$ y# u/ p& q* Q- p
如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多
$ i8 N7 c5 Z. C) F7 B1 c个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ... & V7 y% O$ @, R" X3 v  H9 ~* }
INTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可 ; Q, ^6 `, G4 ]; E8 w2 J
能启用file权限。
% H& t$ M& l2 f. l0 p) ]+ E
6 m5 x( k8 {  K8 {  t% w7 O记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果   h* U) L3 ]6 l' M+ m
当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,
8 S  J$ d$ R; c7 D( I& E检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围 - j+ I' f  S, Y5 G) n& z8 N
的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当
9 O" q% \- X6 i/ p8 ?% D* G6 R你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选 / P5 l& R3 d4 \3 |. B9 U( A4 {
项文件里指定一个旧的口令!见4.15.4 选项文件。 / V4 Q6 _3 y+ J/ k! e
如果任何其它事情失败,用调试选项(例如,--debug=d,general,query) 7 g1 z3 h) b3 N: k6 M  ^
启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每 + a/ a9 n: k; O/ p! }5 @
个命令的信息。见G.1 调试一个MySQL服务器。 5 Z& V  B5 K7 H
如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 $ U9 y7 r* k- D+ T* j
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump
2 t2 |& g3 K( P4 amysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一 6 ~: l% H# L0 X( Z
些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。
8 G, @0 e0 z5 K0 O8 x( v- E. q* _怎样使MySQL安全以对抗解密高手
/ {% n& X: K% p, T当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文
- `. D( d. M. w在连接上传输。 ( ~2 t3 E0 N$ P) `

" P! H, c& _2 Y/ q所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可 5 n$ z+ v7 N0 j* [: a5 S" S
使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全
5 V" u0 e0 O  f' ],你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服 % d. ^) r6 }  w. H! V) s' s! q
务器与一个MySQL客户之间得到一个加密的TCP/IP连接。 " F4 R& Y6 |: \2 t

" \  \1 X1 p) p3 K! Q5 s3 P为了使一个MySQL系统安全,强烈要求你考虑下列建议: * y: W$ A& t( S( z5 m, U3 [) ~

7 G. J+ M/ q7 m, D: r- |对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简
+ W9 |! E3 P/ n. c; v单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器 6 j3 ^* J. e4 I/ s9 e* m' u9 R8 U
应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通 ) N: g8 f$ u0 y" @: {
过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令,
# A' D* y) W6 u* D8 r象这样: & H% U: R/ Y' m9 p
shell> mysql -u root mysql
3 F; }* F4 a0 U* [; Lmysql> UPDATE user SET Password=PASSWORD('new_password')
: S$ B" p& x0 P8 ZWHERE user='root';
& ^" ~9 h9 A& l  ?; G5 u& fmysql> FLUSH PRIVILEGES;
& g( I3 D: ]1 v, y6 E) Z
* Y6 R# f9 s) n" D1 c# F不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行,
2 i+ Q# F) }6 ^( F5 c, m你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户 . m2 s! @; p  I; b, K  R
运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix & D* o0 W7 M: r* p3 _6 F0 ^
用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。
# _) Q/ U$ v6 X. ]  p通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行
. E' a0 U7 w' |4 ]( u: }) T( Q5 LMySQL。 ! F3 T( j0 C3 L- u2 [
如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本 . T2 O1 z( ~4 S5 p- S3 d0 ?
只能对root是可读的。 ( S5 o+ E' |  G
检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用 ' _( [$ \5 `0 X7 l9 N/ `
户。 : h3 M2 D% T1 u" L; r
不要把process权限给所有用户。mysqladmin processlist的输出显示出当
! Q3 N  b- d1 E4 t前执行的查询正文,如果另外的用户发出一个UPDATE user SET password=
6 [8 w( k/ L: V/ {$ J% |PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。 6 f) ?9 u2 e7 ~: ^' a( h, u
mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用
  y& u0 b, u9 P, E户能登录并检查,即使所有的正常连接在使用。 , O% ^+ i6 c2 G0 m! s  C
不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
/ ^$ L- F1 |3 P1 W; X- ~6 l进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ... 8 O! M. K  |8 ]+ U
INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 : b1 Y3 @0 f9 h$ r: a, V
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文 5 W. b0 k7 S1 [) j- i$ K
件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数
% a# \5 a2 ^* |* \. R据库表,然后它能用SELECT被读入。
8 o# z' k1 i2 _1 m3 r+ B  e如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则 ( z+ J  H3 B( g1 H
上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常 ; p# `  x5 m0 M2 E; Z
小心地使用包含通配符的主机名!
1 p8 M4 s' q0 _, Z7 O" u下列mysqld选项影响安全:
) Z( ?4 ?1 l+ s8 ]) p, \. P, s( w: N, b! K' w
--secure 0 d, O; }$ C' \1 J9 K: B
由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来
9 x" g% X4 [6 w9 ^: F' U; }的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也 % w+ L, e; Q* V9 I0 @. ?6 z
增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
+ y0 J3 |0 T8 T3 f0 r它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。
! C4 z4 I' w8 P# w. A--skip-grant-tables : D- n; r: n4 e7 m( y
这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数
: X0 @' H& p* t) n9 L据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器
0 I: O: A4 l" K9 Z5 g; v再次开始使用授权表。)
, L) ~7 N# M4 C1 g' v$ P, T4 M4 H" ~--skip-name-resolve # P% j2 T+ h" {3 U  g
主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。
" @. s3 U5 f/ h6 p$ m8 j" Z6 E--skip-networking
7 l. Y- u! p1 F/ _7 ~' b' _) {在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
; g' U( i8 A7 _& b1 [# Z6 ]行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不
( N$ T; n4 o! u4 p5 J支持Unix套接字。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

4
发表于 2003-7-26 20:02:00 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
看了一屏就晕了。。。& l2 n& ~5 a  }4 t8 C! y8 f
汗。。4 K# h( Z) F0 C" k) P' x! j6 a
水平不够,消化不了。。7 i5 l( h  I# I( }$ L+ o* b
不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

该用户从未签到

3
发表于 2003-7-26 16:52:00 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
讲什么啊?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩
丧心病狂 该用户已被删除
2
发表于 2003-7-26 16:39:00 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
其实我也很想买了看的,可是我是版主,不用钱。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩
关闭

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

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