下沙论坛

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

QQ登录

QQ登录

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

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。
; Q1 ?, l6 x8 A, `9 A  L& W3 }* E9 z( N$ u: i: T
权限系统做什么
; `. i9 {* J0 ~MySQL权限系统的主要功能是证实连接到一台给定主机的一个用户,
0 z9 u7 v% H8 p+ ~并且赋予该用户在一个数据库上select、 insert、update和delete的
' w$ Y- L6 g) b  c权限。
4 A; ?6 e+ j+ y4 P2 b& B! F5 L- b
附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如
4 f9 v! w9 q* ~LOAD DATA INFILE进行授权及管理操作的能力。 ! E1 x4 U/ R% q* @2 |
% ^; C, v9 k( Q- q
MySQL 用户名和口令 1 L$ z5 t* T8 \
由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很
6 X  W/ o" {; J0 e/ n多不同之处:
- F6 z0 q- Z9 g# g: F% B- h' Y! ]) D/ ~
MySQL使用于认证目的的用户名,与Unix用户名(登录名字)或 4 x9 K$ l7 w% d8 d$ ]# d8 m; ?
Windows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户 / V3 k9 B% `2 a, D
名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或-
% I8 l# y9 I' P-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据
% F: m9 z9 X5 x) _4 ~) J库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名 4 ]& [- d& [+ ]7 l9 ~1 y. H* ^
字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。 ; a+ q7 ?0 R  Z$ @
MySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。 4 _7 M) p" l& I5 ]8 a% t* P
MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使
4 ^- o+ A* L& w; F$ b用在那台机器上存取一个数据库的口令之间没有必要有关联。
  m  r! f2 F! f. c# _1 N7 C- m( |, iMySQL加密口令使用了一个Unix登录期间所用的不同算法。
7 Y5 Y' k/ N  Z2 K. s9 M# U% B
  r$ P1 R4 S8 i8 L) ^& [7 I4 Y与MySQL服务器连接 8 G9 `3 M  J$ ^" D2 D  t6 g9 e! W
当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定
( Q% {  U& {$ {( o/ w' v4 {连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql
/ T) H2 m* I, z客户可以象这样启动(可选的参数被包括在“[”和“]”之间): 9 E! @0 J# Y& n; }& V
0 p0 I$ o2 O3 o0 L3 E2 f
shell> mysql [-h host_name][-u user_name][-pyour_pass ] 6 x4 r3 c8 [- M  B5 X) Y4 e4 Z
-h, -u和-p选项的另一种形式是--host=host_name、--user=
& I% g' }- w9 k. g  \: X0 I- kuser_name和--password=your_pass。注意在-p或--password=与跟随它 2 ?, G$ j/ i; X/ `/ m1 l
后面的口令之间没有空格。 8 x- z3 u$ L4 k3 h  n
/ c# }) C5 p  l0 |) V5 p; w
注意:在命令行上指定一个口令是不安全的!随后在你系统上的任
0 L. T+ D* \/ P何用户可以通过打类似这样的命令发现你的口令:ps auxww。
5 D" p( J+ D) R- b; J( w% R6 r* X/ D6 T0 u7 Q" ^! G7 t" b- ^
对于命令行没有的联接参数,mysql使用缺省值:
& X4 k8 A2 @% J. D. ~
; \8 j/ v7 d$ g缺省主机名是localhost。
6 O  d/ _6 l5 x- e$ o9 k% G缺省用户名是你的Unix登录名。
4 z4 h, R9 J; d" Q1 M: I: _如果没有-p,则没有提供口令。
* B1 a' I9 P. U, t# |2 h这样, 对一个Unix用户joe,下列命令是等价的: , {& }! f1 y5 m8 U" q/ Q7 Q
. K- E% S2 M: t, l2 M: l6 g
shell>mysql -h localhost -u joe 4 T7 d$ e- X* z( F8 E& |, a1 C* B1 u
shell>mysql -h localhost 0 {( |0 v" a. W# _3 [& p# D. c
shell>mysql -u joe
: d7 r4 y/ }8 P. P) }$ a7 N" oshell>mysql
9 `4 p. g. X, X( T! m6 C
9 K2 T6 r) k  c2 L6 r: _4 q/ a其它MySQL客户程序有同样表现。 4 Y' j& \1 i3 z) q
) a, s" i) Y8 M) L9 e
在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺 5 f. Q  z- }" @( C* [8 I! m# a& A
省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这
, r+ k% v6 R0 M& [可以有很多方法做到:
7 P: H! s( V& c$ w# a' I! m) a, V' m  R7 D
你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定
& r+ t7 }, |2 M) Z; x% E3 R连接参数。文件的相关小节看上去可能像这样:
" F1 X& C1 w+ J2 ][client]
( g. |5 ?4 e! N- m! qhost=host_name 6 y! u0 V: {0 T! O& u
user=user_name " {6 L/ R3 Q! d3 F. ^
password=your_pass " i) x. b# t4 y

3 d9 k4 X$ t& P" {9 W你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL
  X% D! t5 |3 R+ ]用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是 . {& {& u# ^' m% v
这不安全) 。
* _" c3 \2 C+ _8 g1 \* |% p& y如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配
  A( W* S  o+ i& V) E0 w5 i置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量
+ f. P" @) m( d3 Y4 t指定的值。
1 Y: a' |. w- Y/ w# `* [+ [, {6 {" D1 \( ~" m
使你的口令安全
6 U: w, h3 r2 H* }以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。
8 L% M* J9 W6 U5 K# N当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法
  ^5 ?- _0 l5 O/ _( z3 y的风险评估:
9 L7 l; j. X3 Z( |4 h, \8 c! \( ]1 p; d6 s% N8 r
使用一个在命令行上-pyour_pass或--password=your_pass的选项。
* E2 k  M& i$ `% [这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见,
! n: e; ]; T2 D它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化 6 G) f( |8 F- }! E2 h* C. w
顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可
' [: a! d1 ^4 x8 L+ h5 B' F% }见的。)
  z& ?( V! a2 ?' }" d使用一个-p或--password选项(没有指定your_pass值)。在这种情况
( f& m# x& c% g7 N0 Q2 [' [- M/ D下,客户程序请求来自终端的口令:
( g7 m/ i: F9 J9 G
6 b+ C, G' i5 }, ^9 z/ j5 Xshell>mysql - u user_name - p
! P, s8 b0 l5 h2 ^# o  @Enter password: ********
" T% B; ]1 L3 v5 I, z. E, q+ i6 o% c0 N6 B1 \% }
客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见 2 H& B' k8 X! `" H. P
它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你 ! D$ @. q! i' y1 o: _% h0 f
的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程
( m. b# w. y( @/ @. h7 ^3 l; S序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就 . _- t" h9 n  ?6 Y' `3 k; T
没有从终端输入入口令的机会。 * w+ ]0 Y: K/ L0 {

' t7 Q) Y7 m( H7 D" M在一个配置文件中存储你的口令。例如,你可你的主目录的 # d# J& @9 {- Y& \
“.my.cnf”文件中的[client]节列出你的口令:
5 d5 w% I0 Y% c[client] - {+ i. X$ b* a5 S
password=your_pass
' V4 M7 K' r" q/ v
# R" g( H; b! i, c* L7 f& d如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或
, L& z+ d8 w3 Q3 g% P可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。 8 _3 j& g1 T2 s/ _( g( d3 F& `
# }/ |1 T0 E; [/ ]
你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极
, P' ]- D5 M8 i1 g: e" O$ S+ @不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项; 9 c2 y2 C6 K/ L8 R; F# V( l0 s
如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有
+ z6 @3 |* X. z+ a( x7 S" k( d这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智
3 X- a, c7 V1 [$ C8 e的。
( V0 b  ~( O  k, B1 N6 g总之,最安全的方法是让客户程序提示口令或在一个适当保护的“ & r5 ~' i1 E3 I, H: H; P8 p0 |
.my.cnf”文件中指定口令。 ; c2 G7 d1 a- x3 a3 \2 l' a1 [
. d5 C6 j- t: _9 l: e- A
MySQL提供的权限 & r6 n0 B5 ?6 e' C# u
权限信息用user、db、host、tables_priv和columns_priv表被存储 9 C" P% d" a/ R3 i! {
在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限 0 S$ T# S( Q: M' L* f
修改何时生效所说的情况时,服务器读入这些数据库表内容。
+ ^& e! l3 y0 `6 z) [2 f
/ C, P( C. R2 |由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表 $ R5 M6 Q$ m# M$ f2 v
列名称和每个权限有关的上下文:
* Y# {: ^/ K( _( j$ w. v权限 列 上下文 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 在服务器上的文件存取
% s  |+ Z; e) Uselect、insert、update和delete权限允许你在一个数据库现有的 8 T: L+ {+ b- m# J0 \+ h  R4 [
表上实施操作。
. l+ `  Z0 x+ m/ v* Z! J+ e+ b$ f3 n
$ F1 E5 t* n) Q% k- M) ASELECT语句只有在他们真正从一个表中检索行是才需要select权限, 5 ?2 }5 d1 y! A" t  T+ V' H
你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存
7 @: T/ A- K+ z取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器: , Z$ ^; E* H' `8 Y) ~% T0 V

/ N5 i3 A& {" _9 l9 Y) G* k( e7 Fmysql> SELECT 1+1;
$ k4 Y- P- U5 {5 o& v. G2 i, m( smysql> SELECT PI()*2; 0 ~2 y/ O% r. ], J& O+ H" g0 `
8 x" D# r) f; @' H/ |
index权限允许你创建或抛弃(删除)索引。
8 J$ b& }' ~+ a& ^
( ]0 X, N" L, Y( b) ualter权限允许你使用ALTER TABLE。 1 r, M4 O* Q% r  Z; E4 d
' a& p, x: r8 i( h
create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的
9 M/ X' a/ |9 P5 B- V数据库和表。 ) i3 f' _' k+ i% v9 F, p% Q) k
+ I; W+ Q! a/ }0 c. n
注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃
) p5 w, x2 U1 o存储了MySQL存取权限的数据库!
" r7 R1 \2 j  }: U5 b/ f* W2 @- g0 v9 O7 `0 Q/ m
grant权限允许你把你自己拥有的那些权限授给其他的用户。 5 C: x& R4 w" ~7 [5 W, W
) |5 A5 J& ^5 [0 k# [5 }
file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句 : N2 [! _4 Q; ]  _; x
读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务
+ W% Z$ m  x7 b  [器能读或写的任何文件。
  |0 _* O: @: y5 R" W
/ U9 h+ }& d9 I# r! Y其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示 ; }+ d3 y, `3 w) F
mysqladmin支配每个管理性权限允许你执行的命令: 1 ~) R- z" S+ b" |0 g/ U9 }
优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill / u0 O3 }! L2 B3 k
reload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开
1 N1 D2 q& N! a, V# |+ S1 O$ p和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-* : A% Y- s4 N" q! h4 N
命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 ' j' ?! U- d' K/ f- k: o
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的
3 _/ Q# G$ z0 H选择。 + v% ?( g8 e. Q, f3 C
* g7 j+ |2 J" `9 L4 _! t
shutdown命令关掉服务器。
+ W: ]) _+ X* r% x$ w0 r
; A. b& w2 X1 {. j) |! H7 fprocesslist命令显示在服务器内执行的线程的信息。kill命令杀死服 ) Q) I. B9 F3 N3 K8 r
务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来 4 V% s1 b; F4 }$ ]$ y# G
显示或杀死其他用户启动的线程。
) P1 \; ?0 T6 Q# k" }8 x
" ?0 Z; s& U$ `1 n. r总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你 , D* @  D. U# U8 G: z- E
应该在授予某个权限时试验特定的警告:
+ C9 ?4 S# @, b6 ]; k8 n# f9 \# v) S
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并
( O) r. L/ U) _有grant权限的用户可以合并权限。 4 h  l+ j- E  F4 `5 O  J' d
alter权限可以用于通过重新命名表来推翻权限系统。 " h2 t. \9 s4 A+ X, ~% s: q
file权限可以被滥用在服务器上读取任何世界可读(world-readable,
3 i" B7 t0 _/ e# W即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。 8 d$ w4 c% }1 |
shutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。
: V  |; r5 }. e0 W+ r6 ~precess权限能被用来察看当前执行的查询的普通文本,包括设定或改
; F$ k& D# {) o7 `" H变口令查询。
/ Z/ Q7 ^* k, C$ p2 l0 }8 ]8 {在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口 ; e, Z$ X$ G: i6 Y" K
令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够
$ C0 ~, r5 K3 a' Z1 N+ b0 k; o的权限,同一个用户能用不同的一个代替一个口令。) ) n! `3 B  B0 W% Z6 N
有一些事情你不能用MySQL权限系统做到: / Z# C% c; t) T& Q
. D; U! w5 X+ f8 b, R! z
你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹
2 m; G; Z7 c& s9 Y* [配一个用户并且然后拒绝连接。
5 E8 y# i7 y  }- @7 L. ]5 e0 ?( K7 }你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建 , ^0 C3 j7 Q% t
或抛弃数据库本身。
" v- b  v4 Q# O( I7 M权限系统工作原理 6 }) q$ W& P& n6 u- V
MySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。
: _* H! M: ]/ X( B" d% R当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用
: u$ I* R  B" e! S' O户名来决定,系统根据你的身份和你想做什么来授予权限。 - _6 ?2 @) W# X0 ?& @/ w0 h. G- I

, g; h2 [& Z2 R; R) ^0 U% ^/ j+ BMySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假
4 u3 o0 {7 l  Q) q* Y定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov   O9 C" j) U0 h# U
连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区
: _6 `: ]( Z- R" k- y( o分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov
& Y" u* k1 r% e. x4 ~连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限 6 M$ q7 J0 n. J+ u' D6 L7 f/ Q
集。
, M6 U6 k0 }7 c# |) R( x& W
" g5 b4 v3 R! U& T: k+ SMySQL存取控制包含2个阶段: - u; w" z/ }3 V) z# Y. J
& Y$ L3 z+ {( }7 C
阶段1:服务器检查你是否允许连接。 6 B& I) U8 N% V) A4 g3 @' T2 I
阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够 ( W* |# G. f3 p# y: n  }2 q- Q
的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛 8 r  n" Y: g% N) M9 F; F! J
弃一个表,服务器确定你对表有select权限或对数据库有drop权限。
4 F& T& ^( L& X# P: r服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host ( l) |7 g9 y+ y8 |7 ]: w
表,在这些授权表中字段如下:
2 i8 a# @0 T0 G9 o表名称 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 7 m5 z8 x9 l0 T
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
* l  E8 @4 D$ e# n. ]参考tables_priv和columns_priv表。这些表的   i! Z# n3 Q6 x! b/ `, ^7 }
字段如下:
* N# N+ d% j5 h$ ~, L) b' @/ a表名称 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
; @2 y6 |! p4 d3 W/ `: e' a对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
7 k; S; q& @5 D) U: ?1 {8 C参考tables_priv和columns_priv表。这些表的字段如下: 4 |" f- X$ A8 e7 j6 l
字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60))
: a5 C, I4 D/ P在user、db和host表中, 8 s& a- b0 C6 |
所有权限字段被声明为ENUM('N','Y')--每一个都可有值
$ x- d( E$ x$ R'N'或'Y',并且缺省值是'N'. + D* c& F3 d4 ]( t9 E- w
在tables_priv和columns_priv表中,权 5 z; w# S. p0 Y6 q: _" f% n; s
限字段被声明为SET字段:
- e+ ^& U7 Q; _" 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' % s" L7 i! H, g3 E9 B
每个授权表包含范围字段和权限字段。
3 U8 |/ f, t8 h, w8 T# v# N0 ?7 q5 ~; v  v/ z: x2 X, I
范围字段决定表中每个条目的范围,即,条目适用的上下文。例如,
( }, N- r4 y  n; V# B一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于 1 [; L: a* @( _  W; d
证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条 2 @+ H8 `: e+ @/ g, q5 l9 o. @7 P
目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports' / Y1 s; l9 X9 i" ?" D4 m
将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。
# Q+ K/ T0 M: |. ]: u7 T  mtables_priv和columns_priv表包含范围字段,指出每个条目适用的表或 % J8 v; j4 b; L- p- L4 g
表/列的组合。 ' Z" ~5 G8 G; D) m

. G8 F" \  R% X% w% B% X* P# A& e对于检查存取的用途,比较Host值是忽略大小写的。User、Password、 " B; y: S& i3 w0 I. F7 v0 s8 _* L
Db和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以 2 j7 F& M1 q' ?* u4 d8 u: e/ |3 F: Y
后版本是忽略大小写的。 0 w0 N, f% T. ^8 O: l! Y

) b0 \" n/ u! w3 \2 ?# S% h6 l权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务
0 J) w8 C+ K' P  p3 u" C( `% k器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规
' `% B, g$ s9 V4 O1 v& M则在6.8 存取控制, 阶段2:请求证实描述。 9 g" C& q) k( [( T. t3 _
/ [; `1 I. k8 p! w, E' x+ o& r( f0 E
范围字段是字符串,如下所述;每个字段的缺省值是空字符串:
8 b' a# M$ \1 w- w3 a5 I" W# v字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) 1 W! `, N* f  l; P
在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一
, e7 |7 S6 C8 {8 r4 \0 W个都可有值'N'或'Y',并且缺省值是'N'.
8 k7 `. E. J' z
) b9 a, f; K1 U在tables_priv和columns_priv表中,权限字段被声明为SET字段:
1 G% g$ I2 w, ^* 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'
8 F4 ]" ]  p# N" w% O% z# p# x简单地说,服务器使用这样的授权表: % T: n1 O+ f) m
0 l( u/ o. U0 o( C9 N$ d4 {5 Q
user表范围字段决定是否允许或拒绝到来的连接。对于允许的连接,
' P6 y: {/ a8 U- G$ t3 v* ~8 }0 \权限字段指出用户的全局(超级用户)权限。
5 q7 W, Z% m$ R2 D: X: ydb和host表一起使用:
: p6 l2 D+ L$ M, R0 E% r6 Gdb表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定 * l5 w! F9 h% O
允许哪个操作。 + M" e, C1 P. e3 n
当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩   J- t& w/ {" J7 l6 `, F9 H- h
展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个
. X. _4 P! |0 |) M1 L0 I数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移 : A! }" y, i  p; N, b
入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。 3 p2 b0 t# o: m3 ~; Y+ ]8 |: Y
tables_priv和columns_priv表类似于db表,但是更精致:他们在表
. d$ X* c5 D1 X9 a5 J" P' B和列级应用而非在数据库级。
" v! {# F: S, J注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是 & n: D# t1 j& B. }( l9 C1 q
因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由
9 t; _0 A' G0 K# z9 a在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是
7 c# u2 r" e1 N. P4 m& t# F否执行一个管理操作。 6 N+ ~  K! D4 ]

/ ]8 S, R+ d3 R- D2 cfile权限也仅在user表中指定。它不是管理性权限,但你读或谢在服 . V1 J+ e' G. i, }4 C
务器主机上的文件的的能力独立于你正在存取的数据库。
4 d, j1 |9 \9 ?! G$ s, A) b
( u( D6 ?  R2 ^6 J5 [当mysqld服务器启动时,读取一次授权表内容。
1 E  s& `8 S/ ~: D; ~$ H9 y$ v0 u
; F4 P2 L5 k  r2 z& H2 L5 K8 }4 r当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一 7 o! A0 z2 \( {$ E
个好主意。 . j% l+ a+ X+ v
% M  ~8 @/ p- M( f" j: L2 w1 M
一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给 # {- ^9 @7 l* e- ?* W
MySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意:
1 I5 i+ L$ r' L$ P  [  D# {; s6 H2 Cmysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。 6 x- k& @8 [' w$ n
4 l! y- G. K+ ?
存取控制, 阶段1:连接证实
" x! _/ }% n" l# h1 t当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能 , z: X' n: ^2 c. {4 ?
通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全
' N) A, S9 x2 J7 H% c  C& Z3 M8 i具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。 * V; W" R4 E+ [6 \/ a4 j  y5 m9 Z

' I' }( Q3 O! V( J( v你的身份基于2个信息:
1 p0 y$ t$ }  g5 @( }5 C
1 s  D; B" n% {3 Q# m9 E( p/ n7 l% l你从那个主机连接 2 o) t7 P+ T5 l) }- A
你的MySQL用户名
5 l$ I+ m; U: ?. Y' X身份检查使用3个user表(Host, User和Password)范围字段执行。服   c2 x8 r1 d; E' u( N
务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的
- l% ~' I0 l) k" Q8 X口令时才接受连接。 ( ?! D" A5 y2 q6 j
( o/ C$ c8 c; H  @5 ~
在user表范围字段可以如下被指定:
7 u; B; \1 o. v3 V6 K
# f$ C' J9 Q  c1 o一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。 3 d3 w) j; o0 q" z7 ~; A
你可以在Host字段里使用通配符字符“%”和“_”。
! f2 H$ y+ P4 _4 i( r一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些
% d! z7 d+ ?; T9 K$ i# f值匹配能创建一个连接到你的服务器的任何主机!
# F9 l" c; M* }7 f& Z; ?* f通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何 ( k3 Y1 p8 i8 U4 z: O3 `& I9 ^+ R
名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为
& X$ c; {& v9 k9 s; `9 t是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空 " @8 i6 ~. u0 v0 g0 ~0 [( W& Q7 F; u
白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。 ! n  U) p6 d& Q+ r
Password字段可以是空白的。这不意味着匹配任何口令,它意味着用户
# n8 p& g5 `- d/ S6 B7 \必须不指定一个口令进行连接。 : H* L; V! p% n2 _
非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本 # b3 Q) k. x4 Y* n$ @" q
格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用
" v) h( q' e; l- x5 I/ z% x' [0 H2 `PASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他
/ b, V- C5 j4 M: C1 d' ?. u们匹配,口令是正确的。 # \) D+ `$ T1 O, Z5 |  {2 Y

; r$ s; w  t/ H% p& r' h下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来
; b  L+ y3 `8 Y8 ]" e* U+ i% M4 x' z的连接:
* M6 J3 H. q, H
% e2 h2 p8 h2 r7 Y$ ZHost 值 User 值 被条目匹配的连接 . y) c* M; h3 o) d) P7 k. B
'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接 4 H4 r5 c, z8 T" R, P
'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接
/ R  `; s; I9 I  |* @'%' 'fred' fred, 从任何主机连接 * E4 P1 V8 F2 o, X: Q" z
'%' '' 任何用户, 从任何主机连接 4 `) R, W) p; n. [' y3 ]" ]
'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
: I/ }( B1 z) x'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许
5 {. K, v0 g( y( @* s: H. ]. o( u! ?+ \无用) & Q/ ^$ u! l  H8 C7 ^
'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主 ( W2 o$ C# {4 r- a
机连接 8 b) n3 {; q& N7 M; ]. Y. L
'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连
, H6 A) G+ V1 J% ?1 J+ q& U1 ^. K: G
5 \1 z, }1 P* L, v$ X6 m
既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子 1 v0 N, ^5 _, |& V
网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机
7 w% T7 e5 q& h- H为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以 # L7 E7 h, C0 F2 F# w
数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的
* B7 V9 G; m1 n6 a主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配 # q! H# K  Z; U4 h
符值。
" V2 `0 I$ v+ P  w. [; ]* M6 v3 C; U8 L7 R
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由 + }' I$ Y7 x$ B# _3 R0 \
fred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配, 9 C! D0 f( `0 U& m9 d* h1 A
服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来
$ T5 M9 ?  m6 w解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一
) O' B. a- y9 [7 s! P个匹配的条目被使用。 . C7 e: p9 u: A( ?3 r5 {! L

7 C$ Y# @& U) y6 Y: s4 |, @9 I1 b/ Auser表排序工作如下,假定user表看起来像这样: - b. |0 b# q3 l8 f
: W5 A! l  G/ h7 u3 O
: b0 A% z( N' D. |+ E
+-----------+----------+- 1 [" R3 i  @7 r  |, {' g. k
│ Host │ User │ ... 3 H* `# C. ]6 R, _. V6 M. }
+-----------+----------+- + r, ], n) o( p
│ % │ root │ ...
0 c: E  _3 s% A1 E9 S! o1 G│ % │ jeffrey │ ...
5 @# p; A" h+ r2 W) I" z│ localhost │ root │ ... ) ?6 ~" r2 ]2 W& p% z
│ localhost │ │ ...
& z4 U7 ~* A: {. {4 b+-----------+----------+- ; z: [2 M5 i. e- L9 M

; N% Z' w* ^6 n+ N& k  R& G当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在
6 p4 o+ s+ N' c7 rHost列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以
% M! U: P0 f* V8 j% Z, ]最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且
8 v5 o; d& I: k2 ?% Z% D是最不特定的)。最终排序的user表看起来像这样:
( R$ B1 k! H, |' K2 ]: Z0 P: y
* O9 \' m" j8 w$ ^1 x/ [$ z8 e  `9 Q3 T. y; D& C1 c% B
+-----------+----------+- ' C: i: P/ V$ P  |; a. F8 R- N) T
│ Host │ User │ ... 5 L! u; {% ~# f7 u: f  N0 u) F
+-----------+----------+-
* R* F& i- y3 J) j) E│ localhost │ root │ ...
9 B& _1 y* f& C+ Q3 Z│ localhost │ │ ... 5 I; L# P* G3 g# D' W
│ % │ jeffrey │ ... $ L9 A$ Q4 l" H1 |
│ % │ root │ ... ) b0 J5 W, _/ x: Y! P- U+ a6 f
+-----------+----------+- % {  o- L! I& h2 j5 K# [

1 u- N; j( A9 S9 ^4 ?当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹 ! `( S9 S6 }: i* M# p; O
配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目 $ T; t$ ^3 f  R$ _& [. l7 u
首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/ . g, S) v8 _0 a3 ]1 T1 {
'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。)
8 Q; T4 e* z5 n* c. h: |& s4 T; p3 Z/ O- y4 J
这是另外一个例子。假定user桌子看起来像这样:
! j- r( H9 k% Y: }7 d& z" k  b$ P* z, B8 B" }( }
: z" n2 o$ J  }% J7 B! n
+----------------+----------+-
: Y  o' `. d/ ~: s/ @; _│ Host │ User │ ... 4 Z$ }( T6 f" F. D8 M5 N! Y
+----------------+----------+-
8 y0 B/ c0 N7 O8 V2 D│ % │ jeffrey │ ...
  t% d/ K+ s1 N; Q% w1 ?│ thomas.loc.gov │ │ ... # W( y/ ^+ A' B0 A2 A1 x3 s
+----------------+----------+- # N4 Z  n. h" G& `: y/ p# K% V+ R

8 F0 d2 }  a% M  |5 H. ?$ V% [排序后的表看起来像这样:
1 i8 f2 l1 m) l! ?. S0 l+ T0 x! G  V# [, J2 k" C% [, B
% B3 ^# K. L. s* p& l7 K5 p
+----------------+----------+-
, G& M% v+ L2 C+ N* T│ Host │ User │ ...
- X9 H2 o4 c9 I0 j5 ~5 @. U6 ^" T+----------------+----------+- ' _) R& K  @+ n2 |
│ thomas.loc.gov │ │ ... ! E# l! ]# \: B& u8 C" w
│ % │ jeffrey │ ... ; M' S$ L# ^6 A$ N, a7 `# N
+----------------+----------+-   l$ ~) C) b; P; G% [3 m, g

  p6 u9 x* x$ r4 O" p  g3 S2 N& i一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由
* B4 n+ \8 u$ x& H2 D( q; Mjeffrey从whitehouse.gov的连接被第二个匹配。 6 }" e: K$ h# k9 W
, B; D+ W/ T0 k- O$ z
普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找
& }: J1 K6 D8 \" \& W9 w匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。
7 N7 E$ J) K1 A- }* F" |先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没
( p% {8 g4 u- P  |被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹 ' f  T  Z. Q( X( u/ z/ N
配! ) g" D/ ?- r/ {  {# g/ p5 t& R& L

- e* ?, }/ c# Y) N0 S% T) S如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个 ' {: X+ n/ g0 g  T* K
匹配在哪儿进行。 * h1 C: B; X$ P5 q& V  _: m' v

- @; F# p( j2 e/ a* u3 p. I- I存取控制,阶段2:请求证实 / P4 B/ M4 q" x0 `8 a
一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个
- _, T0 e0 K. T6 n- q* u请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作 7 Y+ L$ b- Q, ]& g
类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子 + y  ]+ ~5 q6 Y
user、db、host、tables_priv或columns_priv表的任何一个。授权表用
, U+ r. w2 C" \. eGRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参 1 I0 n6 L2 q3 L' T8 n# U5 p; E
考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。)
6 I1 x* J) U+ w3 a& x! h, d# ]/ W' P% z5 L% F" E& j
user表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库 4 m) }" H& |2 p7 d
是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器 : w5 d1 A/ Y0 y
主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
" ?2 Z3 t, m1 ]user表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户,
7 V  [% `. C+ s+ |: j; P+ U你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权, + u# R- Q% f# J: k% h' I, m
使用db和host表。
8 H: G- ?+ D6 f& C: d% }& O0 j" R+ l
db和host表授予数据库特定的权限。在范围字段的值可以如下被指定:   o( Z* ?3 q; a- ^! ?" @

/ o$ r! k' c$ p8 E5 d通配符字符“%”和“_”可被用于两个表的Host和Db字段。 ' R! c5 `+ O9 N# L" g! |
在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 0 Y( C& a% Y! K
着“对进一步的信息咨询host表”。 & u, i5 L- W& V
在host表的一个'%'或空白Host值意味着“任何主机”。
  {( S# x- j" s. ]. O在两个表中的一个'%'或空白Db值意味着“任何数据库”。 0 Z4 }+ e  J. Y- A4 o! {2 h
在两个表中的一个空白User值匹配匿名用户。
3 ]3 W5 |% p* E. v9 jdb和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host 3 S1 [  m$ v( d& t0 \9 X
、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于 ' U" i+ ?- V9 Z' G
user表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 9 \, c. Y5 V* l8 ~3 w
匹配入条目时,它使用它找到的第一个匹配。
4 b& K3 K0 j0 Y: b& H" J
1 w- U8 f  ^- C4 Ytables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可
* M7 i4 K- S2 y# t以如下被指定: 5 M9 A8 f( h0 {  M

* X# Q& `+ n0 {  g通配符“%”和“_”可用在使用在两个表的Host字段。
: {7 Z: ~; @  o8 K8 Z在两个表中的一个'%'或空白Host意味着“任何主机”。
2 a" |* L: p) S1 Z3 L# N- k在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。 7 U" T- |  t; ~) h+ F8 X
tables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于 : k" U) L. Q% c5 c# \2 u( g$ D; X  \
db表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。 / _, G" ^/ f, m7 w4 r
7 x. R' k" R  N5 k0 X  ~4 A
请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这
; B6 D- Q0 J& r里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是
# r" I* s" e7 J不同于使解释更简单。) ( Z( P$ f! p, G/ O, u( K  k% o
6 i# ]% W1 R1 K+ j' l$ g! d+ I) Z! }
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是
+ n2 r% _! H5 c- W; k, H* U+ n7 ^唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。
/ x4 J. K7 v) V- K, Y8 N例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授 ! N6 ?5 X+ E5 O  h
予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含
5 v# K* u0 N* `0 U, sShutdown_priv行列,没有这样做的必要。)
7 K( ]6 Z  m) }" H6 ?; ], [
- n+ Q5 U1 y$ S2 w( j对数据库有关的请求(insert、update等等),服务器首先通过查找user表 ; Z8 H8 ]& z4 G' C6 @* M
条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授
7 u* u/ @: d  w1 E: ^) P( h' T0 O权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用
" j; {) |2 o5 h6 h5 m# }户数据库权限: ( B1 `4 l- Y5 O: l1 U6 y& r

4 O( s, x6 I  M' h: H/ F8 \: j服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连 / E4 D4 v+ I2 M! ~* J; g! p. j
接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有
9 `: V- J- I! W/ v7 pHost和User的条目,存取被拒绝。
- l5 k$ R& O7 z如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用 1 y  _/ E6 x, ^5 ?
户的数据库特定的权限。
: R1 H9 \) j% s% z6 E如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被
' [* B+ E: f! {9 i6 }; _* i, H允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和
! W" a* w4 n) EDb字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数 1 X3 a# _9 k# {) L. Q* g
据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交
. J' }# b% N  l9 z6 Q' ^" Q集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host
4 G" m8 e1 \) Z& `% V3 A表条目按一个主机一个主机为基础地有选择地限制它们。)
& u# |% f% y, P- J' E! S在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
, |9 T3 v& [$ M# r$ |4 b* E由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服
$ K# M; F2 K) g/ U# R, K务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到 ! p% s. [5 Y$ F' O% D6 z
用户权限中。基于此结果允许或拒绝存取。 4 K( I' G9 E$ M* v- A9 J

1 S: g3 j' m) [' _用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结:
. I* M0 H. t: p+ w$ Q
0 b6 `2 X# P$ t5 {: }global privileges 3 z8 D# r8 U( k
OR (database privileges AND host privileges) & ^3 z) G2 I9 Z9 n
OR table privileges
; u$ Q9 g+ s+ K6 i+ Q' z" Y( U$ eOR column privileges
$ D) r! ~5 g3 q9 y! l5 J7 }) h2 g, w# x. s" e- u! ]2 X
它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不
+ x1 M( p+ j  e够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能
  u2 V# j- F+ u7 a) v* _要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都 * G0 N: `1 F! b# ~6 p, e& g
要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条
" [6 n  z- S7 v  i- p" |' i目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把
, {: Q: ?+ X0 F2 V* M& |  y两个表区别开来;两个条目授予的权限必须组合起来。 & }3 F( V# Z5 n) d2 i
2 b! E, C! ^! F; Z8 p
host表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本
1 U  b5 Y, t1 r地的网络上所有的机器的表,这些被授予所有的权限。 + z4 m3 B- W+ i  C
; Y: B6 S9 @7 x/ m' J+ n6 A
你也可以使用host表指定不安全的主机。假定你有一台机器public.your.
+ L( I4 J6 u6 A- O( Sdomain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允
, I, E$ u$ a1 q" U! o) t% y" S许除了那台机器外的网络上所有主机的存取: ! R0 v5 M9 {' x6 m( \

6 f. O6 {& G/ K/ @4 y
  L2 X$ ^+ }4 P* P5 W+--------------------+----+-
2 t% q( b" q  T1 U0 T; [3 p/ @5 J1 K│ Host │ Db │ ...
* d. h7 _# Y6 W, x7 [" {+--------------------+----+-
3 f7 h9 P1 C0 ]; B4 K  n6 J│ public.your.domain │ % │ ... (所有权限设为 'N')
  q: Z' `5 `# i/ H8 B│ %.your.domain │ % │ ... (所有权限设为 'Y')
8 v+ [3 K, d# ^; L6 h: G+--------------------+----+-
# \3 h0 a9 s; V6 ]/ F4 g! r6 L
( ]4 t0 G' Q/ i6 ]6 Z; `当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保
5 a2 A! E1 y/ l. ^你的存取权限实际上以你认为的方式被设置。   l& v: A3 R& b$ S$ U! E  J

! A% n+ s( D- P1 I+ U' V权限更改何时生效 # D" X) B1 F. u% V! e4 K5 u" \
当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。
3 U& `  n9 ~) G& O
3 a/ k! A8 Z2 {, D1 l) u用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
0 |! R& b5 I# H3 b2 r1 `) h+ ~0 G9 b9 x' q; ]
如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH
: m( o1 E# \7 \3 {, ~PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否 / r+ C' r, Q1 T% A$ ^% t. {3 ]
则你的改变将不生效,除非你重启服务器。
' d9 }( R4 \/ K1 O
: A0 X5 E; o/ Y9 V$ H# U当服务器注意到授权表被改变了时,现存的客户连接有如下影响: 9 z9 V( a7 w% c" j
+ ^) ~6 E, w% S5 x0 [
表和列权限在客户的下一次请求时生效。
+ ], }3 P$ h# ?- r) ~: o数据库权限改变在下一个USE db_name命令生效。 - }) c1 [( `; c
全局权限的改变和口令改变在下一次客户连接时生效。 ! G* g  }' C' ?! s1 i0 k  m& q/ B! L' k

' i$ `0 D9 T+ T/ m# x建立初始的MySQL权限 % V" d- x1 o+ W; }2 `7 U) `
在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。 " Z- B8 l2 Q1 L( S
scripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列 1 B. {/ }# e* T. d  ]4 z4 `5 c- n
权限集合: $ w" b5 x3 X! d5 m
9 ]' d' `5 N" u2 E
MySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主 ) e: ~! L7 T- R6 y
机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行
/ l: q% q# c& w0 j# \连接并且被授予所有权限。 # G8 v% X: O) x2 S; v
一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库
' a( L( z4 p2 s* ]5 c1 y; S做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视
  g+ m2 q# [  Q8 b4 l2 {4 E- y: @为匿名用户。
2 L4 W/ h9 n0 o- g, B% V, O其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或
" h7 d1 s0 M, y0 B. Kmysqladmin processlist。
1 a; F2 I& z$ Z+ M# G; Z, t注意:对Win32的初始权限是不同的。
6 M6 G0 o0 l* n2 \0 H  r: K# U$ c2 S5 C) f6 e' N6 l* |
既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户 1 |2 w% s, l/ k' s8 b
指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令):
4 T8 E( O/ f- b3 I$ x0 f( x) }( f. @+ R6 p, q
shell> mysql -u root mysql 8 h4 k) C# x' U4 c* B4 s! d% O
mysql> UPDATE user SET Password=PASSWORD('new_password') & A& K9 H4 H0 ^
WHERE user='root';
9 y4 O, g+ ?; U8 B% _mysql> FLUSH PRIVILEGES; ) y7 }* }+ [% W6 f  z
) D0 z( g  {' `3 T. U
在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句:
& u) t+ T3 `5 K; I' v$ ~
$ |# e9 f6 e; |* O& v- n! I9 Eshell> mysql -u root mysql
; ^: Z4 k* L% q( d/ zmysql> SET PASSWORD FOR root=PASSWORD('new_password');
4 K8 R! e7 U2 \
2 d# I" P4 q( T5 P/ @设置口令的另一种方法是使用mysqladmin命令: 5 i. W( B; m9 L" ^1 ?- [2 P

  U# _' l; k, i. D/ M" Y5 |shell> mysqladmin -u root password new_password
2 b- x6 D) A7 H( N
, J" c! I0 m5 t4 w. w/ V注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器 * F, P% f. X9 p& i/ s0 e
再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。 8 n/ U1 ~( q+ Z0 t* V* |

  M* V1 T# N( C; H2 n( `/ p9 q$ f一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个   v  D; Q8 b$ x4 H# n2 a
口令。
. m6 d+ Q% U9 e( E0 Z- }: h* ]
( W- b: x! T) W( p: Y8 h8 n/ n4 \你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它
' N0 b. k; u' Y# }6 A$ e' A4 L或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。 - H( H+ q( K' w; ~

4 l* ~% c; ]$ ]3 W7 v8 o8 n0 S6 l看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它
3 @9 N7 ~8 ^' p% U* D. U! `作为一个研究如何增加其他用户的基础。
- }# n/ o* Z( T" U0 d! v6 h7 C+ Y3 K; P) |& w6 {, m4 J
如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db
0 [' i, R% }+ K; Z: D/ m0 F之前,你可以修改它。 $ {6 S% k3 {/ T. x
; c. x7 e$ u; R% j& @3 @
为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”,
5 D" f$ m  D4 ?5 @“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,
" C8 J( I6 l/ X( X当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能
4 f7 Y* R5 b* [# s5 ~" I$ w在首先编辑它拥有你想要的权限之后。 4 l+ k$ Z% e( ~5 ?; h8 y
1 t3 |0 f9 ~; d! A
注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果 1 P# X' q4 P1 o" @3 R, F$ N
你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。
& Q+ N* f: ~% _, J8 Y+ ^# V/ \5 K: R4 C; O2 |
向MySQL增加新用户权限
0 Q9 I% w. v' |+ ^) I你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授 8 K  C, F+ z0 O/ z- Q
权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。
9 D) ~  T$ J4 W& a+ y5 m  [1 a
( P: V7 @& {) ]/ F& i( Y下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前
8 ?- a: u% r+ b的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台
- c8 P5 E5 H3 O+ b/ B# _% o+ M2 ^机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有
4 K8 K9 Z" w* r+ k) D7 q. [insert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下
$ t" g& V' n4 s的mysql命令指定它。 : z/ K' `# `9 P8 J+ c$ \7 T

4 Y- {6 x: Q, |2 M$ U你可以通过发出GRANT语句增加新用户: ' ?6 m3 `) E) L- C6 C# [2 q4 y
. _% P# u5 l9 ~1 J
shell> mysql --user=root mysql
1 e7 ?/ e- z& E% p# lmysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost
0 R7 z2 }$ l- o+ R# |/ [IDENTIFIED BY 'something' WITH GRANT OPTION;
1 G7 F2 U$ R* `- z6 U0 x4 _mysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
) ?5 s5 l" _5 oIDENTIFIED BY 'something' WITH GRANT OPTION; * q, O8 L: _: O
mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; 0 I2 W9 W. n: |1 T: |4 Y
mysql> GRANT USAGE ON *.* TO dummy@localhost; - c1 l# q5 G  D0 s! U+ E' c5 m
2 C0 N( p; U9 W. ]/ u" i; T; _; E
这些GRANT语句安装3个新用户: : F4 p8 q  l5 C; @1 m+ K; N
7 l' f! ]9 @1 G' _
monty # X3 d, N* s( Z$ _5 N" B
可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个
3 F( A8 A  f- z: `$ }, X' a口令('something'做这个。注意,我们必须对monty@localhost和monty@"%"
, F  @& Y; A' d* F2 E发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
! ~! H% w- |) b6 L5 y) \在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为 ; t3 q% I3 p8 N: n
它有更特定的Host字段值,所以以user表排列顺序看更早到来。
6 _3 N6 T+ m1 t; dadmin
6 @$ x" N+ o) {) r1 A( i  `可以从localhost没有一个口令进行连接并且被授予reload和process管理
0 G) j' J! v* j7 C) Z, \: M权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和
1 s3 e: F2 a* m; l/ ?* ]5 {mysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有 % J+ y8 k4 Y/ }5 V8 s; E/ I
关的权限。他们能在以后通过发出另一个GRANT语句授权。 8 X9 i- \7 ?+ I# C5 h
dummy
& }, K$ U) J! [可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设
* v9 r' p1 C9 L$ S置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以
) d* K& C. E9 |: w2 \5 o* T后授予数据库相关的权限。
2 @* F: l( e2 K2 o6 c你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服 ; c+ I2 o$ T" S) _' q8 L4 R
务器再次装入授权表:
6 V3 Z# ~5 H. a9 m5 w+ u* `0 P6 Z- O6 ]5 I  f+ N$ D
shell> mysql --user=root mysql
8 {" q2 E' C9 Y# \, O' Dmysql> INSERT INTO user VALUES('localhost','monty',PASSWORD
) m6 Q! j6 I2 ~- Y/ a('something'), 1 d. B9 m" Q* q# u6 m8 Q4 r
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', : R, k! P0 v* ^6 ^' s. c4 M8 K! t
'Y','Y')
8 l% J. K: Q# D& amysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'), % T, l9 ]0 q! {0 p) {" K
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
8 \; @6 Y# s5 O1 S6 \'Y') + X8 Y. F: ~9 f( M
mysql> INSERT INTO user SET Host='localhost',User='admin',
* F# m/ s7 J  b" MReload_priv='Y', Process_priv='Y';
+ L; E! @$ D. M" I- r4 k' d/ L# i* hmysql> INSERT INTO user (Host,User,Password) 7 O  N) i! w, B9 j, Q- w
VALUES('localhost','dummy',''); % F9 ]+ n+ \" l( }) u
mysql> FLUSH PRIVILEGES;
. q7 b2 G4 ^+ ^& b& ~' |* a" {0 W, ^3 ^4 i# r* k
取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
8 s$ l4 k# @3 i+ b3 E8 u% u3 M3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版 % J# R6 P; |' S3 {
本具有的更加可读的INSERT扩充的语法。 ! l# M  o  n# j! C

8 S% s  a8 n' c注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为
* `+ `: j+ _) W- b3 W'Y'。不需要db或host表的条目。 % r1 d" U9 j; G1 Q. }' f

- y+ E! A" @* ]# g在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户), : V" o* m* |: z/ q! @( R
因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。 5 d7 l2 A# b$ D6 X% y
2 j& u6 }' ?4 O
下列例子增加一个用户custom,他能从主机localhost、server.domain和
& K6 ?3 N% Z/ X$ ~3 @4 x" U( uwhitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从
, k2 h3 x, x: p5 Jwhitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他 & @. R- P7 g+ o* B% Z( O3 \
想要从所有3台主机上使用口令stupid。 3 E% q' D; u- u% O! l/ ]
/ z1 v8 Q8 a& U9 t. A
为了使用GRANT语句设置个用户的权限,运行这些命令: ' C$ i) F5 h" S8 u% O

6 f& v& k0 G! _$ qshell> mysql --user=root mysql
& m( ~, H" T% \, w8 Bmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
! o' W6 @' N) }' D% y0 xON bankaccount.* 5 U7 w6 I7 C5 Z8 ~- K7 R
TO custom@localhost
7 N" _9 B: \# ^- FIDENTIFIED BY 'stupid';
# n+ x4 j0 X. u# `' S  emysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ( Q( s6 P5 U/ _) N; y8 }, G
ON expenses.* " q( N0 L4 B- Q  V' \7 u
TO custom@whitehouse.gov 4 J. b  l+ I! H0 q6 t2 @* q
IDENTIFIED BY 'stupid';
% R5 Z0 A, u# U, r  tmysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP 1 ~! E* T, r& k6 h
ON customer.*
& V/ [  p$ ^0 i- y5 }) k! zTO custom@'%' + |8 L/ w5 y& K9 a/ Y
IDENTIFIED BY 'stupid'; 3 m# Q0 x3 w1 P6 g

+ m( k2 S: }: _2 `2 s通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时 6 S. M, T# F2 f0 Z
FLUSH PRIVILEGES): ! j% |  g) E5 x# H4 z& o; w0 s
" p4 o5 u, Y/ O  }: L
shell> mysql --user=root mysql
# b! w7 y8 U. @: A' G) ~* amysql> INSERT INTO user (Host,User,Password) # G7 @7 w  g/ K  q4 \' a2 m% e
VALUES('localhost','custom',PASSWORD('stupid'));
+ l5 E% x/ P8 Nmysql> INSERT INTO user (Host,User,Password)
# Q: L; h% b8 iVALUES('server.domain','custom',PASSWORD('stupid')); * u7 k  _: ^  f
mysql> INSERT INTO user (Host,User,Password)
9 L- _/ l9 O# E* HVALUES('whitehouse.gov','custom',PASSWORD('stupid')); # C2 T4 S: g( S7 B( @9 \" [  R
mysql> INSERT INTO db 4 W/ i" J4 e% Q4 C
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
; R: T# K2 y  \" i" i( t8 ZCreate_priv,Drop_priv)
+ e1 U2 [0 ?7 T1 V4 s8 ], n+ k0 NVALUES
/ ~& Q6 [. M+ Y4 g, m('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y'); ) I. o4 p. K! u+ ^
mysql> INSERT INTO db 2 A" p2 U) d4 s7 }% [1 j
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
' f5 ~4 e" J9 L! Z4 _" k( D) |8 ?Create_priv,Drop_priv) . V* T# V, w5 m! @! I
VALUES 5 c" F" n# h; }4 ?  Y
('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y');
& A+ X4 n# |% v9 Zmysql> INSERT INTO db
% e, K( J9 n( w2 z2 a  O(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
; p! j6 \7 o9 a9 _- u8 [Create_priv,Drop_priv) * ^1 f% K0 j. g% Y6 A" T
VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y'); ) H/ x' w7 _5 l) h; ~! J- L
mysql> FLUSH PRIVILEGES;
3 S  y8 h; W' R- ^; X. J7 w" l8 P4 B& o) v! ?. l
头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机
* P% l3 S! J4 \" W3 A9 {. a( l进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT % B+ a2 s" M" Q$ H
语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限,
* ?' A( L  k2 W- U1 @" @+ V8 ^但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告 . I! b! s. I8 c7 r" b" K/ f
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。
" `5 E+ t8 v% R8 [/ A% e3 M, G3 o4 z5 Q( u& T" i
如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发
) H* B5 a  G' `) ]' x, V出一个如下的GRANT语句: 1 U  i6 q1 @  N$ Z; u
5 f$ s* o" ^2 y3 d1 P; d
mysql> GRANT ... # N0 u2 s$ `0 X+ w3 e# L
ON *.*
8 ^( R8 T! ], s& [7 h1 FTO myusername@"%.mydomainname.com"
4 [( a* V4 x, b4 e$ F$ nIDENTIFIED BY 'mypassword';
  H9 p/ t' a; r  u: I  F+ A1 s/ w9 `5 u* \5 b" Z7 p- I2 b' C
为了通过直接修改授权表做同样的事情,这样做: # ?* T) i& r- r% ]
5 L1 ]5 }$ U% {) a" f; a
mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', + r3 |  ]: u2 k  m: w% E
PASSWORD('mypassword'),...);
. z  C/ ^: A! A( Gmysql> FLUSH PRIVILEGES; 4 i  w' }" k& |" }7 M- y  S7 z

* n& D/ Z1 G5 X, v你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变
2 W5 g- g7 o  }0 f  @  O和更新值。你可以在MySQL的Contrib目录找到这些实用程序。
2 ~1 Y9 J4 k' z; L& J
6 h& V- R5 F3 P! }: E$ h% ]2 ^怎样设置口令 : M2 p7 |1 ^* m9 ~$ q( s
在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存
" S# ~+ y6 w8 Y- u储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以
! N! `# B$ J. C; |加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图
& b# ]3 {  X$ C3 |$ W& O8 _设置口令:
1 V8 v: J" C) k( Q
5 X8 P; W* B& J1 o7 ~1 P' sshell> mysql -u root mysql
7 R7 [1 l: u& w, Tmysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey',
, _  y: ]  f- N6 J'biscuit'); ( v# k5 f5 R& q; s  N
mysql> FLUSH PRIVILEGES
, Y* i/ g  ?4 L! T- y
8 q; X, i9 G& E1 I$ B/ q结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用
$ j6 ]0 w/ t# m: c# ?7 Y. m这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服
( x+ Q  k" r' c) g2 }2 i; y务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是
6 J0 B  p: Q* ^; O1 ?- c'biscuit'),比较失败并且服务器拒绝连接:
5 @1 Q8 j% D* v+ C) U6 O2 R9 ]$ g9 ?) W* y7 K7 o0 Q2 @
shell> mysql -u jeffrey -pbiscuit test
0 v2 D7 j# U0 R6 N) UAccess denied
+ C/ O# W+ \& o/ W' }1 \8 e% M$ l7 a& `1 r; A
因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样 ( M7 y, [" |! K$ M, @8 J* b: m$ I
被指定:
  I/ O6 C& y" }! ]) Z! d; r0 D. F. z8 [4 L. z9 o
mysql> INSERT INTO user (Host,User,Password)
4 }# V  r: s; `7 HVALUES('%','jeffrey',PASSWORD('biscuit')); - n' I5 k6 c6 I/ @& o( Z+ a$ t

" {- g# G0 b  z0 X! Y当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数: + k5 J; |# D: V: b' d, ]
7 q: L% A$ m9 x
mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
9 {9 g% g, ~. Z4 a
) }% }5 I7 N9 |( u' c如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口 2 Z/ q# s! L1 |) S' J/ z
令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指 8 e# R) m  P* j
定一个口令'biscuit':
! |0 U1 t3 p$ k) O( _* A7 Z
  W( }6 i- K+ C* bmysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit';
2 g" ?  S# i- x; B* h9 B
" |$ \: Y. z: g5 b  c9 _+ j" O9 g7 r- b' u  t- @
% K9 C8 ?% X" i0 W
shell> mysqladmin -u jeffrey password biscuit 8 @/ \2 @; T* p; i7 u9 e$ ]
注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应 2 I; x+ j1 h$ P4 j
该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix
, ~4 U' j: ^5 P2 P! R9 _/ h( `口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。
' q& y+ K8 m" ]4 g2 C/ e$ p+ x! |5 v3 R
Access denied错误的原因 ' \/ B% Z. H; |- z3 P4 }
当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 " b. F9 K- C; ?1 S+ m. U
的表指出一些你能用来更正这个问题的动作: 1 t# b% f* F4 P3 T: k
* i2 r) s( e# h/ S9 x! N& d, ?( }
你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容 : t/ Q) M9 p$ e2 }* k
吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初 ! w/ K& p+ B) _& D
始权限: ; v  c  Q' O! h9 R
shell> mysql -u root test " Z2 ~  e5 @6 W  c( @: X; T1 `
# R4 d) C8 Z& o' l- K; z( t# Q
服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件 % M1 |3 Y; m& c! q8 M& L0 m6 N
“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安
9 b7 E4 w: B$ Z3 _/ W装根目录的路径。 8 m' |9 d, a. a: N0 b5 F
$ [& I/ y7 f6 z. \  k
在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
6 S" G: d9 Q& f9 ^  f9 V2 _shell> mysql -u root mysql ; F1 }; F/ q1 {  I
" T" c) w3 R/ d5 ^4 R; k
服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个 ; L9 a0 e. B% {, L" z( u6 b& P& _8 W# B7 i
安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如 3 \, a% a: r1 w* A) X7 X; z
果你作为root尝试连接并且得到这个错误:
+ {* p, F, S6 }& ^' \0 W+ r% r8 |  f$ o+ |. z* s8 r8 c. B! Q, x
Access denied for user: '@unknown' to database mysql
5 O' Q4 ?" h; p9 a3 d0 h2 h) Q# v* M, t+ B0 h& ^
这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld 0 h0 M. p- }( `5 F5 E, c# C
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项
* A3 {: `/ O- z5 N& L" z重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机 7 `. U- ?% b/ ~  V0 h
增加一个条目。 - S6 A: ~* Z/ f

, G# X( f' y- |2 w' I4 R$ Q$ p如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以 ( K. W+ g+ Z& L% @  o
后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在 * o. I5 U$ Z- M0 V5 ^. Z
GRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。 ( E6 a$ {# k6 o# R( k# S* ~
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被
( D0 _3 J; }! b4 r忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin 0 o. w9 ]0 n0 y' }  G5 W
flush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被
; H( N: r9 P- O& _; Y2 ]重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗
+ T; L" V; y/ l% f0 a; N(flush)权限以后,因为服务器仍然不会知道你改变了口令!
- Z  q, U$ W% N* x2 e6 \如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变 ) G) x4 a" ~1 a- C* |& C7 m
了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权 , U4 w6 k6 K' c* [2 X" L, y! @
限改变何时生效小节所述。 / y- c" E9 A- Q' P2 k+ F
为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变
) ^5 U0 R- L0 X  c3 ^: s9 Z) s3 z3 qMySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的 ( i( }( H( S/ q5 T8 i- `5 k0 I# c
改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权 . ?$ C2 w: z7 l
限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务
% Y% b& l5 V; b2 ]4 c/ N4 p6 L器开始使用授权表,而不用停掉并重启它。
) d2 g( B+ i" ~' x7 q) l5 l如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name
4 t' ~, V- p- C0 ?4 [db_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用
& }3 \7 Z  M& H0 E7 Rmysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令
4 q, A$ b" J( I7 _# a. j1 {之间没有空格;你也能使用--password=your_pass句法指定口令。) $ J, }  \5 ~% U' `- _
如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句 4 R5 i. p/ ?& D0 ?3 O% K
设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语
- z: E0 f$ J( M0 u句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。 ! n" L9 s2 K* e$ L, p
localhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机
4 G9 `+ S, [, |2 x: Z" a而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系
( n/ R: w5 D% d! U4 E# F统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT * ~9 n# s" W% T% I9 Q2 k& Z
-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确 # o; _0 k: g# }. P
地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你 4 i" Z3 P5 b; n
必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一
1 M; t7 ]- M9 ]台的主机上运行一个客户程序,这也是真的。) 9 ^# w! {( b; [0 y8 ^+ y# ]6 y9 Z
当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个 : a, F$ Z! m$ w$ Q) T
Access denied错误,你可能有与user桌有关的问题,通过执行mysql -u root 3 E6 x9 e0 x3 U  I
mysql并且发出下面的SQL语句检查: 9 l4 X$ E4 q  V! l
mysql> SELECT * FROM user; 8 T( O& M; P" k' V+ i$ ^; i0 \6 S

/ H! {: Y8 s: z6 e- ^1 L$ W2 i结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户 8 f, P1 Q& i# P6 K5 R* |
名。 ' v# K6 ~* x% F

- D; }; J4 T1 q; aAccess denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图 4 b, R. s+ e) k& \7 h# z
用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一 # F* h- I% ^0 F1 O; T$ j/ ?
个条目,正确地匹配在错误消息给出的主机名和用户名。
2 j5 |! S5 O6 w7 a如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列 6 L! z; R/ J2 Y
错误,那么在user表中没有匹配那台主机行: 5 A2 V2 I# {9 B" f; T* h- G
Host ... is not allowed to connect to this MySQL server 2 W2 J0 Z( f% R. v6 z7 `

. [) b* a. ]3 D你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试
+ v) u2 S- F9 I( E  a图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
/ b. o, E3 {; K/ J1 Y你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为   F2 s+ S3 I0 t) G5 l9 q6 ~; Z
Host列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从 1 R2 e* w* \/ b9 Q) Y
客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。( 0 D  [  h+ `. z" x! \1 P! \$ [; t8 B
然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则, 7 I! j0 @6 v& {
你将有一个不安全的系统。)
+ l. ^+ ~$ v8 O$ ]5 p" P; q. T+ R# o) ?- U% H# _
如果mysql -u root test工作但是mysql -h your_hostname -u root test * ]4 F) C1 H1 d# E/ ]
导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的
: K2 ]( Q7 ^8 [1 }$ \; N一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统
) Y2 p( ^- r. }" a, r3 M的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有 2 \( n' C4 b+ @1 X9 |
一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet.
5 X! k5 w+ X$ k& s  {+ }+ M0 ^se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作 - f8 l( t. d! [$ l. Z
为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符
) m3 d" K. r: }2 d6 `7 o/ W如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!)
, u0 S! H, h9 y) K- d* f如果mysql -u user_name test工作但是mysql -u user_name other_db_name . M' Y; I8 W% ~
不工作,对other_db_name,你在db表中没有没有一个条目列出。
  Q; S! P! ^. N4 B0 V3 X, L: t当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其 * g" a5 g+ W, B4 E+ @
它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
: }' B% h9 [, h- d. ?你没有把客户机器列在user表或db表中。
- ]  Y2 G3 e8 C- R! g4 Z如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host
! p! Q8 M; |: m( v% w包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用
& x4 s5 A( d* |5 |Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost
$ ]$ u1 e9 G6 X3 u' n  N/ u" ]从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost'
  _) B4 [, N5 W和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从 0 H2 {; v; r0 m' a" M+ o9 W
localhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和
0 W3 w& ^- P! C: E+ V/ C0 UUser='some_user'的第2个条目,或删除Host='localhost'和User=''条目。 " L5 M! O- t$ s; p+ q
如果你得到下列错误,你可以有一个与db或host表有关的问题: * q5 l  z  S! |: K' V4 F! q! I, T
Access to database denied # e2 H5 L" R) L9 k2 [4 Q5 T
' U5 O% x3 S  A5 O: P
如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多 ) n$ }" L0 S, l' x5 R) x" d) o! f
个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ... 4 S% J! Z- v+ H5 j2 ~8 W0 D6 v
INTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可 9 `5 }7 i3 ^0 g3 S3 u/ ^7 ?
能启用file权限。   Z. q7 C+ j2 y4 i* D  `
6 Q# ?) Z+ J' R$ E' [
记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果
! I5 ^% x  u" m; ?6 h% n2 V: m9 c) B: a当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数, ( t. H% u2 {6 s* z/ B4 X
检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围 / }3 ^" T( p0 c* d7 C2 l& n1 R  I
的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当 6 K% l! T' H5 P
你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选 : q. Z' e3 s1 q+ T8 f6 Y
项文件里指定一个旧的口令!见4.15.4 选项文件。
7 L. z4 e% n) Y7 i: r% y/ F如果任何其它事情失败,用调试选项(例如,--debug=d,general,query) ! ~4 M2 c/ H: _% n2 S* ~* Q9 }
启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每 + ~$ w1 t. u# s) e1 `. @" Y
个命令的信息。见G.1 调试一个MySQL服务器。
+ }' C. h' h* h2 D如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题
# T: Q: }; c( ]到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump
# K, q$ w5 E; X: y' \8 [' qmysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一
8 i: Q" S9 F; E  t些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。 7 A8 I, }2 e# ^
怎样使MySQL安全以对抗解密高手
; [' m3 o7 D0 i, o. c, S# g8 q当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文
3 }5 v3 C; F3 W" y在连接上传输。 1 [# N0 Q: w& B  O: N% s
! j' e) X  d: W5 i* e( H
所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可
+ O* c! ]: ]8 G) w使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全
1 r+ Q& A) C- g9 R! Q* J+ M,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服 : Y; g( T. G. [3 a  u* N
务器与一个MySQL客户之间得到一个加密的TCP/IP连接。 & B7 a( @( H8 F1 ?

- B$ T. R3 ]! ~6 f2 I# Z3 o: ~为了使一个MySQL系统安全,强烈要求你考虑下列建议: ' A. x% [8 P9 f5 Z. T

& ~/ X0 F5 B) G# T: S# s  a5 l对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简 ) ]* w/ @" P- h4 `5 o! x
单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器 % D/ W' J3 F) a% Q
应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通 6 J$ l  d) S: F$ L/ n
过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令, + l. j4 I, K% C+ g
象这样: . I3 i$ f' t" T8 T( t
shell> mysql -u root mysql ; }( H( ~' L. h! r; x( j! R, v
mysql> UPDATE user SET Password=PASSWORD('new_password') 6 c2 @3 `5 h/ R) F
WHERE user='root'; 5 G# J. t) t7 X  ^6 z; N3 n: Q
mysql> FLUSH PRIVILEGES;
; r- ?( T3 T1 Q) Y7 i: Y! `- e5 W7 G6 {+ S7 G  q
不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行,
+ `7 }' z2 W, C0 J你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户 / f& _: h+ P8 N" B3 L$ F
运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix , C% Z. C% l: s$ u0 N) [
用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。 9 `$ C7 I5 [/ ^3 n8 J: W1 R# y
通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行
5 c4 l) d/ N$ U1 O& h) ~  RMySQL。 4 N: w/ q+ N8 i1 ^% Y' Z
如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本
" n; |6 u% s4 L$ e* P. T! Z只能对root是可读的。 3 _& {/ ]  T5 w7 Q4 S0 f# |
检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用
# m, M. d4 J6 y户。 9 B: w0 E! Y5 r+ s' q  L
不要把process权限给所有用户。mysqladmin processlist的输出显示出当 $ x6 C, b4 b5 a, T8 f
前执行的查询正文,如果另外的用户发出一个UPDATE user SET password=
+ e$ E" f/ A/ }& KPASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。
' T, X! Q* }5 c7 \8 \: J4 mmysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用
+ q! {$ {- Z( b0 f+ \! c0 h. x户能登录并检查,即使所有的正常连接在使用。   V+ C8 x. [* j- @2 m" H0 `* @
不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
% ^' t2 X4 U) G$ F8 A进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ... & l6 q2 L; K& A2 q
INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的 4 w! Q  {9 @$ O1 k
文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文 0 N% p2 z. P7 o! X! \: G& @6 _2 I
件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数 9 T* G. Q& u# Z  O8 D) n( v+ e" \
据库表,然后它能用SELECT被读入。 7 N7 G  O/ z' {* D4 P" o
如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则
; P% _1 H, [  q: u上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常
: s% w+ a5 M$ u4 J, ^  U; j小心地使用包含通配符的主机名! ' u& P& t5 J! q  u$ |
下列mysqld选项影响安全:
% w% r3 v; B: M+ m! ~5 E% a  i" L- L3 T6 I4 E* s
--secure
; }+ |; z: K7 [2 _由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来
  s  u( s( Z9 j$ x& E1 W0 x7 h的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也
0 \: D1 M/ j5 C6 x) I7 R' A( L* ?增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时 ! ]. {* ~' ?$ @1 t* w
它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。 ) }% F' K8 H2 A
--skip-grant-tables
- B+ n0 D: U/ T: v8 h这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数
1 a, P; T! L+ J; Z0 ^: I据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器 ) `0 q: S( E/ W( d
再次开始使用授权表。)
' s+ C2 h+ h$ M. t! c( n$ \: T--skip-name-resolve , B4 L, e- B+ o
主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。
0 b8 O0 s$ ]0 ^4 G* l5 J--skip-networking 0 B9 Q. x- Q7 z: {- m3 R
在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
1 s3 `5 R, v  K行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不
9 E. G% h6 c' B; g4 c3 n7 h/ j- D支持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 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。
2 ?6 Q$ H# s& L0 @汗。。( f4 Z2 q+ W) M( `8 n5 `4 X4 r
水平不够,消化不了。。$ o9 L  g8 `0 g' t
不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

本版积分规则

关闭

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

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