下沙论坛

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

QQ登录

QQ登录

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

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。
$ p: V8 L, Z' b
# v8 M4 \% p' x1 Y, R+ q* }权限系统做什么 9 Q. X. O# I  b( f0 F, K7 n
MySQL权限系统的主要功能是证实连接到一台给定主机的一个用户,
) x6 S; w5 }% }9 w8 |并且赋予该用户在一个数据库上select、 insert、update和delete的
7 V/ U" x9 R. g: `权限。 & F9 g- V: }8 M6 y! Q) W% s
1 x; T$ W3 B4 S7 x6 m: A
附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如 3 v; a2 D; T; D3 g# m, U) ?% H& a
LOAD DATA INFILE进行授权及管理操作的能力。 : q. z# K) x$ Y5 L% ^
- D' |$ G3 U& Z' A
MySQL 用户名和口令 " K0 M# I+ R" l/ a) _( V3 h8 ~
由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很
, p% t# _2 G  J6 q, z多不同之处:
" K' _3 t2 C, c
8 {  ], i' g& _8 cMySQL使用于认证目的的用户名,与Unix用户名(登录名字)或
9 x9 U9 O# ^  wWindows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户 # B# M  N; n: f0 R. [/ p
名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或-
9 Y* @7 w* E2 y- N7 g! |' M: f-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据
3 N. y7 o& q$ ]# f( k2 s4 t: z库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名 $ o: ^% _) j  ~0 E, |
字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。
% Z! P; Y) w" z5 n4 K9 M" gMySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。 3 H0 `9 n0 j9 ^. c+ |
MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使
3 u* @9 w+ G+ X6 @用在那台机器上存取一个数据库的口令之间没有必要有关联。
! n+ U6 _1 v$ F# c$ P0 ?$ m1 QMySQL加密口令使用了一个Unix登录期间所用的不同算法。
1 o  U2 S1 O5 ]" Y/ g. q
- `: f$ q  p) I9 y# I$ P7 r与MySQL服务器连接 / W# K1 S- U3 D% ~9 \- o) ^1 S
当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定
2 @' l* C3 j, U: P6 \$ g# {连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql & n, ]! s/ y0 l( x- O
客户可以象这样启动(可选的参数被包括在“[”和“]”之间):
) D6 \: }+ a2 C5 H9 `* U2 H( y7 t6 V  ^, _. t2 g. F
shell> mysql [-h host_name][-u user_name][-pyour_pass ] ; F+ G) w' h/ m: n
-h, -u和-p选项的另一种形式是--host=host_name、--user=
# t9 }6 U* C. S, x9 z6 k. g% H$ Fuser_name和--password=your_pass。注意在-p或--password=与跟随它 : B+ L% ^3 [0 p
后面的口令之间没有空格。 3 a& z% B6 o6 m7 j6 {" Q) W" B
8 V* m" J2 q' d! f5 p, y5 z
注意:在命令行上指定一个口令是不安全的!随后在你系统上的任 - n7 S7 [- @/ J( U' `& c+ S" G
何用户可以通过打类似这样的命令发现你的口令:ps auxww。 8 ?$ D; I  E/ m) Q3 o4 w) [

8 _* O( h" v5 K7 E; a对于命令行没有的联接参数,mysql使用缺省值:
2 q" t& `9 @' z
# M  P" |6 V# |3 |缺省主机名是localhost。 4 R4 |% E* Z9 T* p) b! B
缺省用户名是你的Unix登录名。 / J* X1 d0 ?# }, j7 K
如果没有-p,则没有提供口令。
& J) K  ^8 m- r/ x* g' Q这样, 对一个Unix用户joe,下列命令是等价的:
7 U# S, X8 v8 B; M1 u5 Z
- E, L3 Q/ S% M! m& s6 ]shell>mysql -h localhost -u joe
; u! }* U/ j) x: U5 \shell>mysql -h localhost
: M$ _' ]5 |  H6 H. M4 qshell>mysql -u joe / I  `3 G# \# C/ _2 N# L$ z% |
shell>mysql 5 O: L" D! T3 Q: U
4 J# W* B, T6 q
其它MySQL客户程序有同样表现。 7 G/ @- X0 @# M3 s
2 L" s6 O3 d" D
在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺 5 a' C9 r) `1 G, }9 d6 g, h
省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这   h* u3 c) U/ t! L0 R4 E, O
可以有很多方法做到:
* R: s# p: {7 _, d* V$ k
7 V3 X6 r( q* w你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定 + f9 I" M: V3 Z6 Y
连接参数。文件的相关小节看上去可能像这样: % t4 z4 A9 ~4 O, Y2 `* w
[client] 7 [+ L) A% I6 ?2 ]9 s
host=host_name
$ c4 u: [. x# x/ D; z2 duser=user_name   }8 q# M( j. }8 U
password=your_pass ; g  ]& y* [. X
- P# G! w7 C5 f
你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL
6 y5 g+ z7 P  L- j用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是
# X4 E, Y! n& u( d这不安全) 。 , {* l, P0 d/ k+ N% z8 _3 G
如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配 5 P$ e' o# p, U/ i$ U$ ~# M
置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量 4 b6 n6 H" F0 h' q5 x( Q
指定的值。
. `8 t# w. A/ g1 g. n5 F
9 f9 M% N7 ~/ v, m2 |2 {使你的口令安全
2 b/ M+ R: c- q) E8 f/ _6 s以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。 4 L" U/ E3 P7 ?' r$ d' O- M
当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法 1 _2 }* Y. A  c1 i
的风险评估: ( O6 P9 \& |9 H* z. _! P0 D7 M, Z
3 L% \; \- }  {! c$ j
使用一个在命令行上-pyour_pass或--password=your_pass的选项。 : u' K0 l0 m1 Q! {( W$ B
这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见,
0 G& p7 f0 t2 m3 N( ]1 E7 @9 p它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化 5 w0 r' M: N7 `. L$ T4 `  {! z
顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可
2 d' c5 \: \- ?) ?见的。) $ |/ z+ g4 N2 x7 {# b
使用一个-p或--password选项(没有指定your_pass值)。在这种情况
7 B, W* k$ u2 g8 m7 O3 W下,客户程序请求来自终端的口令:
8 `5 x  p8 ^; p# o/ j; |( i, e4 i4 V7 |3 O  J- c5 H
shell>mysql - u user_name - p 2 X7 b5 @9 I7 G1 ~1 ^" T: u+ z
Enter password: ********
" Y: Z, `* Y2 P0 U& ]/ d1 y. i3 g& ?) u+ B+ K+ V; S2 x4 c
客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见 + C1 R# s- a1 M+ I- R  B7 t9 a
它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你
$ U. m4 d# t$ I8 Q0 t* g的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程
6 X: J( o1 i' d( \序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就
% x% y4 U' F6 m没有从终端输入入口令的机会。 ' W% ~" q- z! `/ }7 v# t' H

2 T$ L8 l( r+ U' E8 K8 F3 S在一个配置文件中存储你的口令。例如,你可你的主目录的
5 Z4 X! |$ r3 I# Z* D5 g0 X3 {“.my.cnf”文件中的[client]节列出你的口令:
; H) q, B0 P; s1 d[client]
& e4 f9 Y+ ]5 }password=your_pass
# T4 U5 `8 E- n" r$ ^7 `& F/ R/ X2 y- s4 j5 S* ^) D% R3 ]
如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或 - [; ]  v+ G# \8 J+ E; g* W; f# b
可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。 + i/ A2 ?& p9 F9 _! X/ D% h) s* P
  [* d7 {9 y. @7 `+ r" Q8 y
你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极 0 s% N* V  ~, z5 J$ R
不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项;
3 W9 [: V' H& f如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有 3 _4 a5 V$ u# y/ ]  Q. B8 Z
这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智
! F6 w- z* D% v( M! L的。 % G$ o# n2 J  e" l4 C. h
总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
+ G9 W# g" ~; x' L" s3 y0 }# ^.my.cnf”文件中指定口令。
6 T! G1 \3 ~2 c& }+ y- e) f; M9 x: R  W8 h) O0 m5 l( \0 T9 s
MySQL提供的权限 4 P1 u* l( r; u/ {3 Y, I+ [$ ]
权限信息用user、db、host、tables_priv和columns_priv表被存储
* Y3 j! ^% r. W! w在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限 6 N3 Y* c+ ?! \: N  d9 D9 n# Y
修改何时生效所说的情况时,服务器读入这些数据库表内容。
( I! c  b4 u, `8 [- F$ G& r  ~- T1 }6 v5 x) x
由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表 , o0 D1 z' h$ R- _
列名称和每个权限有关的上下文:
+ B; g! b) G* Q0 ^* l) R+ N; i6 e权限 列 上下文 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 在服务器上的文件存取 ; {8 V$ n: O# `6 [2 l/ Y  f+ S$ m
select、insert、update和delete权限允许你在一个数据库现有的
: q" d, o' h, f3 V3 [表上实施操作。 3 q- c/ S% O, p7 @5 o

# k$ J/ u; p! t, L+ ?, `SELECT语句只有在他们真正从一个表中检索行是才需要select权限,
: l4 T2 l2 j  X1 a; ~' L你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存 ( g2 ^2 j- L' W  J
取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器: / f5 K2 I4 K) i- h, c

* s$ x" U- o( V, cmysql> SELECT 1+1;
  b+ H6 D! w1 Wmysql> SELECT PI()*2;
4 ?, O& J+ ^8 s& `  i: b/ x
; w6 ~- _8 x5 a2 R3 N1 dindex权限允许你创建或抛弃(删除)索引。 ( N2 \. E: N  X. @8 W

- g, `! K0 _! ualter权限允许你使用ALTER TABLE。
/ ]$ J4 U+ z6 f7 j7 S8 z: U8 Z$ X8 G/ L) x/ U/ D& }
create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的
$ j) H$ j, w* E& q" O8 W/ d' R) _4 |数据库和表。 2 h  j& _. M$ E; b+ H9 K% S8 N

- D3 K" n% Y' l- b注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃
4 ^" M  @$ y) `' ]存储了MySQL存取权限的数据库!
2 S& Y. r7 p3 @* [' m4 S7 @
( u' }; q2 A% G5 p2 ^, Ugrant权限允许你把你自己拥有的那些权限授给其他的用户。
8 ^! [% P  o) `; r) D" g. c9 |* o6 k! t4 e$ R  u2 \9 n& n
file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句
  z8 ?' n3 A3 `" s4 u8 l/ Z( _* n读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务 9 ~7 Z% R9 E- A2 T4 b" A
器能读或写的任何文件。 4 u& E& t- d) k( L0 \( B' u# h* z/ }
3 d8 |: M1 \( c: d  w5 a" s
其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示 - b  L# S' c2 i6 |5 {
mysqladmin支配每个管理性权限允许你执行的命令:
3 n, B5 R7 ~9 F" N6 c: [6 K4 H优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill 3 W+ {8 y; Y: s
reload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开
4 y( ^' E, q& Q3 w* z# d和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-*
. `) {( j) o2 p, d命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更
" f. t7 Y" G! ]& X* Y3 Q0 O好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的
) X. G2 W) B0 e$ O) f2 t选择。
2 I- w1 v- K' j4 e8 M- p, Y* l* p' V' O+ n* l# E2 |
shutdown命令关掉服务器。 6 k  T5 w6 a5 \$ z9 D7 L3 t: i

8 S. U* T" e! u* n, I; Pprocesslist命令显示在服务器内执行的线程的信息。kill命令杀死服 ) {1 P9 K& C. ]" i7 b4 o1 ?9 W7 |  t6 C
务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来
0 X' [5 L1 u) k  u- s$ [显示或杀死其他用户启动的线程。
, |6 ^; u7 {2 S! W8 P) o6 d' @& ?3 C: p' }( U3 T
总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你
- I! S9 H0 K) \% {应该在授予某个权限时试验特定的警告: & u& m% W4 a6 ^, D. l# r
5 d7 b& ?  O: n& {2 C6 L
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并
: U( b% `& [, l- ~! C. P; O6 Q有grant权限的用户可以合并权限。
& l8 N- M0 G4 r5 g: Ealter权限可以用于通过重新命名表来推翻权限系统。
/ X! e. J6 d/ E" j; p& Z7 Ffile权限可以被滥用在服务器上读取任何世界可读(world-readable,
$ B! o5 t2 U( k即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。 ; s& U8 @; {5 j8 j2 }" W
shutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。 # L: [# N9 g1 Z( f: m7 E1 c
precess权限能被用来察看当前执行的查询的普通文本,包括设定或改
3 k6 Y: t% O% W  N% Y8 k$ M变口令查询。
- s+ R, Q, Y6 o" }) R6 s# x在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口 ; z7 M0 @" }) C1 [2 k
令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够
0 J7 |: ^; N7 g的权限,同一个用户能用不同的一个代替一个口令。)
& H' k' C+ H9 s- [9 G有一些事情你不能用MySQL权限系统做到: + [; U9 H" `- |& i0 [# k2 ?) B

% g/ @$ p. o" ~2 v% m你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹
! a# |( Z; o; W' A4 p: {配一个用户并且然后拒绝连接。 + P) l$ `8 x- S) a
你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建
: L6 Q' D7 O2 \- B或抛弃数据库本身。
+ G( G$ g6 m7 h6 M+ Q! z权限系统工作原理
( I, |( ]3 ]) e6 t% qMySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。 2 K5 T4 F; e* V
当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用
, }$ g' m0 u" _9 C+ j& [' D  Y户名来决定,系统根据你的身份和你想做什么来授予权限。 & }, G! y0 c* i' `0 b
% E8 \! z* [  H0 d" y
MySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假
2 i% E( F0 s/ h& C7 Y定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov
$ K' }7 ~$ C9 w$ E7 l4 K# z* c2 x连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区
- d" o$ I  p% f/ [& K# T分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov & g, W* @7 B, W- t% a) p4 g) g
连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限 # g: _+ P4 U; T+ p; Z
集。
; K4 c. @3 s/ _8 b9 \6 r
+ t6 M5 T& w2 U6 ~MySQL存取控制包含2个阶段: " Z4 y0 W6 T8 g0 K5 D
: [9 b* d5 x; o: {0 r8 U
阶段1:服务器检查你是否允许连接。 - H4 Y0 z! n1 g# U' D
阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够
. d) J2 v$ l& P" p9 b$ K1 I) x的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛
: G7 ^1 s) j. g- T8 z) B& |( b弃一个表,服务器确定你对表有select权限或对数据库有drop权限。 7 d+ o; W: C, J8 m8 o9 I9 \
服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host
5 O4 _0 v, Y$ K7 Z" ?" N  k5 p- z% S表,在这些授权表中字段如下: . O9 g8 C0 N" l/ J, U  _% o0 C& w
表名称 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
& z9 T$ p/ {0 b0 T+ O3 E% b对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
# ~1 F( w; x% ~参考tables_priv和columns_priv表。这些表的 : S) w$ e8 S  t# q3 b
字段如下:
9 s. y4 J3 v5 v: 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
- x( G$ ~$ }1 I对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
1 S5 ]6 G8 A/ R参考tables_priv和columns_priv表。这些表的字段如下:
/ f+ x* E* d8 z% b) J字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
. U' @; j+ K) G: T在user、db和host表中,
% i. Y, s- C6 a. c所有权限字段被声明为ENUM('N','Y')--每一个都可有值
2 O& T4 [4 b' y'N'或'Y',并且缺省值是'N'. 6 n6 }- i( |% l) _" r
在tables_priv和columns_priv表中,权 0 S$ H' j! Q8 w; [4 G9 I0 Z; y' a
限字段被声明为SET字段:
. p. S8 M& }. }5 a4 p! L6 W% V3 \表名 字段名 可能的集合成员 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 q. \; h  D* }2 f每个授权表包含范围字段和权限字段。
6 h; `1 h. v: U% y8 ]! d4 C9 q5 o  U# @5 _. n$ Q
范围字段决定表中每个条目的范围,即,条目适用的上下文。例如, # G( S0 h* l6 N# S- ^2 D
一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于
3 p/ Z0 s+ {- A" f( V1 [8 {$ i证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条
6 ~& c: V' D) f4 ^目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports'
% a% [2 P6 k) d6 T4 V: E: _! ]9 Z将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。 ; ?! z" @+ Q! |  k
tables_priv和columns_priv表包含范围字段,指出每个条目适用的表或
( ~8 d) g$ f9 }. C) \6 C- I: L5 @表/列的组合。
, y( W) C+ C% g+ W) w2 v
! S! l6 S- }) J( l; S9 {对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
  e/ M2 j# [/ ?2 C& K# l# uDb和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以 ( ^  ]8 g  m- r) Y
后版本是忽略大小写的。 2 {* E9 E, a. _, Q7 `/ c* Z8 ]2 A
: j7 i6 K1 B  R
权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务 2 d% a; R+ z3 Q" U& z) ?
器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规
# P$ b1 g# J; `则在6.8 存取控制, 阶段2:请求证实描述。 4 h* u. K: a% b- y8 F3 f
* ~* s7 E1 V) q; ?
范围字段是字符串,如下所述;每个字段的缺省值是空字符串:
1 Z, ~+ g; r  m' G0 F9 `6 M2 v字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) ; a: n+ t1 ]! T- x# s# @0 A* K  I
在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一 - M- x3 @+ {# i# V( S* g) l
个都可有值'N'或'Y',并且缺省值是'N'. + Q: W# \+ t" p, m$ m
, o/ U! l1 P; u/ j3 \
在tables_priv和columns_priv表中,权限字段被声明为SET字段:
  `* z6 J2 D" O' U9 ~表名 字段名 可能的集合成员 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' 4 [3 G8 D( w, z: Y: y: Q! X
简单地说,服务器使用这样的授权表: 3 Z% Q: O$ H! t5 r

# |' N# F! B$ t' Xuser表范围字段决定是否允许或拒绝到来的连接。对于允许的连接, 3 N$ f4 h$ `2 f( s4 _
权限字段指出用户的全局(超级用户)权限。
/ G) r- {! `. x! wdb和host表一起使用: + w( [, n7 M& O8 y
db表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定 # k& F( h% I) j* `% B# h# t
允许哪个操作。 - y) G8 [2 R# B4 Y, y) N0 u
当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩 7 ^6 d0 [0 A$ K. ~7 x
展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个
4 d, G! w) o* T, u  B3 _& J, U% [. H数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移
7 R  b5 s* X3 T3 ]4 D入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。 # k2 I, Q* t5 f3 i6 V- y
tables_priv和columns_priv表类似于db表,但是更精致:他们在表 ( ^" H7 p# p$ V% C
和列级应用而非在数据库级。
% h8 N! v5 p  ?- G注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是 8 C$ [1 U  ~8 Z3 D6 A  t/ S
因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由
$ C" T) [" a4 m5 l, g, f! m在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是
+ I# h& w" V/ n否执行一个管理操作。
- T" Q: {; R% S! _$ r. E; i
8 Y7 [/ o; z1 j/ [file权限也仅在user表中指定。它不是管理性权限,但你读或谢在服
! L+ u- c4 N) m, f务器主机上的文件的的能力独立于你正在存取的数据库。 : p8 f7 k' ^4 R& p+ W, C
  W, h( j7 d6 j& i  i( e
当mysqld服务器启动时,读取一次授权表内容。
& ^# {/ [' Y( K( [8 z; ?
8 v; ?4 D# J# g7 F1 _; x& w6 S. V* y当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一 8 z" m& T. O+ t5 }
个好主意。
, V6 j: }6 ]5 Z$ C8 N; v: A
4 c. |/ n0 i  ?5 U+ f! C) M+ n一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给
2 ~3 v; P# z: p0 W% yMySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意: # f" v) ?  H  I5 H( ]
mysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。
: B, f& a+ N% G4 H/ C, O# x
, T$ l/ s2 }- P. t4 A存取控制, 阶段1:连接证实
: q! j6 H* n1 p# N, A当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能
3 p) t# r+ i* f0 J9 o# P通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全
4 P9 q- `, P1 F! K具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。 . L! Z  f/ L) q$ |- S- c

$ }: i' R( C# \; f6 c8 _你的身份基于2个信息:
" j! O" @( U* A' A1 ^, w  I, Z; a! T
你从那个主机连接 6 {, I$ i; z) F
你的MySQL用户名 . K/ u) a, o% `% u; r+ {! @  f
身份检查使用3个user表(Host, User和Password)范围字段执行。服
# y5 N7 R" i. i务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的 1 Z) Z1 f$ T& T- P8 y
口令时才接受连接。
! M" q* }% C. B' T$ L
3 {, }. T- i) h  c4 j* v* V1 ^, @在user表范围字段可以如下被指定:
) J$ ]: |0 Y; D6 j. C. f) u
6 X" N' x5 d! S* J! V一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。 0 _) Z6 K7 l! b8 u& x
你可以在Host字段里使用通配符字符“%”和“_”。 + w) ^$ p2 V9 {# O  B" U( N
一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些 $ [6 M8 D# m# ~# B7 x% e! U( R
值匹配能创建一个连接到你的服务器的任何主机! & N0 I+ v2 i& T4 [- b+ w/ }
通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何
2 n( u0 F* ?. }, R6 i3 N名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为 8 c. e. r. Z& b. ~9 ~
是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空
, c1 l' n7 H" p  y& Y# w白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。 0 K; k) N9 V3 m  _
Password字段可以是空白的。这不意味着匹配任何口令,它意味着用户
! Y+ {% d0 g3 q, T6 A2 ~必须不指定一个口令进行连接。 $ k+ E0 E2 ^, G- e
非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本
* m) i/ i( H' e格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用
" R7 L$ F0 c/ d/ EPASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他
* i$ {& x% t' z# C; D们匹配,口令是正确的。 0 [0 Z0 }# X4 W6 h) M7 a

( _6 c6 i$ L5 w) o+ G- ^下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来
, M  ^* n( C, r- p: I的连接:
8 D7 H  a" v' ~) R
3 V$ U1 Z9 c$ yHost 值 User 值 被条目匹配的连接
. J) d, L0 E1 _. u, I'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接 ) b5 `' P! Q8 K6 f- a
'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接
" [# Z$ O4 }+ L/ |'%' 'fred' fred, 从任何主机连接 9 ]3 K4 L# J+ g9 P
'%' '' 任何用户, 从任何主机连接 * O9 @" {5 j9 b* N! _2 A  L
'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
  _7 G$ |! m$ y5 Q'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许
9 |  I" |1 c; @/ f# d1 _无用)
  }- n0 @/ d5 L0 M8 C0 X1 `+ l'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主 6 I5 Z/ b6 p% g6 C3 L; m
机连接
5 U+ T$ ]( F# z; q. D, y'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连
0 z" J3 _% O; F7 Z" }& o* c* M, h! m( Z( |) F
  {5 X. ^' D7 B4 W, k
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子
( d! V7 @  S# B. Q7 g6 i4 n网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机
* a0 e9 x4 g$ W# q( ~为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以
& t6 `) A% ~) h数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的
4 i# ]% O; l* `% Z+ z主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配 9 X+ d" ~* j# k, s
符值。 ( o% D8 J" F" p$ |  H, B  X
4 D. i2 B& l! s- j9 {' ]
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由 - L- u$ m  _/ q& T6 V5 F1 o+ r
fred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配,
& r. |) u  F. d1 p$ {* u服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来 . e$ D9 ]3 o4 ?$ {9 T, L
解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一
7 }( l3 }8 y/ c; c个匹配的条目被使用。 / X" J/ m$ J8 p

+ N3 a- z+ a7 }9 ~# q' guser表排序工作如下,假定user表看起来像这样:
$ R/ a" @6 J+ N+ n7 I1 t. e4 t* A* U
, H) n  O# b1 t. Z9 l5 w
+-----------+----------+-
; z6 M0 `: L) k1 Z8 I# c2 g│ Host │ User │ ...
2 A4 |' \% P) a4 v! p9 Q+-----------+----------+-
7 [5 x; E- g( Z; J8 E. R│ % │ root │ ...
) j" ?! o: T3 ]! u4 v3 T2 c; P" e. W* Q( |│ % │ jeffrey │ ...
2 h# l8 {5 P5 i# g  T8 ^  C│ localhost │ root │ ... , M; f  @8 z+ T, f
│ localhost │ │ ...
1 Z" a: K7 O1 w; Q  I( r3 H. \+-----------+----------+- 7 M5 I4 a  H' V# c3 t

+ ?8 d. m" y% `* U$ v当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在 ) a" T9 }3 A. \" {+ ^
Host列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以
( Y5 r7 u& ~8 R* `! F8 f1 C& {最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且 4 e# I7 c9 |6 S+ R1 {5 W# y
是最不特定的)。最终排序的user表看起来像这样:
) p# w( d* E  L, L- t, B6 I- \8 t" o& N) R* _7 h; q% ^

$ x9 M) z* g, D6 j/ A! A% {! x+-----------+----------+- 4 e# b7 `5 K8 ]( n& {0 y: V
│ Host │ User │ ...
0 O$ k# O2 T8 c& A% L3 p# k6 N+-----------+----------+- * j" R( ?( ~8 p( [
│ localhost │ root │ ... % n% Y. Y; H7 z* F) z
│ localhost │ │ ...
9 R) p5 m) z( w* f, `. e0 `1 D│ % │ jeffrey │ ... 3 m' I) |: S$ `8 I
│ % │ root │ ...
- h: B( o' E( u+-----------+----------+-
6 X2 N( L; A; M( G
/ b! V$ S: ?' [) ?$ f9 I当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹
% f: `' m5 y0 q4 W: |6 Z配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目 " b% |/ s! v! m6 F- V
首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/ 2 @+ i  q, t2 r3 z: O" ]4 k+ p% ^; Y
'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。) 8 f# p3 E/ G1 p+ z' I
/ o4 ^) Y) e' e4 h8 u& y
这是另外一个例子。假定user桌子看起来像这样:
* [" V! @$ u- w! N. _; x
. T; m. Y" \" ^* ]6 P$ a! [. u5 X) e; r1 c! ]  h' t4 q3 M
+----------------+----------+-
0 |. ]& h& J1 s+ ~│ Host │ User │ ... ' F* ?+ m5 c; ?' P$ L* M; D
+----------------+----------+-
/ s# ], ?9 c# P│ % │ jeffrey │ ... 4 n! ]0 R' c8 r% ?2 ?7 d9 O
│ thomas.loc.gov │ │ ...
+ r: p' Y% W& B; r+----------------+----------+-
2 w- t0 O" \& b" \
" T7 ~) \4 V0 B# R/ ]  d+ Y排序后的表看起来像这样: % U* P' H, l: B! `4 q! O* c6 n
: n7 t/ \# _8 v  P7 I3 L

, l4 J; S1 K5 Y9 g+----------------+----------+-
' C0 o& Y/ t, \; v│ Host │ User │ ...
2 I9 O* r3 r. m2 c+----------------+----------+-
: `4 ?$ S# Q% H  G; c! h% n  Y  H│ thomas.loc.gov │ │ ...
  L- c+ T" `+ l% S% ~; W7 q) q│ % │ jeffrey │ ...
; K" H, ~. \& {' r: a% q) B/ R+----------------+----------+- ) w' [( J& }: U, _- q2 ^+ L% _( W  g

6 v- ]: s1 b$ o# N. T一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由 . W- g- I$ h. f" @# R% B! E7 g' f
jeffrey从whitehouse.gov的连接被第二个匹配。
( w. T, G' w* }( N) h- h9 y0 g0 Q( F5 |0 a8 r6 \; s
普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找 + _+ J% G" e4 Y6 u
匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。
8 Z. ]% D6 m2 E先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没 ) j; q* ?  j# Y* Q5 ~4 O0 K+ E
被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹
3 v* Q4 T0 V2 o  \配!
& ^- F. m! o7 Z& Z* J
2 I; \. r- _' N9 g! k: [6 W如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个 & Z9 Z6 N1 Q* A8 o* E/ X8 b
匹配在哪儿进行。
% s  b% y+ A$ p# c( Q/ O1 Q6 C6 _- B, L& |1 {6 F# ^2 Z# J: f
存取控制,阶段2:请求证实 , q. l, q! @, E/ l
一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个 ; H5 r* D& |* H" @  i
请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作
/ U( d9 \. E7 h# D  x3 ?类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子 / l+ o& ^. s/ c
user、db、host、tables_priv或columns_priv表的任何一个。授权表用
# G2 R+ [& [# U0 D  SGRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参
3 i% \$ v9 L$ c! q考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。) ! l- l  @5 b) \) C1 U
0 e" v* s3 b+ G2 V
user表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库 8 r( H5 e. I7 ]/ O% V. b8 x
是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器 + F) E& u9 ~( c/ l- A5 n, c& ?
主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
6 h. U; Q( ?6 q' U2 _+ buser表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户, % N" I  @: I5 X4 Q! e: U
你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权,
* X6 I( O- i' ~6 L5 R5 C! G/ g/ V使用db和host表。 ; @- _; B( T1 ^  Z/ L9 x7 h" g7 H* n
+ W. {: A' o8 s! H& m( w- B3 U
db和host表授予数据库特定的权限。在范围字段的值可以如下被指定:
! u- N/ i" V/ f; I: I" Q  o& y0 ~1 E0 A. \: K
通配符字符“%”和“_”可被用于两个表的Host和Db字段。
. l6 S1 H+ L* C* F& e- N在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 . w6 E* a5 t! y
着“对进一步的信息咨询host表”。 6 ~" m. c$ d3 q# O& g; P: I* ^
在host表的一个'%'或空白Host值意味着“任何主机”。 & c( D* C' w9 ^9 ^8 N% o
在两个表中的一个'%'或空白Db值意味着“任何数据库”。 0 C6 T; Q1 s, X3 W
在两个表中的一个空白User值匹配匿名用户。
5 c& q5 N6 _: fdb和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host : w) B( @6 e- _
、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于
1 t2 J' ]4 M2 P* X0 |  D# i$ @, tuser表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 9 C& @/ r7 ]: D/ E5 i2 \$ [' x5 P1 @
匹配入条目时,它使用它找到的第一个匹配。 + F% b8 r2 d, F3 {: d4 r

+ j8 z; p1 [; ]& ~tables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可 . S2 h4 i4 `; H
以如下被指定: 6 q' o1 a& D+ N
7 j7 }$ |, Q5 [" `
通配符“%”和“_”可用在使用在两个表的Host字段。 / `2 e2 B1 e* L) G0 m  n
在两个表中的一个'%'或空白Host意味着“任何主机”。
7 J% @4 n' X  ~# Y" L在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。 ; O) J! P; f  h2 a8 R6 ^; E/ }
tables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于
* K; {8 q+ F7 v7 D0 |db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。 % [4 L. A" H" S5 a

. V4 [0 R( y  z, ^, c, b$ Y请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这 : H! \3 v, x4 b6 e% W* ^
里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是
# f: z+ ~- c4 \6 U! _" }不同于使解释更简单。) . Q& ^8 e& |# }* Z, s6 C7 ?% N$ o
4 @' `4 x) c/ C" p) {
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是
8 o, ^# O6 }* }  V3 Y! a* G+ j1 @唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。
; e' \  ]3 n- M& d. [, I0 h例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授
- A3 t, H* K( _8 [; K8 a予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含
: B7 |% n+ f7 z' w; W) zShutdown_priv行列,没有这样做的必要。)
& J8 d/ ^+ ?3 V" H% m. O
9 V$ K# h* Q7 Y# h3 g7 Q对数据库有关的请求(insert、update等等),服务器首先通过查找user表 % o" O4 ]& N8 {) L# O; r" O4 Y8 i
条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授
$ S3 g5 [+ N/ g# d; P, H( U5 z权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用 9 \& Z' c$ \: W6 t! [) E
户数据库权限: 9 \; M( n/ e0 R7 v1 f( A

, W* w# R; D7 @' |) u' S服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连
8 O; O; i+ R" q5 X/ b. G9 [! ~8 Q接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有
# K  `% W0 e4 m) [/ OHost和User的条目,存取被拒绝。
* J( B5 Q4 m0 q" N4 Y. d如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用
& I* m: ?; j2 t0 x, a+ a7 t- `户的数据库特定的权限。 8 F* c" k/ k$ K8 V5 ?8 G
如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被 : Q9 E' h9 g7 C$ C; ]
允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和
  _, v5 V( l" N7 Z2 k% W+ y: C3 qDb字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数 / o0 T' v9 y1 K6 ~
据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交
) Y/ w1 B# a# S" m+ a集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host : E7 A, f7 L. l- Z
表条目按一个主机一个主机为基础地有选择地限制它们。) 6 U, L2 v9 Z! D
在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
. z% B' v9 j- g# t由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服
6 E% t6 q. T" z- x务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到
2 _9 W  u2 k5 M3 w: T用户权限中。基于此结果允许或拒绝存取。
1 c5 Z/ O/ h% i- f. a1 S1 n2 P$ F/ E* ~
" H' \2 I8 p5 I' b. H) N% g( T用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结: # V0 D: W' n: r2 D

$ Y) i8 C/ N' g& i  s+ ?: I/ B2 ]# nglobal privileges
& E$ ?6 X- B5 Y6 j" BOR (database privileges AND host privileges) ! Z+ J1 J( I7 D
OR table privileges
9 _+ y" v7 H5 g5 q+ d5 e+ O/ Y3 s) hOR column privileges
/ q! e5 ~: A8 L1 f( J8 a$ Q. P+ w+ T9 o$ Q4 j1 `
它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不 / \7 k7 G. n) ]! ?8 N7 M4 L
够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能 + O( a% B0 N' B" n9 h
要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都
* J! u: s# \1 \# M( ?/ l! M要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 - Y7 a% v9 g1 W7 U
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把 4 N5 D7 R0 d2 @0 O; S5 T
两个表区别开来;两个条目授予的权限必须组合起来。 ' Q2 \) V# j  n+ W2 q% B: }. Q

* S! o* \& e5 d7 O  Z6 {host表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本 9 Q' ]# D! [, o7 p
地的网络上所有的机器的表,这些被授予所有的权限。
7 D8 s% S; m8 z2 L# m+ c( V# K- {/ E9 ^; r. b
你也可以使用host表指定不安全的主机。假定你有一台机器public.your. , L1 D" X+ E! O5 [" I4 p
domain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允 ; U& c* k$ Y! D( F  O1 I1 [
许除了那台机器外的网络上所有主机的存取: 8 H. e" g- m; G, x/ q8 i/ B
, {$ b! X# I5 I3 y

5 g4 h  s3 j7 c; V7 P+--------------------+----+- $ E6 {, M" l5 W, d+ C+ U* M/ B
│ Host │ Db │ ... ' P# }4 G: H, X- Z
+--------------------+----+- % Y( E3 ^& X! R3 }
│ public.your.domain │ % │ ... (所有权限设为 'N')
7 q5 F' [* S+ g1 Y( y) V( s; s│ %.your.domain │ % │ ... (所有权限设为 'Y')
$ Z1 a" q, f( s8 @. ~9 X+--------------------+----+- $ d1 e; r, h0 e8 n/ V5 X: B

% K$ b4 W1 j- \; U. V6 M当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保
9 I. J2 F# e: r: h9 ~# i% a你的存取权限实际上以你认为的方式被设置。
1 z" R# r5 E. g2 m
. U  p% U" k# t6 T1 c2 f% x权限更改何时生效 6 {- {& l# M. m0 H) |, Q/ H3 l3 A: x# t
当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。
$ V9 R3 d- D1 M+ v: L& n) p
8 q2 k. {$ p0 J6 p# v用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。 8 F$ m. ~5 R# Y# q% k0 O) i

2 T' ^- H/ f* k$ l7 l  d  W# K如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH
5 M" _8 n5 Z$ JPRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否
( b( H1 Y8 T! W1 g! W, O则你的改变将不生效,除非你重启服务器。
' ^6 s$ x* N5 x  |* u: T0 e6 J4 F
7 u( t8 c: M9 \" \0 b& x1 p4 H当服务器注意到授权表被改变了时,现存的客户连接有如下影响: - E$ J7 D, y7 d' i! B" s. H
: Z* X' n# _9 K3 w2 T3 ?
表和列权限在客户的下一次请求时生效。
& l; I2 L9 L& U$ ^4 C数据库权限改变在下一个USE db_name命令生效。 + y; s0 m# ?" l& l/ f% N
全局权限的改变和口令改变在下一次客户连接时生效。 1 Z, A9 H9 P7 j* n
5 T6 |* V% ^4 I. n  J" y
建立初始的MySQL权限
5 T: p7 J$ V8 |& A在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。
( b+ {0 Y2 l2 P# W6 gscripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列
/ W6 }  W* K$ ]2 e+ D$ L权限集合:
$ C9 p! M- Y8 T# W4 u0 N+ J: x: |7 p7 x6 |
MySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主
, d  L# v, O+ v, S3 u, R9 U机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行
7 z1 y$ [! a9 g5 N# d1 g+ W8 K$ |连接并且被授予所有权限。 * z  D$ c3 t$ ]# ]* K  |9 u
一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库
5 k0 r- j1 P0 v+ M; @: V8 D9 g做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视 6 z6 z4 U& u1 r
为匿名用户。
' t3 S& |" J  u  P* c2 _' o0 X其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或 7 x  c* V1 G% j9 h9 f* f9 m
mysqladmin processlist。 ' {9 W2 K' i& @$ V5 \" W  q* E
注意:对Win32的初始权限是不同的。
4 i! X5 ~0 |3 i) q( u! I( I1 Q) @% Q3 \: E9 Q: H
既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户
2 f: g7 X9 u( b1 w6 B指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令):
  }4 \2 W( b$ L- }$ T' P8 Z
6 `0 R) v6 H$ A7 xshell> mysql -u root mysql
1 v4 w9 m8 c3 j! Y& D  qmysql> UPDATE user SET Password=PASSWORD('new_password')
2 q% U1 o* Q- k  p  t/ dWHERE user='root';
/ \5 s# \; _% T5 l3 M# Amysql> FLUSH PRIVILEGES;
5 E/ M) y9 {: g) F2 n5 [) R/ D9 \$ s: I& |
在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句: , e) \$ T9 W, ~$ ^& H8 l

4 o: a5 ^' y" p8 lshell> mysql -u root mysql % H8 M& H% r5 ^$ C0 \
mysql> SET PASSWORD FOR root=PASSWORD('new_password');
& T4 i6 N& Q/ p" m) O/ s1 ?/ p
* r  B# ?8 j% o8 V' [  G设置口令的另一种方法是使用mysqladmin命令:
) @( |8 y' m/ u% A
8 [% b$ N. z# Y5 t# wshell> mysqladmin -u root password new_password
6 i4 O6 z. O( h7 G. m  U" G) @( w* Z. }1 ?) K) i9 ?
注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器 3 v# O( j. |7 v, Q: L
再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。
1 {2 i' o1 n" ]4 ~$ z+ H, K) R" m9 L) d" i- H
一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个 1 v: r$ D+ w8 |; M+ U
口令。 ( t4 ^3 w9 E# d7 w
- C6 `# p8 m& h, a# ?! q7 N
你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它
; I5 J. Q3 K# R或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。
1 C+ z0 e" G* @* A9 q) P% u( k5 k3 H, q5 ^$ t& f
看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它
4 _5 D8 S2 l5 m, H  T  [& y) j作为一个研究如何增加其他用户的基础。 1 ^; @5 T( R/ w( N+ s' [

1 H. v( h, Y7 E' Z0 C如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db
4 Y7 J( I; B" C之前,你可以修改它。
# C! X4 [* Z  e8 p1 _* K- Y" w+ Y2 b  x6 M; |7 a$ U" W
为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”,
1 ]% ?- G$ t- R7 Z5 |% a- f; T“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,
0 K- D0 z2 S1 l# m当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能 & u1 m  H, ^  ^* b
在首先编辑它拥有你想要的权限之后。
5 q6 s, f; X/ f0 z3 j
- j+ m( A, g3 V) o: Q注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果
3 w& x- K% V- N+ H/ R* Y你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。 % E( a/ v+ X# L+ ~- s0 o0 D) l
! x9 \  }4 \4 i( y  l
向MySQL增加新用户权限
: Y& G; q+ Z, N; n5 W4 b你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授 4 H  V6 W/ `6 G- ]3 |
权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。
9 Y( j8 H4 ?3 a3 R+ z! p  k' R& u9 u8 r( p# r
下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前
0 g5 B$ [) ^4 W; A. y2 m) t的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台
, h7 L7 V7 G: F: [: N0 z机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有
0 A6 _0 ?. Y! w5 w* Oinsert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下
$ T6 o) P% Q5 [, T的mysql命令指定它。 - e" W* ^; ?3 ]" C/ ?: r

* O6 l& n9 Z0 S* p4 |4 a' C你可以通过发出GRANT语句增加新用户: ( ^1 m9 O! |, p, t2 x
4 H2 |0 h( s8 H# ^) W
shell> mysql --user=root mysql ' ]) a4 S5 A! ~4 b0 a% j( D# B$ b
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost 4 d& Y2 P2 ^' C( a8 m' g# X
IDENTIFIED BY 'something' WITH GRANT OPTION; * ^' ?6 Y; S* E
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%" 2 H) u3 l/ Z6 ~, c7 W" }
IDENTIFIED BY 'something' WITH GRANT OPTION;
" w1 A' r3 e& p! I. Q; [7 Vmysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; 4 n/ m- U; }4 a" ?2 h
mysql> GRANT USAGE ON *.* TO dummy@localhost;
7 [% S. G* G5 E* K
$ j! n$ X+ N$ _% P4 h这些GRANT语句安装3个新用户: ! Z1 s2 N  t7 l' q- w2 s

1 I" c, F3 t4 `! Qmonty
" V# x; V, ~- k: a可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个
* [9 {4 \6 ~8 P4 c& ^/ E口令('something'做这个。注意,我们必须对monty@localhost和monty@"%" 1 N6 C. O7 ?7 Q
发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
' Q$ C$ s6 n' p: G* _在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为 2 \! y: {: \1 b9 C( [8 p( j$ a
它有更特定的Host字段值,所以以user表排列顺序看更早到来。 # |  Y3 Z) l7 O
admin
& a5 V' u/ C: t7 T1 j7 w, q可以从localhost没有一个口令进行连接并且被授予reload和process管理
7 V$ q. v* K8 [$ y% ]2 c; q) h权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和
* [2 k4 U  y1 Q# g' ?mysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有 - {0 ]) T. ?4 S; r8 L4 i, b) ?
关的权限。他们能在以后通过发出另一个GRANT语句授权。 2 Z0 s  B' W" Q  M2 P
dummy
' k: M/ _$ k. U; }8 v8 r( A1 ^( [4 |可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设 / Y  r5 R8 u8 y
置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以
: M5 n# y1 j: F7 ]0 [后授予数据库相关的权限。
2 R& J1 }, t4 {5 E8 O( {你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服
/ C' C8 _0 B& d1 B$ v8 [务器再次装入授权表: 4 @5 t" @" v/ ?3 P$ `

- @8 \- M' O, e. Q6 o# ^shell> mysql --user=root mysql
. N  R9 ]1 b: p2 l- V$ C+ Q  ~; Rmysql> INSERT INTO user VALUES('localhost','monty',PASSWORD 5 d* C* |: \6 B* m/ N
('something'), : E4 p9 m! U4 u, W
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', 7 \' V8 T) J8 z# c/ n  X
'Y','Y')
& q% C% t/ I) C- l& G; T1 q  Nmysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'), + `3 @7 M# F1 ^/ a' J& _# Y
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
5 j) A# ?9 n/ n( P* _$ _'Y')
% D5 c! b2 M# Kmysql> INSERT INTO user SET Host='localhost',User='admin',
) F, F  \7 \: @* ZReload_priv='Y', Process_priv='Y';
% A/ O6 T" y0 C. s# ~1 d/ [4 i" Umysql> INSERT INTO user (Host,User,Password)
8 ?! q! _, G5 B: `VALUES('localhost','dummy','');
3 N2 a8 V( V. X1 i2 Q1 x9 Amysql> FLUSH PRIVILEGES;
$ j# G! H( M% q# I9 Y+ I8 b0 {2 E+ D# x5 t
取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
8 r  a) Y, q* H' M' F3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版
$ Y4 m2 x( b: }" E' _( J( ~本具有的更加可读的INSERT扩充的语法。
5 `# M, f3 ^- R4 Y3 c
6 Q+ {; \, L5 q& g6 o. g! u注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为
. C3 u' s' f" ~'Y'。不需要db或host表的条目。
0 ?- C2 z  L6 v" W; |7 j1 ?! t& |( j, V' b& w* M/ o
在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户),
  b; g, T( Q) z  e$ C" A- z因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
! K+ R" ?8 ?# W& S- e
0 K; i* Q/ H: {下列例子增加一个用户custom,他能从主机localhost、server.domain和
. y) R9 g( ^8 A+ nwhitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从 7 L/ ?; V+ n4 |, ~0 T/ V  A
whitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他
. L, S; |" G, N2 D* c% f' H, G" b想要从所有3台主机上使用口令stupid。 ( p1 f+ W9 p4 k1 n$ p/ j: y

: ?, }6 T# [, O* A8 U7 @$ h为了使用GRANT语句设置个用户的权限,运行这些命令: 2 h5 q* r- m' S1 `

% k/ F7 P: o- i1 t' c3 U- cshell> mysql --user=root mysql / H2 m/ W/ Z7 {: K1 e, D
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP # |* P& c1 ~8 M) l7 f' e3 p
ON bankaccount.*   R: d1 H% F4 S; Z3 h
TO custom@localhost * q/ u, X- I$ H9 V! S" C- x" m
IDENTIFIED BY 'stupid'; # d% X" U- N- i/ E
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
6 [! i6 E* }0 I: aON expenses.*
9 N' v! ~8 t: y+ s0 {( ITO custom@whitehouse.gov
2 C4 e3 E: m4 [0 g! m( r6 rIDENTIFIED BY 'stupid';
# W4 l( l2 C- o/ f, H% emysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP 0 a, j3 G8 p: W; S0 t
ON customer.* # k; L; ^) \: k6 }* Q+ Y6 c- A
TO custom@'%' - J; |- a( y) t- b6 ]
IDENTIFIED BY 'stupid'; 5 {* }: T) Y) P' |) G1 d' i6 Q

5 B9 l, P9 K2 ?& S' {8 i+ r7 E通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时 , o# c# ~" Y" }3 g! P
FLUSH PRIVILEGES): & S, d6 e) ]6 b) m+ ?
6 b3 U- G3 T3 `  I6 f# ~. }% K3 u  D, l
shell> mysql --user=root mysql
3 m, [9 S" K  C( E. bmysql> INSERT INTO user (Host,User,Password) # C, N% K5 [5 f- @% z- z
VALUES('localhost','custom',PASSWORD('stupid')); 7 ]6 p8 i+ }2 R6 @. \2 Z" l6 X
mysql> INSERT INTO user (Host,User,Password)
, b( L; ~. [+ nVALUES('server.domain','custom',PASSWORD('stupid'));
# v! a$ u1 B7 I  s1 Imysql> INSERT INTO user (Host,User,Password) 7 `2 K$ C* g5 ?% a/ l) v+ E: \
VALUES('whitehouse.gov','custom',PASSWORD('stupid')); , ]0 x- A& V( S5 q% O
mysql> INSERT INTO db / s2 A! p  Q: g
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, ; u4 w  m: Z% Q8 F) ^" {- q* R
Create_priv,Drop_priv)
: f) Y+ A! {/ Q- d! S& ]3 uVALUES 5 m$ _/ M% b+ R: w" V' F
('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y'); - K, F: N( I% i- {
mysql> INSERT INTO db ; i3 Y3 r9 X5 ~* M' ]
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, " X) Q# _5 }9 c1 {
Create_priv,Drop_priv) 3 ]& y  n. x% X4 H7 |
VALUES 5 |, y; V  X% j0 V( [. \
('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y'); $ _0 u! |! r( T. [* l' _& @
mysql> INSERT INTO db
4 m+ r* N& f1 |(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
& z8 p( T, \; g8 B+ kCreate_priv,Drop_priv) 0 H0 V) U- {- M0 m2 ?0 Q9 \
VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y');
4 G( H' U8 B8 ^  ?6 C4 bmysql> FLUSH PRIVILEGES; 7 T5 I- v% {5 @/ r$ N5 G

6 i; S" Z" Y/ Q; ?5 @' Y头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机   d, ]3 b) t0 o6 z, D0 J
进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT 7 f4 a  o+ f, W0 c% G
语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限,
& o* n" |4 v' \9 c但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告 0 Y4 N6 j" K4 i4 _- L3 L
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。 0 Q6 {, Q0 u+ ~9 j% h, d$ X
4 E$ W1 o& b. H' v( [% m2 j/ p- ]0 n
如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发
& }( c3 B. q! U! V& ~7 c出一个如下的GRANT语句:
" B7 ^3 ]- D  D1 y+ x
# d% M- k8 F+ X/ \2 X5 cmysql> GRANT ...
- g$ t. q, ]% P! DON *.*
3 [! b! k/ d6 t2 n* d: N9 b8 |TO myusername@"%.mydomainname.com" 8 L. U9 G. b; j$ ^" U3 i4 J
IDENTIFIED BY 'mypassword'; ' r; w3 w+ y0 Q5 n) d/ r/ `
  ~3 C6 o( J0 R; k& d2 D
为了通过直接修改授权表做同样的事情,这样做:
" b4 s. i! [; A# [6 A: e: T: W. z: P/ |6 a- Q  y
mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername',
" M' a0 a2 W9 T6 r2 BPASSWORD('mypassword'),...);
; f0 m) e0 m" s1 `/ F- Kmysql> FLUSH PRIVILEGES; 8 J: E* J+ ~7 V. j" a" d- j2 h

; L9 \" L6 |$ x& [你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变 4 Z# o+ }' ?8 k- D. }) W
和更新值。你可以在MySQL的Contrib目录找到这些实用程序。
0 U9 v  ]0 ^8 j4 \: L/ L! R% f* K# t  a2 O" t
怎样设置口令
$ ?1 _! ]; C- I" [5 s在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存
/ X7 O/ i# L8 n) f储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以
/ O. [2 C( J: L加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图 / \- Y. M2 F. g8 C- Y# G
设置口令:
4 T7 ?- Z0 k% U& Z) K% I3 a' q) B
shell> mysql -u root mysql
3 d5 S9 W6 u) i; e' p/ o' Cmysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey', 8 j2 b0 Q% ?0 `
'biscuit'); " w, H& n, A* i' U2 X6 I  U
mysql> FLUSH PRIVILEGES
1 x. _) X" C: q( ]9 m0 P! Z+ n, j1 Q+ E% r  {$ h
结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用 - b9 {7 L3 U/ K8 z/ M- K
这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服 / L& V, d+ F' R3 o
务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是 5 A) M0 r  E! `0 |4 t
'biscuit'),比较失败并且服务器拒绝连接: & r0 x$ r0 d/ y" \+ o% Y
/ A  j4 e" ]( g; r
shell> mysql -u jeffrey -pbiscuit test
! X! q2 k1 O3 UAccess denied 2 _+ H5 d9 m& p4 y- }( C
/ w# I( [& L& i" z8 i! ^; `7 f
因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样
: d* R7 C. D6 R* b/ i5 p被指定: ; o& Q7 F- U& O( f
# M5 O6 S% ^. p2 T
mysql> INSERT INTO user (Host,User,Password) ; t1 c1 l  H) N, F
VALUES('%','jeffrey',PASSWORD('biscuit')); " P* ~! ]' U* H

: J1 `+ x) M$ }5 t+ o1 n+ X当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数: ' q0 s% H. l/ _. E, E& g

- P$ {% ]6 t6 W* K1 d4 x; M' qmysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
& l5 ]- m& y. B* w$ S- {/ I
4 G! s5 z6 `% _2 K- @. s3 O如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口 6 `' F! S8 p; G2 ?5 Z
令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指
, c5 s3 p6 ^* t% e定一个口令'biscuit':
# c) U1 v! ~2 K. |8 r# J
+ T2 _+ ?+ K" m' ?  W5 lmysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
& _, I8 U& P+ m: B- q/ [, t( p8 l* z( k7 \. x9 }. b! @

% ~2 y! T  [- D6 g2 a) D( }( |( w0 M! _2 I$ ?
shell> mysqladmin -u jeffrey password biscuit
. g& W0 k: g0 u# t注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应
5 p2 B, ^) u! L' V! M% U该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix 8 m  b6 N% }$ d) ]1 X* V! d6 V; k
口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。 , X1 U- d' E5 Q' L& Q
& F! ]2 F# O0 e% D- N
Access denied错误的原因 3 w8 Q" r# i/ r$ l1 w
当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 / _. Z2 Y, j" }2 M5 o' T
的表指出一些你能用来更正这个问题的动作:
2 u* L6 v5 m* K: [1 }1 [( N  p& z4 @- q8 p3 m( ]
你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容 5 i" b8 Q2 W  o! U9 {
吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初
' V; m0 ?4 \$ S& b. a1 O始权限: , P' }6 |9 M- y: C
shell> mysql -u root test
1 h5 {: L$ |- a3 i4 z$ r0 D
) ?( K; R0 T5 c9 I* y服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件
- Z9 y* R# g' T" d( k“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安 2 j9 N9 e6 z4 T% F
装根目录的路径。
, R1 ~, o8 L% G) @0 `" P
, S- |4 @* E; S% ^  K9 r在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
$ f& f- _8 b" |7 z$ z& @6 Oshell> mysql -u root mysql
8 z- f: F# g8 ?4 r3 i9 b: k' N# }, j/ i9 b$ p
服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个
' b9 p% A% R* s6 d3 M# k安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如
4 K7 _  W0 v1 \& \+ g" y# R* ]3 [果你作为root尝试连接并且得到这个错误:
1 j% T. \( p5 H  Z
; K6 @* t( W; a- O$ VAccess denied for user: '@unknown' to database mysql % `5 v' p& w0 D

6 ^* T; @: o+ {" A+ A1 I这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld . F% g, G% h  b/ i
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项
- Z1 o; u5 D; n4 u  b- O' M重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机
0 X8 F$ M" x6 Y6 G; u. |增加一个条目。 9 v6 F. J4 d& e3 T; k6 t

3 Z; b2 `, \0 g" O如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以   e& L5 Y! _0 }* ?$ X2 H* ?$ f
后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在 # q9 I9 C: M# E+ w( d
GRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。 : G) y, H* s3 [9 x  ~, L2 W4 S) D
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被
) f/ `; p9 w/ X. V! y2 ]- U忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin
; ]* j& q  E6 U( }2 Q$ bflush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被 3 B4 R. \, b. l/ {: H6 s* j* }( W
重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗
! b' O* ^2 D& g' J: d(flush)权限以后,因为服务器仍然不会知道你改变了口令!   _1 M6 g$ W6 ]
如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变
2 [# ~* h+ k1 b! [- W  m$ Q( j/ f/ _了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权
" w& F. P+ x0 e4 i! m# s9 @限改变何时生效小节所述。 $ z4 I; U( U, c  n) D: R
为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变 " C2 Q  c6 R' D! J0 |/ h
MySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的
0 ?- V" X: C# M改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权 5 r( w  R0 K4 o+ T# z
限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务 - y' E4 a; ]( ~$ _$ `$ f; ~- C
器开始使用授权表,而不用停掉并重启它。 5 _- C6 u. T; c1 [  c/ N4 t! J
如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name 1 q: i1 N/ I7 i  M' Q, E' H
db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用 ( y- c/ K& D% N; k8 t# f2 R, b# E
mysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令 - Y. D" }5 T& @/ _, T4 \
之间没有空格;你也能使用--password=your_pass句法指定口令。)
' d' V/ ?* I1 L8 O* ~& A如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句
3 V, q% Y1 v' F$ H+ K  q设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语
" U( e+ ]% ?) `句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。
! E( i/ D% B5 P4 p* @7 Xlocalhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 ( l) U1 V6 Y( h1 G/ @
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系 : [  E3 Y+ |- R, G+ F
统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT ! ]$ _* S9 d1 H4 @6 R7 O
-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确
: e" ^- r1 e; p3 C7 j- e; _4 `/ W% p地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你 5 P+ e& S* @' Z# b
必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一 * Y8 c; F& t( j
台的主机上运行一个客户程序,这也是真的。) " K$ t" {/ G# q3 L$ ^
当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个 $ V. R* l/ b; A
Access denied错误,你可能有与user桌有关的问题,通过执行mysql -u root % G6 I) e) [; A  @
mysql并且发出下面的SQL语句检查: : T( Y/ [$ G( U
mysql> SELECT * FROM user; & Q8 a( ~* d- p' ^1 o9 g

2 }2 Z5 }; K9 ?' X2 X/ t结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户 2 C" {1 L% o7 V  E% t. V; L
名。
5 t' B, I* w: ]1 `  p1 O' d/ d2 I$ y* F1 O5 N- D
Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图
; ]! J! R( Q* c8 k, F9 U用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一
9 k/ m: ?5 u0 W- \& M5 I个条目,正确地匹配在错误消息给出的主机名和用户名。
7 [  g" @4 {6 I如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列 # X5 }1 m- ?7 G. e3 `9 R7 ?; s( c
错误,那么在user表中没有匹配那台主机行: / t& T: g- s; @# D2 f. d
Host ... is not allowed to connect to this MySQL server ) b3 ~0 u% ^+ y9 [8 ?
6 k- m  D+ L7 w1 j* Q# R$ R4 N
你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试
# W+ e; w- u# b; a9 P" E, Z图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
! u/ e) K7 t4 i4 k你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为 9 S# e9 W5 B8 _7 b9 Y
Host列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从 8 c0 k) W. _& G0 x5 U
客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。(
: [# d% z! a6 `# x$ b4 q# ~1 c+ U然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则,
8 e# y6 i7 H- r你将有一个不安全的系统。) $ _2 h) F) l2 g
' q7 O" H8 j" t0 B: R
如果mysql -u root test工作但是mysql -h your_hostname -u root test
+ P7 [& ?& Z* A( a& e7 r! I导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的 5 a3 B# {( ?, h0 x; v3 o4 _6 `
一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统 5 A8 {6 P! E3 R
的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有 # O: r; C) b. r9 @7 G
一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet.
8 Z, R2 \" U& z  I2 G# X! X) zse',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作
  J- M! S4 V" T为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符 ' m8 L& h3 r. e2 x2 y  G6 o
如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)   @' Y' I2 @' Z9 S8 i
如果mysql -u user_name test工作但是mysql -u user_name other_db_name
/ {! X2 r; I/ Y6 _; j+ k. h不工作,对other_db_name,你在db表中没有没有一个条目列出。 - ?; C* |" o* ^1 B) a% t
当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其
% y6 G& f7 h* Y它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
  B4 N: n6 s. H) D0 H你没有把客户机器列在user表或db表中。
  _7 x1 G, E8 w& Q7 i( X/ A如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host
4 S$ z1 p: C  I" o/ H4 q; a" @包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用 , \. f5 _2 D, Q* a0 d9 b
Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost
# H) x/ b, K3 {2 I# |1 r从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost'
6 Z6 P/ D( A% V2 x. @1 Z和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从 3 {6 c& z4 Q+ B( K+ d4 J& s  d. i2 r
localhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和 5 e$ x/ G3 M0 O8 n4 ~$ R
User='some_user'的第2个条目,或删除Host='localhost'和User=''条目。 , |& @8 l) t) P! J1 C5 }, K
如果你得到下列错误,你可以有一个与db或host表有关的问题:
' X/ z! N7 z0 P( A+ P6 d5 jAccess to database denied
2 C  t1 a1 I. O5 H. v. A/ V( ^
' s# p* X6 \% K4 Q% c如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多 % R0 a0 J1 g' P! P( G
个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ...
. ~. c; R+ o% R0 y+ h3 w) N3 Q/ DINTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可 ' }/ l2 I. l0 J+ ^) A& f, `- s
能启用file权限。 % P  C5 u) g* y) v6 d
% v6 q$ C# v4 {7 c, \/ W
记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果 4 M0 P* S- _3 ^* X
当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,
9 Z" F' g# [% _1 k& m检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围
2 @- J& G6 A8 b2 J" b2 W6 O* r" a4 o的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当
0 r6 @. j) p3 r; A# p你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选
  O) {; ^: q8 D& X" m项文件里指定一个旧的口令!见4.15.4 选项文件。
' E  r' P- V5 g" k, t0 G如果任何其它事情失败,用调试选项(例如,--debug=d,general,query) 5 m6 p3 k: H# A  k
启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每
- b7 z1 {: |/ C! D, k' n( C个命令的信息。见G.1 调试一个MySQL服务器。
- q7 [% D2 A8 Q3 {如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 * ^+ g, S# b9 c/ v2 ~* y# q, Z
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump
/ _/ J- i' ]3 Y" l: K  o4 p' rmysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一 / f* F; U! n* O
些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。 ( Q" P3 o! ]' y* q3 |# J3 W* H- y
怎样使MySQL安全以对抗解密高手
, x. ^0 N; ]5 w0 ~, }7 W当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文 * J  O0 A6 q+ }3 U' ?
在连接上传输。
# t; c5 w# c: f/ z9 ~) O; W: o' y( N- ]! t/ m- D! o
所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可
: v2 I# S7 i( d1 b% a: J使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全
! C! T. Q) j, d+ |1 G,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服 ) Z. b: ?. z* s! O  f
务器与一个MySQL客户之间得到一个加密的TCP/IP连接。
7 X& r9 P7 P, R$ H5 N# I; b# P* r9 v. H& y  R% @
为了使一个MySQL系统安全,强烈要求你考虑下列建议: / u& o3 [( q+ W$ t( i% X
4 Z: r+ w8 r& X' P* X# ]# w$ |
对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简
; b1 f$ W" ^( ^: r( R' ?单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器
. j4 x3 b# R7 U) I应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通 9 c& B5 Z4 @" Y4 S. D
过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令, 2 Y1 A( v7 @4 {1 c- H
象这样: 3 Z; p1 w0 F) r: J5 I3 P& n
shell> mysql -u root mysql 0 ]; z2 [3 d0 P% v8 t" s
mysql> UPDATE user SET Password=PASSWORD('new_password')
4 [0 y# P0 I" _" J& \! I+ n$ `# JWHERE user='root';
% h- c8 e1 V1 c' y$ Emysql> FLUSH PRIVILEGES; 6 L# {3 w) k; l4 g6 V+ S
- \" s$ s9 X' v) K4 Q3 W# y
不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行,
$ Q! n" W1 h) A+ {你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户
% f. y2 E$ z  ~; y. I运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix ) e+ ~' X8 f" @$ H
用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。 # |5 l8 [3 R" `6 Z0 L( r
通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行
' b$ y% s" I% \: K0 F2 I/ V" U. ~! NMySQL。 / ]- I4 g; G3 h& H
如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本
8 `0 d7 P! B2 g: @只能对root是可读的。 . P3 j% _7 J. f9 L
检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用 ; y$ g, V  e% V$ F
户。 , `9 v1 x0 \4 R6 C
不要把process权限给所有用户。mysqladmin processlist的输出显示出当
$ R/ I5 I- A' F+ s" L! W: H前执行的查询正文,如果另外的用户发出一个UPDATE user SET password=   |- p3 \& b$ `1 ]
PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。 1 \  q( U! x- p  V3 u4 |) B
mysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用 ! M) a" J1 j% x" j; n
户能登录并检查,即使所有的正常连接在使用。 7 Y5 P* J- `+ d/ b$ ]
不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护 ! y% A4 w4 Z* ^1 [' {" y4 {
进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ... / x+ R5 J* H* Q& [
INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 ( l* j2 e$ ^2 x6 B/ m
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文 ( g7 d* m9 v5 X2 T& a" \' i
件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数 # L6 x& R0 `7 c6 M7 J
据库表,然后它能用SELECT被读入。
' R6 P( A2 O1 K8 ]% p如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则
7 E6 [' F0 x* l' U9 x上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常
& h5 G  g) @1 r9 J4 O  ^, Q小心地使用包含通配符的主机名! ) W, D* E. m9 C  }
下列mysqld选项影响安全:
" o5 m0 \. n" Q) m& X
" v4 H) n, h6 m5 C( v; b/ x# k/ P2 f--secure
8 {4 m7 r' w. K' `. L- i由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来 / U2 `+ C2 Q! v8 {8 b
的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也 . p5 g; O8 B) N! h, k1 T
增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
- s6 h* v/ A  e3 v/ `( g它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。
5 D1 G) d3 S* O' f/ d& N--skip-grant-tables
( v$ X) u4 V" g1 u' ~- }这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数
* t/ U/ N0 T: F: H8 }8 X据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器 8 R/ I/ D, q" q1 n
再次开始使用授权表。)
& n- g$ ~' n; k4 a* T--skip-name-resolve + j: U3 w- N( f* ?$ c
主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。 ) A/ _$ m/ N% ]& s$ ~) g
--skip-networking
% F: s3 E3 t. @在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
# ~  J' R/ m  w1 C- w0 E行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不 * p# {/ R( Y% S2 U* y( n. b
支持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 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。% ?/ A" K) S' c! B* V3 r
汗。。7 F1 R0 C  w3 O- \/ G0 ~9 K8 \
水平不够,消化不了。。
5 c1 y- n& ]8 n不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

本版积分规则

关闭

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

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