下沙论坛

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

QQ登录

QQ登录

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

MySql的权限存取系统

[复制链接]
rcrun 该用户已被删除
跳转到指定楼层
1
发表于 2003-7-26 16:31:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
MySQL有一个先进但非标准的安全/权限系统。本文描述它的工作原理。
3 e9 ]' O# M4 G  i/ ^1 W6 e1 W
; V1 p' F+ Y' l% n  f9 N) v权限系统做什么 $ L6 q4 D& R2 s( q
MySQL权限系统的主要功能是证实连接到一台给定主机的一个用户, 6 l" f& o- b5 Z& y- A6 e5 S' C+ X
并且赋予该用户在一个数据库上select、 insert、update和delete的 / ]* y. s& y" s& s: M. d
权限。 - h& u) ]$ C. r! w% r& B& x
, z, x' x. N6 A* |- ?
附加的功能包括有一个匿名的用户和对于MySQL特定的功能例如
; t% Y% b5 T3 Q+ q7 M# {4 SLOAD DATA INFILE进行授权及管理操作的能力。 3 i' }' F7 D+ L; k
& U, [; f/ U& @
MySQL 用户名和口令
/ Y: u8 E- T* E9 F: I由MySQL使用用户名和口令的方法与Unix或Windows使用的方式有很 1 @# I: i* j9 i3 k: r0 M
多不同之处:
$ U+ o" C( d( ^9 B; y
9 A( M8 D8 a, u5 E9 P# S- {% X& wMySQL使用于认证目的的用户名,与Unix用户名(登录名字)或
1 i$ c7 b# X& Z5 CWindows用户名无关。缺省地,大多数MySQL客户尝试使用当前Unix用户 8 w- b! n" H/ A8 N) g6 _* b
名作为MySQL用户名登录,但是这仅仅为了方便。客户程序允许用-u或- 4 d1 p# G/ ?2 n, d% T
-user选项指定一个不同的名字,这意味着无论如何你不能使得一个数据 4 E+ o4 J4 P8 F' B8 f0 [
库更安全,除非所有的MySQL用户名都有口令。任何人可以试图用任何名 ) U/ \, H8 `& ~9 f5 @. h, x
字连接服务器,而且如果他们指定了没有口令的任何名字,他们将成功。 ' s8 ]% A4 T5 A+ a, x5 X7 b& N
MySQL用户名最长可以是16各字符;典型地,Unix用户名限制为8个字符。 3 P9 u* p8 {9 T- y
MySQL口令与Unix口令没关系。在你使用登录到一台Unix机器口令和你使
) y+ |7 u' |: b用在那台机器上存取一个数据库的口令之间没有必要有关联。 ! l8 }* R, U4 {, [' ~  f2 |5 d2 _; m
MySQL加密口令使用了一个Unix登录期间所用的不同算法。
3 b- x& U* t8 I3 ?+ ^% g! K9 ^7 f/ ^& [" Z  F1 I5 f
与MySQL服务器连接 & r- H4 x, m- a, v5 \' S) H5 k# t6 ~
当你想要存取一个MySQL服务器时,MySQL客户程序一般要求你指定   _# V# f% W( Y, A( ]- F1 h
连接参数:你想要联接的主机、你的用户名和你的口令。例如,mysql ! X# w3 E: |  T9 v
客户可以象这样启动(可选的参数被包括在“[”和“]”之间):   Y# u+ `* d8 W9 p: N1 T0 M
: F) Y: b9 d5 D% E' Q
shell> mysql [-h host_name][-u user_name][-pyour_pass ] 2 Q1 d! x! W8 I& {% o
-h, -u和-p选项的另一种形式是--host=host_name、--user=
1 I5 f* h4 L  K# Juser_name和--password=your_pass。注意在-p或--password=与跟随它
/ X$ _% p9 ]  F. O" W后面的口令之间没有空格。
4 }; D  r* X+ M- t( D: {6 v
& F  U: B$ C% r注意:在命令行上指定一个口令是不安全的!随后在你系统上的任
5 ^  K0 Z+ y7 M- F! z' c4 {( x何用户可以通过打类似这样的命令发现你的口令:ps auxww。 $ h0 o  M6 h" _. H% S0 p

# d, S: p/ Q+ s, R2 y+ r对于命令行没有的联接参数,mysql使用缺省值:
) G4 V8 p' g+ x
0 g' l8 O+ e0 f& S7 ]; d0 A' x' G缺省主机名是localhost。
" b$ Q9 p. d$ R缺省用户名是你的Unix登录名。 ( j8 h- O1 N* m1 B: m- y; X7 @
如果没有-p,则没有提供口令。
/ P* D3 ]. R' T& @这样, 对一个Unix用户joe,下列命令是等价的:
2 C. e# g0 l5 a' P
5 x- v- k- L) C* Xshell>mysql -h localhost -u joe
6 r0 Z# }- f$ E+ f: ~  Nshell>mysql -h localhost ) n% e8 ~7 }6 U$ M0 I+ a% F; C
shell>mysql -u joe 0 S9 Q& {) [- c) A
shell>mysql 1 f1 ^& @% J/ ]; d

5 j1 t- ^) y) l9 \" p9 N0 N其它MySQL客户程序有同样表现。
/ E. Q. C4 d! @0 y  j2 c1 s5 h0 m. ]; O! Y: T
在Unix系统上,当你进行一个连接时,你可以指定要使用的不同的缺 $ |9 o) k( w9 s6 ^/ H5 R
省值,这样你不必每次在你调用一个客户程序是在命令行上输入他们。这 6 w! [- y" p9 e  \2 ]4 O- T
可以有很多方法做到: $ Z$ H; x! V0 X7 I( t

$ d+ t0 F# @) S你能在你的主目录下“.my.cnf”的配置文件的[client]小节里指定 / x8 T. D: W$ P% h
连接参数。文件的相关小节看上去可能像这样:
) L! n9 J- r7 D- m+ E: i1 i[client] ) ~/ Y5 q' J5 G
host=host_name
9 h& Y' Q& K9 z2 D6 H1 N& h& j% B/ kuser=user_name
, W8 _9 t& t% I; M' ypassword=your_pass % O  `) p0 \9 Y! o

  p* g7 O, {! |# C3 U# \! i. b% c你可以用环境变量指定连接参数。主机可用MYSQL_HOST指定,MySQL
0 i' N& p" a' M# J% u3 ?用户名字可用USER指定(仅对 Windows),口令可用MYSQL_PWD指定(但是 $ ^9 w8 P% C( C! N! t' N
这不安全) 。
' `/ ]/ v8 w' {: u$ x% j" `+ l+ ~如果连接参数以多种方法被指定,在命令行上被指定的值优先于在配 1 w8 a# x, y! L' [" F0 @
置文件和环境变量中指定的值,而在配置文件指定的值优先于在环境变量 5 }) `+ F" f* P
指定的值。 9 w+ A& f9 D6 t6 D' g

0 v* g; z3 \* y! A) R5 r9 w$ R0 h使你的口令安全
0 l( b- ~  f2 F* T以一种暴露的可被其他用户发现的方式指定你的口令是不妥当的。
& F  \4 y  H, x当你运行客户程序时,你可以使用下列方法指定你的口令,还有每个方法 1 k" g7 a' n5 v% E( X+ O8 b
的风险评估: # Q% v1 @) g  w
: A# d' B' @: O/ s7 \/ N, R9 Y
使用一个在命令行上-pyour_pass或--password=your_pass的选项。
" p. [; L( f6 t$ @$ g. {! z; B这很方便但是不安全,因为你的口令对系统状态程序(例如ps)变得可见,
+ {  y/ D2 s) M+ q, `3 u它可以被其他的用户调用来显示命令行。(一般MySQL客户在他们的初始化 * ~+ h: u1 B, C  N( F0 z9 `5 H
顺序期间用零覆盖命令行参数,但是仍然有一个短暂间隔时间内参数值可
9 d4 x* d, x9 {* O  b# L& B; P见的。)
! J  E. Y9 E+ ?: m; h$ k) o使用一个-p或--password选项(没有指定your_pass值)。在这种情况 ( [8 j+ I2 J' \
下,客户程序请求来自终端的口令:
$ v5 H0 ^( ~6 u" [* ]& c
+ ^+ b# E) V) z- X9 X  l+ l) Ashell>mysql - u user_name - p * K% e9 e8 D7 ]/ j
Enter password: ******** # g2 B: P7 [7 u' N6 T! A8 M
- w, _3 ?! P! n
客户回应“*”字符到作为输入你的口令的终端使得旁观者不能看见
; h: L, f# K6 q3 P它。因为它对其他用户不可见,与在命令行上指定它相比,这样进入你
; v. K# W3 e* [1 D4 N  N! O* z的口令更安全。然而,这个输入一个口令的方法仅仅为你交互式运行程
$ k) X. k  r1 w) }/ S# ]  F! ]序是合适的。如果你想要从非交互式运行的一个脚本调用一个客户,就
! e! R2 {" _+ ~; h没有从终端输入入口令的机会。
9 O  W  h- s+ b# b8 A- a( [( \3 B$ s/ ~
在一个配置文件中存储你的口令。例如,你可你的主目录的
# K& h7 n& }: b% o0 [( ^“.my.cnf”文件中的[client]节列出你的口令: . p8 p+ D0 A$ `4 x* ^
[client] & V0 ]5 p) O- }% I8 E
password=your_pass
! B7 e) t# G* ]2 m# p. u3 Y# W6 R) Q$ O6 Z1 _; I/ s) ?7 l
如果你在“.my.cnf”里面存储口令,文件应该不是组或世界可读或
$ I& |1 L# w4 d* t可写的。保证文件的存取模式是400或600。见4.15.4 选项文件。
0 D3 r% x$ m4 k2 L. F9 `
2 U( y  a. U: f6 l你可在MYSQL_PWD环境变量中存储口令,但是这个方法必须想到是极
4 F/ _7 m6 ]; q$ A/ b. L% I不安全的且应该不使用。ps的某些版本包括显示运行进程的环境的选项; : `( {) C( j1 a5 H
如果你设定MYSQL_PWD,你的口令将对所有人是显而易见的,甚至在没有
/ G# n$ g, \5 c7 f& l这样一个版本的ps系统上,假设没有其他方法观察到进程环境是不明智
& ~+ g4 w  s# D7 f+ i6 h. y的。 8 i/ O1 G/ M+ s, L# A* h
总之,最安全的方法是让客户程序提示口令或在一个适当保护的“
$ T& H) e4 V6 G2 O- f9 }2 |% M.my.cnf”文件中指定口令。
: s' q% r0 B0 f3 \1 C: `# X3 d: s/ F0 J0 o( P3 h. D3 E
MySQL提供的权限
9 F. X/ Q8 y' G* V  A7 W权限信息用user、db、host、tables_priv和columns_priv表被存储 / l0 E% x8 M4 p2 _( q
在mysql数据库中(即在名为mysql的数据库中)。在MySQL启动时和在权限
# V4 i$ A6 N; _5 d; ^* V5 N' o修改何时生效所说的情况时,服务器读入这些数据库表内容。
' g1 z0 b: f9 Y! V  f0 o2 R# n
, z6 d+ w3 Y; ]0 _. h! q9 [& |由MySQL提供的权限名称显示在下表,还有在授权表中每个权限的表
" I5 s3 B% X2 Y" i; [1 Q8 V/ J列名称和每个权限有关的上下文:
+ z. d$ J6 X% q; M$ T9 r7 ^& o权限 列 上下文 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 在服务器上的文件存取
& h( w- U4 Y& ~( i% t4 W$ d- bselect、insert、update和delete权限允许你在一个数据库现有的
, F9 v, {' o$ ^% |5 T表上实施操作。 - e. Q8 i; Z6 H/ ~9 f
- M$ @9 T$ ^+ G: l6 C
SELECT语句只有在他们真正从一个表中检索行是才需要select权限,
2 T- K% U" {! x; E, b; n+ [你可以执行某个SELECT语句,甚至没有任何到服务器上的数据库里的存
. D( O2 R, T. X取任何东西的许可。例如,你可使用mysql客户作为一个简单的计算器:
. V3 t8 `# Q' ~3 X+ w1 r
/ ]3 g* ^7 W6 x# wmysql> SELECT 1+1; . G) Z7 v7 e8 R$ B: y% s
mysql> SELECT PI()*2; # ~% q( y8 K7 U, w- g& A3 i* [
. F$ o  y1 X4 B3 j3 F2 C# n
index权限允许你创建或抛弃(删除)索引。 * P  d0 F" u7 W' V6 B

9 V; [1 `; S+ n/ ]alter权限允许你使用ALTER TABLE。
6 J8 L2 V7 ^8 y0 A$ Q: K0 g
3 R5 H) r" y  v7 f% a, \create和drop权限允许你创建新的数据库和表,或抛弃(删除)现存的 2 S( B, X" p2 t% e# _- e2 ^8 b
数据库和表。
5 r% b/ k- i0 F9 x" E
4 b3 e7 I& y( q2 e! ^' y注意:如果你将mysql数据库的drop权限授予一个用户,该用户能抛弃 ' G2 d' t) }: k' Y% Z
存储了MySQL存取权限的数据库! ' _, t" w* P" v& F7 B  \
2 N" [0 ^6 y, c, i
grant权限允许你把你自己拥有的那些权限授给其他的用户。
  s. C6 v( p4 z7 s! L1 L2 ~+ I! D2 D
file权限给予你用LOAD DATA INFILE和SELECT ... INTO OUTFILE语句
4 X, ]* x! ]7 x1 u5 n7 Q读和写服务器上的文件,任何被授予这个权限的用户都能读或写MySQL服务 8 d; |! C7 ]# P$ F
器能读或写的任何文件。 1 S  K% H' a7 L( }# D' ?
, T- @, m( }3 G0 _/ G% V4 @
其余的权限用于管理性操作,它使用mysqladmin程序实施。下表显示
$ }' f( ^. a% z' E9 W7 Wmysqladmin支配每个管理性权限允许你执行的命令: 2 ~1 C6 D, M4 C! ~. F; A
优惠 权限拥有者允许执行的命令 reload reload, refresh, flush-privileges, flush-hosts, flush-logs, flush-tables shutdown shutdown precess processlist, kill . F! o$ ?: D6 ~  z
reload命令告诉服务器再读入授权表,refresh命令清洗所有表并打开
" S* m+ s9 m7 P" ]和关闭记录文件,flush-privileges是reload的一个同义词,其它flush-*
" i) I" K  |. C4 ]  h, \' Y命令执行类似refresh的功能,但是范围更有限,并且在某些情况下可能更 8 C& k. h  s6 d  k. b5 H, D4 K7 W
好用。例如,如果你只是想清洗记录文件,flush-logs比refresh是更好的 : d/ q/ W- T9 f0 \
选择。 , y# A# j5 n7 K
8 v. B3 s0 H7 e# c
shutdown命令关掉服务器。
% w, t8 w" P) C" M4 ~, h0 I( l8 c: s# c& A5 s
processlist命令显示在服务器内执行的线程的信息。kill命令杀死服 1 q, U2 x* j' s* \: V
务器线程。你总是能显示或杀死你自己的线程,但是你需要process权限来 4 M' f' q1 W4 a" z7 I' y% A7 z
显示或杀死其他用户启动的线程。
/ y; I% S0 k3 n5 k0 T; {* y# [
8 P/ q0 G7 ^$ H3 E  Q2 K总的说来,只授予权限给需要他们的那些用户是一个好主意,但是你
3 k5 i8 T9 R# t4 P: p- i* D* f应该在授予某个权限时试验特定的警告:   G4 ]6 H# `8 d/ [7 V# l
2 t. G8 `0 ^7 w! S8 W& j( l1 L
grant权限允许用户放弃他们的权限给其他用户。2个有不同的权限并
7 s, A4 ~/ c' E5 U6 f% Q6 e! l有grant权限的用户可以合并权限。 : i( M  n4 q# I  c
alter权限可以用于通过重新命名表来推翻权限系统。
" G! m' z( T* S3 ofile权限可以被滥用在服务器上读取任何世界可读(world-readable,
" a3 U: |# P" N' N( q7 {  X即任何人可读)的文件到一张数据库表,然后其内容能用SELECT被存取。
; E% n3 t. Z& g/ X) ]1 X3 u3 jshutdown权限通过终止服务器可以被滥用完全拒绝为其他用户服务。 9 o( }& ^, M6 A4 ^3 f
precess权限能被用来察看当前执行的查询的普通文本,包括设定或改
1 A& y; S; r. C+ B. i; L& e( @0 B变口令查询。
8 F* h/ u; R% W  m9 C: D1 P! H( I在mysql数据库上的权限能被用来改变口令和其他存取权限信息。(口
1 Z. V& v$ h. H. i1 T6 {' q令被加密存储,所以一个恶意的用户不能简单地读取他们。然而,有足够 6 x& h6 s# ~* Q. N3 J! y! u: c4 _0 h
的权限,同一个用户能用不同的一个代替一个口令。) 6 x! ]( s, d+ j$ b9 A7 P
有一些事情你不能用MySQL权限系统做到: 5 O' l  R" G; b

) u, y6 S+ m) h5 ~6 i% J1 M4 ]你不能明显地指定一个给定用户应该被拒绝存取。即,你不能明显地匹 ) w/ E) o# J8 @. H
配一个用户并且然后拒绝连接。
& O) C& ~1 v/ X4 l; |" I8 r你不能指定一个用户有权创建立或抛弃一个数据库中的表,也不能创建
5 W2 \2 t4 K% F# j3 k1 Y% A) x或抛弃数据库本身。
2 c8 ]& _/ f8 T) U5 B! M权限系统工作原理 ' {5 x9 n0 O+ v6 ~; P) a
MySQL权限系统保证所有的用户可以严格地做他们假定被允许做的事情。 + e) L8 O( w& @
当你连接一个MySQL服务器时, 你的身份由你从那连接的主机和你指定的用
6 S8 G6 A3 H' X5 {% e户名来决定,系统根据你的身份和你想做什么来授予权限。
& t: i; f0 L- ]7 L5 ~6 D
+ P* Q* Z7 C* K* fMySQL在认定身份中考虑你的主机名和用户名字,是因为有很小的原因假 $ p* s: ~2 I( G) }. c8 Y
定一个给定的用户在因特网上属于同一个人。例如,用户从whitehouse.gov % d% s) A' j3 i: o/ M8 G. ~2 }
连接的bill不必和从mosoft.com连接bill是同一个人。 MySQL通过允许你区
8 I8 Y2 B1 M8 f* |1 C( q分在不同的主机上碰巧有同样名字用户来处理它:你可以对从whitehouse.gov ' O0 |5 m1 M% k' r% m+ ~) P# Q
连接授与bill一个权限集,而为从microsoft.com的连接授予一个不同的权限
& X2 \  e$ d, [3 f+ f3 d: }# e+ `. i集。 % c  ?& i( J, _# f9 \6 b

5 R5 E0 G( B2 d) g8 B6 CMySQL存取控制包含2个阶段:
' G* h4 E, ]6 W$ z' ?4 f  |2 h5 R
阶段1:服务器检查你是否允许连接。 6 A" i$ A) T3 }4 `3 U
阶段2:假定你能连接,服务器检查你发出的每个请求。看你是否有足够 / p! G% m; ?4 A
的权限实施它。例如,如果你从数据库中一个表精选(select)行或从数据库抛
( U9 G- J% Y" l7 Q) Q+ {3 k9 ?弃一个表,服务器确定你对表有select权限或对数据库有drop权限。
8 H: _; A+ ^0 F/ D, s; d服务器在存取控制的两个阶段使用在mysql的数据库中的user、db和host 5 r. v$ z6 ^9 l- v% F
表,在这些授权表中字段如下:
& e% q+ V$ {* B9 P表名称 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 . n) }/ P0 I% O* U7 [: r( N: [
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
# K6 }# Q4 {2 W& ?3 X; ^参考tables_priv和columns_priv表。这些表的 8 h( A7 O2 U# x+ L, Q: e$ @
字段如下: & u' Y4 G: j! R* p' l- J! V
表名称 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 & g; }( a# u: }
对存取控制的第二阶段(请求证实),如果请求涉及表,服务器可以另外
1 U7 h: r! N) m4 Y- ~7 O# Z参考tables_priv和columns_priv表。这些表的字段如下:
$ C4 N/ O  Q0 a8 ~+ I7 W, m字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) 5 k- G$ y4 {& Q1 C' r: ^
在user、db和host表中, ' c0 r$ p& X, h1 z. B; n# r; r
所有权限字段被声明为ENUM('N','Y')--每一个都可有值 3 A  k  u2 l6 C( Q( q3 B
'N'或'Y',并且缺省值是'N'.
% Z$ |& ?1 N! @$ E5 M8 b, b" w* S在tables_priv和columns_priv表中,权 . x" h( r. J& R! V, w& E& g
限字段被声明为SET字段: 1 l  N$ T' {* Z6 ?6 h  F
表名 字段名 可能的集合成员 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'
" L8 o8 B3 Z: j( Y0 t6 X8 n每个授权表包含范围字段和权限字段。
3 r: y! J; [( k
% o/ H$ C" A& W范围字段决定表中每个条目的范围,即,条目适用的上下文。例如,
- O, s7 ^1 Z7 \' q+ |: o: T一个user表条目的Host和User值为'thomas.loc.gov'和'bob'将被用于
9 z. V+ ~; `" T证实来自主机thomas.loc.gov的bob对服务器的连接。同样,一个db表条
: F, t7 G! @2 j6 z) N' w目的Host、User和Db字段的值是'thomas.loc.gov'、'bob'和'reports' - Y4 p5 j2 t' u% [  }7 @
将用在bob从主机联接thomas.loc.gov存取reports数据库的时候。
$ w) y0 l! I. `/ etables_priv和columns_priv表包含范围字段,指出每个条目适用的表或
$ x) Z' [4 ]: _3 c& F0 v表/列的组合。 # U: Z7 ]0 r* v+ l; r) M+ O9 G
2 g5 x3 n  M7 Z7 X) K2 z
对于检查存取的用途,比较Host值是忽略大小写的。User、Password、
- ]$ n5 N4 W0 d9 C) S4 D9 K* }* H9 XDb和Table_name值是区分大小写的。Column_name值在MySQL3.22.12或以 # l* B  d- Z: F* d' _& I) @
后版本是忽略大小写的。
7 a. l# p( |3 O4 e& Z
6 z* P& Y) I$ B7 E2 `权限字段指出由一个表条目授予的权限,即,可实施什么操作。服务 % n1 d& s% U0 f: f9 ]) o4 d
器组合各种的授权表的信息形成一个用户权限的完整描述。为此使用的规
3 z1 F2 D1 ]$ |" ?0 S; L7 B则在6.8 存取控制, 阶段2:请求证实描述。
4 z. }/ R) z% _: j
! z4 j# @6 I3 @" j% [" v+ @$ X范围字段是字符串,如下所述;每个字段的缺省值是空字符串:
3 O4 h% k. ?/ ]+ R- _2 m字段名 类型 Host CHAR(60) User CHAR(16) Password CHAR(16) Db CHAR(64) (tables_priv和columns_priv表为CHAR(60)) 4 I7 A+ V6 T' X: j4 p/ ]1 n! L
在user、db和host表中,所有权限字段被声明为ENUM('N','Y')--每一 7 S6 T* _' @3 Y& d# c8 `
个都可有值'N'或'Y',并且缺省值是'N'.
/ M( N7 N, p# u2 a! `7 T( a9 m8 \1 U8 X- K- b! j) Q( t# Z( O
在tables_priv和columns_priv表中,权限字段被声明为SET字段:
- s3 o9 f2 f: b4 s1 D9 a表名 字段名 可能的集合成员 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 E- ~8 o  n9 o& b9 {
简单地说,服务器使用这样的授权表: 7 p6 n: ]9 {/ v* f) W

. O# u7 W1 {. [0 Puser表范围字段决定是否允许或拒绝到来的连接。对于允许的连接,
3 W2 t( T- Q1 j/ J权限字段指出用户的全局(超级用户)权限。
; e3 n: H5 c6 d1 bdb和host表一起使用:
: Z4 Q3 {. u% ^db表范围字段决定用户能从哪个主机存取哪个数据库。权限字段决定
1 u6 M9 k* q8 K; D& B允许哪个操作。 " d0 R( e+ w+ x7 S0 g/ s2 |6 J
当你想要一个给定的db条目应用于若干主机时,host表作为db表的扩
3 L6 [  `7 s4 k; b展被使用。例如,如果你想要一个用户能在你的网络从若干主机使用一个 6 j/ S! T# p4 r4 {7 B
数据库,在用户的db表的Host条目设为空值,然后将那些主机的每一个移
  a, ~! p& I+ G. M& D入host表。这个机制详细描述在6.8 存取控制, 阶段2:请求证实。
& u9 w3 u" v8 O7 B( P& stables_priv和columns_priv表类似于db表,但是更精致:他们在表 . C5 `9 E) u8 _0 C& ]3 x
和列级应用而非在数据库级。
: z  D' u: X" Y& g2 M注意管理权限(reload, shutdown, 等等)仅在user表中被指定。这是 - J1 l7 y" j9 a
因为管理性操作是服务器本身的操作并且不是特定数据库,因此没有理由 , S3 N# Y5 u; q9 ~. t$ o
在其他授权表中列出这样的权限。事实上,只需要请教user表来决定你是
* r0 E: L0 j  P+ s# e8 j5 @, R否执行一个管理操作。
" D7 x' k; g8 o  i1 r; i
& p5 X/ x' ^; C, C% F* W0 Zfile权限也仅在user表中指定。它不是管理性权限,但你读或谢在服 1 P% k% q6 I0 `& p5 k# Z* s, }
务器主机上的文件的的能力独立于你正在存取的数据库。 - a$ H% }* `0 c6 L  t9 C

3 e; @; o6 [% S: N' c' |当mysqld服务器启动时,读取一次授权表内容。
5 ^2 i, y' Q* [" Q3 T0 d" L; k+ C# s7 H4 ~4 I8 @
当你修改授权表的内容时,确保你按你想要的方式更改权限设置是一
* V% y; `- ~3 `个好主意。 9 D: Z/ w+ e3 ^: F( ^. ^
; n8 J( b+ z9 c
一个有用的诊断工具是mysqlaccess脚本,由Carlier Yves 提供给
& ]5 W: ?6 |" f; K  o9 WMySQL分发。使用--help选项调用mysqlaccess查明它怎样工作。注意:
' x7 {6 Q8 n& C0 d9 Zmysqlaccess仅用user、db和host表仅检查存取。它不检查表或列级权限。 # g$ e1 b! T# C
* [, V% p9 t+ |0 A" a
存取控制, 阶段1:连接证实 * m  o% ~$ Z2 q) ^+ X. s
当你试图联接一个MySQL服务器时,服务器基于你的身份和你是否能 . t: O$ m7 J7 M0 i5 \( A
通过供应正确的口令验证身份来接受或拒绝连接。如果不是,服务器完全 8 {. ^( B0 m3 r/ Y6 g7 I5 j" s
具结你的存取,否则,服务器接受连接,然后进入阶段2并且等待请求。 ( r, ]3 Y% {1 L" U; J

) L- s: ]9 N+ \  i& Q你的身份基于2个信息:
4 C0 O! g. G1 |9 ]" Q1 Z& Q
, p% g1 [* @6 f: ]) i你从那个主机连接
' m; K7 q3 z1 |- A: _你的MySQL用户名
0 ~& Z( T6 X3 T/ E7 {2 }/ P身份检查使用3个user表(Host, User和Password)范围字段执行。服
) N% H8 [6 C8 s+ |+ i务器只有在一个user表条目匹配你的主机名和用户名并且你提供了正确的
; ~* U% B& Z3 `0 t2 n$ k口令时才接受连接。   w, n! p/ @& w* k% l4 m$ p
, _2 b# |! e6 H1 }% b/ m8 f! ]
在user表范围字段可以如下被指定:
4 G; i6 {6 t0 T. v( R  }
, \- M3 i( [5 Q3 x$ |" e一个Host值可以是主机名或一个IP数字,或'localhost'指出本地主机。 0 v1 n4 I4 T1 X$ s# ~, \% Z" r
你可以在Host字段里使用通配符字符“%”和“_”。 , ^  ]6 F0 u: u9 R/ |
一个Host值'%'匹配任何主机名,一个空白Host值等价于'%'。注意这些 8 M* Q; }  Y/ J) p0 c0 v0 j0 @
值匹配能创建一个连接到你的服务器的任何主机! # a+ d* v2 `& ~. g% q4 t4 r/ v- F
通配符字符在User字段中不允许,但是你能指定空白的值,它匹配任何 7 M: i) N5 Y! l, W* K
名字。如果user表匹配到来的连接的条目有一个空白的用户名,用户被认为
8 x% D( i; E; ]& G) M: ?是匿名用户(没有名字的用户),而非客户实际指定的名字。这意味着一个空
4 F8 a, Q1 \1 p! b. L8 h# E白的用户名被用于在连接期间的进一步的存取检查(即,在阶段2期间)。 % L. }! W: m( y1 U
Password字段可以是空白的。这不意味着匹配任何口令,它意味着用户
, G  T6 f- G: W: I8 V0 l+ T必须不指定一个口令进行连接。
* R! C+ H2 _) |非空白Password值代表加密的口令。 MySQL不以任何人可以看的纯文本
2 ?: V1 s3 T; J* q2 _! s0 B! b格式存储口令,相反,正在试图联接的一个用户提供的口令被加密(使用
  B6 `3 v5 I+ `! Z- e; d( J5 LPASSWORD()函数),并且与存储了user表中的已经加密的版本比较。如果他 " v$ ^; j' E) |
们匹配,口令是正确的。
; n; e! u- f) z; O
/ v4 d6 M; w% |6 w( g下面的例子显示出各种user表中Host和User条目的值的组合如何应用于到来 * ^. k8 N6 P* f" d6 |9 f
的连接:
) R$ X, D/ X. p6 `
( Q" b4 @0 B8 d' @& qHost 值 User 值 被条目匹配的连接 ; |+ N' k! R0 n& I
'thomas.loc.gov' 'fred' fred, 从thomas.loc.gov 连接 2 L. P" I5 v  T+ ^
'thomas.loc.gov' '' 任何用户, 从thomas.loc.gov连接
) n  b! \6 l2 X3 k1 m9 M'%' 'fred' fred, 从任何主机连接 " l) W% B( ^; I7 i! Y8 l9 R5 H
'%' '' 任何用户, 从任何主机连接
7 }! n# U" `  ~9 Z% ?, H'%.loc.gov' 'fred' fred, 从在loc.gov域的任何主机连接
! b  _6 b' e% n. D, S) n'x.y.%' 'fred' fred, 从x.y.net、x.y.com,x.y.edu等联接。(这或许
; t. \3 g9 F$ h# V6 O无用) + R& s% b( T, ]0 i% n$ b
'144.155.166.177' 'fred' fred, 从有144.155.166.177 IP 地址的主 . }; Z' Q3 h" Z$ M+ U
机连接 " F7 O8 O1 j7 @8 u# @9 ~& p. t
'144.155.166.%' 'fred' fred, 从144.155.166 C类子网的任何主机连 " u5 t# w: X' U" o) P

0 J# O' M& d: q  k; i
$ y, U' V5 V* Z$ X' t6 w既然你能在Host字段使用IP通配符值(例如,'144.155.166.%'匹配在一个子
% b6 r' N& }' q) w网上的每台主机),有可能某人可能企图探究这种能力,通过命名一台主机 ; D7 }1 I$ t5 e" j$ _; O8 \0 g/ _
为144.155.166.somewhere.com。为了阻止这样的企图,MySQL不允许匹配以
! C$ \' y. q0 l, p! ]- S# N数字和一个点起始的主机名,这样,如果你用一个命名为类似1.2.foo.com的   ^: d! r! Q% v5 ]: d& M( |  S
主机,它的名字决不会匹配授权表中Host列。只有一个IP数字能匹配IP通配 : ^$ y. j& ?+ I0 H, v
符值。 5 }6 p- u+ C* R7 ~0 H& O
/ ]3 D. R, Y. i& y' I7 U
一个到来的连接可以被在user表中的超过一个条目匹配。例如,一个由 $ n" H) T+ I# m  I! V
fred从thomas.loc.gov的连接匹配多个条目如上所述。如果超过一个匹配,
2 X3 R( E5 m4 M/ t& c服务器怎么选择使用哪个条目呢?服务器在启动时读入user表后通过排序来
" N' Q# m  A7 K, k* d解决这个问题,然后当一个用户试图连接时,以排序的顺序浏览条目,第一
6 ?. v; B6 f8 h' i个匹配的条目被使用。
1 I# Q8 @. J4 G
4 c. P- S" Z: B* puser表排序工作如下,假定user表看起来像这样:
3 Z& }% e9 W' U' k2 F' A2 V! p
8 W9 q1 `4 x: Q1 X. `* {( I8 P& L1 ?) c# a6 z* P8 s. w& i
+-----------+----------+- * r% T- @" c" ~$ N) x' p; e
│ Host │ User │ ... 9 F2 {9 s% H* |' u
+-----------+----------+- 0 n1 v9 m" N  b# R9 ?, _2 b' s
│ % │ root │ ... " u* q3 x. }; v0 O( X
│ % │ jeffrey │ ...
( y1 G& h5 N2 D! p6 x) O# P7 n, {│ localhost │ root │ ... ) v6 q( ~! t& O; b$ l/ n
│ localhost │ │ ... # _+ Z$ S0 f3 U! L2 x! h* h& g
+-----------+----------+- ) a& h! @! W8 z9 P) q. A
, {* w, y% D8 p# y
当服务器在表中读取时,它以最特定的Host值为先的次序排列('%'在 * ^  q0 t& k* w2 x# h
Host列里意味着“任何主机”并且是最不特定的)。有相同Host值的条目以
8 ^5 ~' i, J& j/ M) z  M, f  l最特定的User值为先的次序排列(一个空白User值意味着“任何用户”并且
* C. `6 r4 @7 ^6 V2 k% a0 P2 s( e是最不特定的)。最终排序的user表看起来像这样:
4 c+ [  g  b5 T! [* ]* G4 C/ c
' X+ _3 Q) A' X# N6 C' n# C8 r
( L7 r: ~6 E4 k3 l+-----------+----------+-
! |# G# Y; V6 ]: K0 Z+ `2 V. _│ Host │ User │ ... 1 I: g& ^5 e3 W) v* H4 e# {
+-----------+----------+- 3 }: T3 a" l; J' a4 \# i
│ localhost │ root │ ...
) b/ [+ l! a# i) d1 w$ Z) F; S│ localhost │ │ ...
+ d% {) A2 {5 O8 y* }6 b% @, b│ % │ jeffrey │ ... 6 l6 y& ]2 A6 j* U
│ % │ root │ ...
5 X: Y& D" W2 v+-----------+----------+- * m/ R% }% f1 N% b2 N/ S
: ^5 F. M- G3 L  L  z! I9 U
当一个连接被尝试时,服务器浏览排序的条目并使用找到的第一个匹
* x/ ]; R0 H, g配。对于由jeffrey从localhost的一个连接,在Host列的'localhost'条目 1 H3 c6 ~7 R4 z. y- C
首先匹配。那些有空白用户名的条目匹配连接的主机名和用户名。('%'/
9 c" A: g: O9 h- n'jeffrey'条目也将匹配,但是它不是在表中的第一匹配。)
$ U  I+ g/ R6 w# ]' V" v8 B; J
# f4 `" p" P/ a; L  B这是另外一个例子。假定user桌子看起来像这样:   n$ Q# Z% P4 y+ T' c
; u6 M$ v) o& x8 ?
' N/ z, v* |  O
+----------------+----------+-
4 S7 f+ w5 I& i& G5 ~│ Host │ User │ ...
. v- x0 G" ]& A# u+----------------+----------+-   t! [0 @/ X% N% l" M5 W1 b0 k
│ % │ jeffrey │ ...
+ x9 U9 D9 J" p& A9 o│ thomas.loc.gov │ │ ...
" s. I7 u  a. x  X9 j( @3 N# S+----------------+----------+-
( Y+ ~% l7 U( g* [/ L8 }4 r% c4 b; L# s, E/ P; F8 |5 K
排序后的表看起来像这样: ) x( Y* Q+ L% W. D
9 u# V5 g) W& I- r) i; G/ a" F
' n- N, n" L5 i8 _/ |- T
+----------------+----------+-
$ R: ?# K; {% e4 Y│ Host │ User │ ...
7 K: ^4 b5 h2 B0 a  }' x( \+----------------+----------+-   e8 o( t  ]& o& n7 \% U
│ thomas.loc.gov │ │ ... * Q: _& X% x7 I) W
│ % │ jeffrey │ ...
% L4 z) P7 t8 J# l' q+ Z+----------------+----------+- & u+ V# x# S8 `% F9 }8 J
6 @+ H) Y  e1 E# ]' m
一个由jeffrey从thomas.loc.gov的连接被第一个条目匹配,而一个由 . f5 y! V: _6 y
jeffrey从whitehouse.gov的连接被第二个匹配。
  o7 I+ L. r/ }. J$ d# n9 N# {9 c5 G. g7 M: W8 _9 R3 W  k7 Z) C
普遍的误解是认为,对一个给定的用户名,当服务器试图对连接寻找 8 J6 ~# K* G: ?& U
匹配时,明确命名那个用户的所有条目将首先被使用。这明显不是事实。
1 q% N# i3 b8 A: B' x# N; m7 x3 k先前的例子说明了这点,在那里一个由jeffrey从thomas.loc.gov的连接没
/ {( F$ w' U) m被包含'jeffrey'作为User字段值的条目匹配,但是由没有用户名的题目匹
3 Q& Q5 {9 I1 w$ n配!
8 I, P$ u9 k! Y: v% W& _8 o  O7 c/ u: P' r) b6 V1 m
如果你有服务器连接的问题,打印出user表并且手工排序它看看第一个
% G5 h5 ^; T& Q$ e匹配在哪儿进行。 & F6 x# G$ w8 E/ T/ N% Q
1 h9 ], Y( {3 i, [. a
存取控制,阶段2:请求证实 1 L( ^& g3 z4 Q0 x
一旦你建立了一个连接,服务器进入阶段2。对在此连接上进来的每个
1 N9 ^, Z0 j! u+ |( ~+ D3 L! u" ~( w$ G请求,服务器检查你是否有足够的权限来执行它,它基于你希望执行的操作 9 R) ]8 x) ~" M- a- t" ]: M8 |
类型。这正是在授权表中的权限字段发挥作用的地方。这些权限可以来子
6 T, \( a0 k2 @$ @user、db、host、tables_priv或columns_priv表的任何一个。授权表用
! ~) T! I2 i$ V/ N" T9 }GRANT和REVOKE命令操作。见7.26 GRANT和REVOKE 句法。(你可以发觉参 6 F' X+ O& Q1 r* `8 p
考6.6 权限系统怎样工作很有帮助,它列出了在每个权限表中呈现的字段。) ' W5 M& }! G0 Z6 }; I+ H

0 U% ?# n; d2 _; N, G; n% fuser表在一个全局基础上授予赋予你的权限,该权限不管当前的数据库
" e6 n7 }: j! f0 I4 {( f* o是什么均适用。例如,如果user表授予你delete权限, 你可以删除在服务器
; z3 F; ]1 Z1 {# w主机上从任何数据库删除行!换句话说,user表权限是超级用户权限。只把
* l" R9 r+ a, O8 b* uuser表的权限授予超级用户如服务器或数据库主管是明智的。对其他用户, 7 F! d' G" B3 i5 d6 L2 {9 s
你应该把在user表中的权限设成'N'并且仅在一个特定数据库的基础上授权, ' m; M* e# j5 r! h. Z- t' U( T
使用db和host表。 - x/ ]0 }# f( z

& V: H$ B5 u! N% fdb和host表授予数据库特定的权限。在范围字段的值可以如下被指定:
9 h/ f$ b% u0 ~# T' g, u. `# s% Z
( v2 o" R' S: W& Y( c' p: V& e通配符字符“%”和“_”可被用于两个表的Host和Db字段。
* k& D* K# A: @  j在db表的'%'Host值意味着“任何主机”,在db表中一个空白Host值意味 / z$ _' f# z+ R8 Q# m) Q* Q) _
着“对进一步的信息咨询host表”。
! u. t& p; A3 s1 F* `! q; h在host表的一个'%'或空白Host值意味着“任何主机”。 1 o9 u, I# l+ @3 j. O' r1 M# ~1 ]7 S
在两个表中的一个'%'或空白Db值意味着“任何数据库”。
+ U; a1 z; k: |2 t在两个表中的一个空白User值匹配匿名用户。 % E3 U+ D8 i& e
db和host表在服务器启动时被读取和排序(同时它读user表)。db表在Host   F0 V& v: H. H: j/ X0 G2 g$ S
、Db和User范围字段上排序,并且host表在Host和Db范围字段上排序。对于
; x( P. @! I# C& j3 wuser表,排序首先放置最特定的值然后最后最不特定的值,并且当服务器寻找 & K& i# C2 s8 V/ J
匹配入条目时,它使用它找到的第一个匹配。
9 r% u: ~' p" D! f5 Z
2 c* I% h0 k4 M) c+ v1 Atables_priv和columns_priv表授予表和列特定的权限。在范围字段的值可 / @4 {2 {4 h! Q+ d
以如下被指定: 0 u. m, k5 m% t! b4 M$ T* M$ D
, D" W4 F- w( R, y
通配符“%”和“_”可用在使用在两个表的Host字段。 " Y9 i/ o& C- Z& Y! I% L' K
在两个表中的一个'%'或空白Host意味着“任何主机”。
. ]8 Q) S, z7 |- [, L" J: Y4 j) G在两个表中的Db、Table_name和Column_name字段不能包含通配符或空白。
4 J# o5 i6 E' dtables_priv和columns_priv表在Host、Db和User字段上被排序。这类似于
1 x8 T2 K) F1 x& xdb表的排序,尽管因为只有Host字段可以包含通配符,但排序更简单。
" j# u. ^4 Z4 p4 j; \& I% ]
6 i0 [5 x$ |! Y$ y- s4 J* m- M. c" \请求证实进程在下面描述。(如果你熟悉存取检查的源代码,你会注意到这 5 C( C2 v0 k' {0 F2 _/ Z
里的描述与在代码使用的算法略有不同。描述等价于代码实际做的东西;它只是
) D$ ^" Q2 j4 d, M2 I不同于使解释更简单。)
& Q7 Q! ~( [8 C& N5 u, ^7 U, C* U6 Q1 ^& Y
对管理请求(shutdown、reload等等),服务器仅检查user表条目,因为那是 ! f9 N: R0 ?. K+ w
唯一指定管理权限的表。如果条目许可请求的操作,存取被授权了,否则拒绝。
5 g8 S) g1 Z3 y* ]+ J/ y例如,如果你想要执行mysqladmin shutdown,但是你的user表条目没有为你授
5 k7 V3 w$ O% C+ O+ T% R予shutdown权限,存取甚至不用检查db或host表就被拒绝。(因为他们不包含
$ ]* Y0 f: R% }  T- v% lShutdown_priv行列,没有这样做的必要。)
# I5 G# Z1 b  T5 e: t2 o5 j. B( A0 ^2 f0 n2 G
对数据库有关的请求(insert、update等等),服务器首先通过查找user表   l5 W# {# V! J2 @9 h4 R
条目来检查用户的全局(超级用户)权限。如果条目允许请求的操作,存取被授
0 u- h  T2 }# v; j权。如果在user表中全局权限不够,服务器通过检查db和host表确定特定的用
. v6 h0 ]  ~! E- S- @户数据库权限:
/ \& L& ^# r; _% T
) H0 D7 F( z! l9 i' k服务器在db表的Host、Db和User字段上查找一个匹配。 Host和User对应连
7 _) v6 n; N6 \/ `接用户的主机名和MySQL用户名。Db字段对应用户想要存取的数据库。如果没有
8 r3 O5 r4 Z, k$ v( N1 ^7 a5 Z8 cHost和User的条目,存取被拒绝。 ) ~; @( r2 J0 `% ^$ L  V9 E
如果db表中的条目有一个匹配而且它的Host字段不是空白的,该条目定义用
! S0 A+ _) v% o4 @7 ~% z+ o$ T! n户的数据库特定的权限。
  g+ o4 ~1 f/ X- G. [. l如果匹配的db表的条目的Host字段是空白的,它表示host表列举主机应该被 9 H' P0 c. l8 g4 ?3 k3 v
允许存取数据库的主机。在这种情况下,在host表中作进一步查找以发现Host和
' h* B! U, d+ d2 DDb字段上的匹配。如果没有host表条目匹配,存取被拒绝。如果有匹配,用户数 ' `$ }7 W  r( G6 b8 h
据库特定的权限以在db和host表的条目的权限,即在两个条目都是'Y'的权限的交
5 W& {- ?  F$ v集(而不是并集!)计算。(这样你可以授予在db表条目中的一般权限,然后用host ( d  L1 L; N0 W4 R4 y! \
表条目按一个主机一个主机为基础地有选择地限制它们。) 8 z. c+ U. v& ]+ k3 b& x, c% i, C' ~
在确定了由db和host表条目授予的数据库特定的权限后,服务器把他们加到
& E: k7 @& [% p* V4 H7 R( e由user表授予的全局权限中。如果结果允许请求的操作,存取被授权。否则,服 6 B) r8 f; j4 [( M
务器检查在tables_priv和columns_priv表中的用户的表和列权限并把它们加到
2 S5 y$ Z6 R6 h. e+ ~用户权限中。基于此结果允许或拒绝存取。
( z4 F- `7 S+ [/ W! \4 v. g: w# y, _2 d
用布尔术语表示,前面关于一个用户权限如何计算的描述可以这样总结:
4 b4 p1 h: {" ~) P' q0 W) |: w/ |7 q; m& L/ J$ |
global privileges . b  c/ A* G& t) y/ W
OR (database privileges AND host privileges)
) w5 `% z' F! K# B0 j/ A6 KOR table privileges 8 z0 ]% b6 g( J7 _4 _9 w, d" S
OR column privileges
6 r( J+ n, E# t
' y0 X3 Y5 W  \' V) @. h它可能不明显,为什么呢,如果全局user条目的权限最初发现对请求的操作不 " u: }1 P$ T' D. e& I
够,服务器以后把这些权限加到数据库、表和列的特定权限。原因是一个请求可能 + I0 M. X6 e8 \+ W
要求超过一种类型的权限。例如,如果你执行一个INSERT ... SELECT语句,你就都 " E  _1 t% s" z9 _
要insert和select权限。你的权限必须如此以便user表条目授予一个权限而db表条 7 G9 u, i5 n/ d
目授予另一个。在这种情况下,你有必要的权限执行请求,但是服务器不能自己把
" F# _: Z1 T% m# I4 c两个表区别开来;两个条目授予的权限必须组合起来。 9 t: c5 D" C$ }5 h5 K

$ S* c% Q  n0 D# ^9 \/ k1 Uhost表能被用来维护一个“安全”服务器列表。在TcX,host表包含一个在本
$ o. B6 v% i# u( V7 w8 {: j: X3 m2 E& b地的网络上所有的机器的表,这些被授予所有的权限。
1 U& ]0 V4 I' J) @
' {5 [/ g. ]0 `- K+ P& q: ?% c; Y你也可以使用host表指定不安全的主机。假定你有一台机器public.your.
6 ^, l. V; R# x  p6 ~/ Zdomain,它位于你不认为是安全的一个公共区域,你可以用下列的host表条目子允
2 R* f  l- _8 d8 }$ Y% j许除了那台机器外的网络上所有主机的存取:
: o1 p3 A$ p1 [% ^; l6 N! N0 q! a' r8 f1 G
* m# s( V! I4 O5 q3 g% G
+--------------------+----+-
( r8 [+ y/ f* w8 v3 X2 l& g6 `; H2 _│ Host │ Db │ ... 7 n, g4 w5 a7 [" {5 r
+--------------------+----+-
0 t( b* Z. D2 w( R( U│ public.your.domain │ % │ ... (所有权限设为 'N') 6 n. H5 }( C# Y! q$ R9 B
│ %.your.domain │ % │ ... (所有权限设为 'Y')
' y' l* U/ Y9 j: |0 O4 Z+--------------------+----+-
  l6 U* U; h/ S4 R1 Y+ p
9 u5 P7 e7 a& E. i当然,你应该总是测试你在授权表中的条目(例如,使用mysqlaccess)让你确保 2 `  F/ j  Z* L- c2 N8 ]; C
你的存取权限实际上以你认为的方式被设置。 3 P& N& E, x9 n- ?" `+ M. N

1 t2 H; y; i5 o6 O  L- b权限更改何时生效
# c5 g2 c) N; H/ K当mysqld启动时,所有的授权表内容被读进存储器并且从那点生效。 + [  P5 r% f: t( l8 P/ ^3 u
! H  Q2 [) t! O. j
用GRANT、REVOKE或SET PASSWORD对授权表施行的修改会立即被服务器注意到。
) E7 R! u" H* @+ \' T, t
- A& d4 x: Z% r5 C6 m如果你手工地修改授权表(使用INSERT、UPDATE等等),你应该执行一个FLUSH + ^0 Q* b2 f9 J8 l: Q- y1 |
PRIVILEGES语句或运行mysqladmin flush-privileges告诉服务器再装载授权表,否
9 o$ h( g, U! D$ R$ U7 h则你的改变将不生效,除非你重启服务器。 : }( I% M  N: M* N$ ]2 u
2 s! ]% `* y% f# P( \: w9 m+ F
当服务器注意到授权表被改变了时,现存的客户连接有如下影响:
9 B9 V' u8 r8 L8 C  W- K& u1 m) j- z
表和列权限在客户的下一次请求时生效。 $ S& k' s, e6 M$ M1 O3 i$ v% m3 z
数据库权限改变在下一个USE db_name命令生效。 0 b- c; V; p4 S! C1 {
全局权限的改变和口令改变在下一次客户连接时生效。
  u1 N* j) N$ G' p& `/ o; Y+ D0 W3 M* U2 u5 T
建立初始的MySQL权限 8 F5 d" V6 B) F1 l
在安装MySQL后,你通过运行scripts/mysql_install_db安装初始的存取权限。
" l/ N& x( i$ Oscripts/mysql_install_db脚本启动mysqld服务器,然后初始化授权表,包含下列
+ w5 m" K% o8 q. G5 u权限集合: ; x+ V$ ^8 u% C) p" ]' V

8 G9 m: M  F. Q- `MySQL root用户作为可做任何事情的一个超级用户被创造。连接必须由本地主
2 S2 N: ~4 I) T0 O机发出。注意:出世的root口令是空的,因此任何人能以root而没有一个口令进行 7 {' n8 h5 F' {" Y" x8 O9 j
连接并且被授予所有权限。 . A9 t( M: ~  Y! s! _
一个匿名用户被创造,他可对有一个'test'或以'test_'开始的名字的数据库 " d4 X# I6 O/ C3 ^( m
做任何时期事情,连接必须由本地主机发出。这意味着任何本地用户能连接并且视
& B$ ?% _6 i2 g& A4 [, P/ `# i$ _0 j为匿名用户。 ' P$ K2 f6 @+ I& h
其他权限被拒绝。例如,一般用户不能使用mysqladmin shutdown或
1 y3 T( a/ e% b- Z$ T- Xmysqladmin processlist。
& E! ^# a: c; ^0 e3 O注意:对Win32的初始权限是不同的。 0 W0 T% X9 K; b' I

) q7 _5 l/ S6 J. i既然你的安装初始时广开大门,你首先应该做的事情之一是为MySQL root用户
* z. j! E& K8 Y) w" _指定一个口令。你可以做如下(注意,你使用PASSWORD()函数指定口令):
5 M6 M+ s# i: \3 B% `
8 y. h& R4 D' P0 G4 P# A4 rshell> mysql -u root mysql 4 R! A9 `! `4 f' G. g: S
mysql> UPDATE user SET Password=PASSWORD('new_password')
& g6 a2 I1 {/ i, N! bWHERE user='root';
4 V0 D8 G8 j1 m# emysql> FLUSH PRIVILEGES;
& g* `0 q" h* S5 y+ f- U* W
3 u! A: \- J4 n9 |$ I在MySQL 3.22和以上版本中,你可以使用SET PASSWORD语句:
; g2 B) B' H4 C, r; F
' K& d) S% _" E9 P& Gshell> mysql -u root mysql + m# B0 {, U& p2 [" {' @1 Y
mysql> SET PASSWORD FOR root=PASSWORD('new_password'); ' Z" n1 h; f1 r! o
- m0 F( ?1 B, I
设置口令的另一种方法是使用mysqladmin命令: ; r4 b: J; C4 D% @

0 w$ u5 f( T; C2 n2 ^shell> mysqladmin -u root password new_password 1 I  c) y/ `& h* I+ ^) P+ G
5 b  m; Z+ d0 M% d% o2 L6 Y
注意:如果你使用第一种方法在user表里直接更新口令,你必须告诉服务器
- F9 ]2 o9 Y' ?2 ^+ ^3 z2 v/ r9 m再次读入授权表(用FLUSH PRIVILEGES),因为否则改变将不被注意到。 : E* z5 ~/ x: u4 e  b
3 X* P8 L' j; s
一旦root口令被设置,此后当你作为root与服务器连接时,你必须供应那个
6 c) O& G0 W" A1 \: m  }口令。
, t8 o4 M& k3 Z' A; B5 }5 L  ]" S
你可能希望让root口令为空白以便当你施行附加的安装时,你不需要指定它
: q/ K8 ^* L0 B, V5 Q4 k) r/ J. O或测试,但是保证在任何真实的生产工作中使用你的安装之前,设置它。
  a- x: ~2 Q" N' e' d  [6 ~1 i' y# |% H; D! S' C2 R; V
看看scripts/mysql_install_db脚本,看它如何安装缺省的权限。你可用它 8 W5 S5 \2 ^; L& H* u5 s
作为一个研究如何增加其他用户的基础。 - V' k: R0 z3 U' |

3 p9 T) W6 K- I4 T9 x如果你想要初始的权限不同于上面描述的那些,在你运行mysql_install_db ' c  L+ I# q' @# _4 G
之前,你可以修改它。   M, u, U7 _5 W0 N  E
# C" K, N: n/ m
为了完全重建权限表,删除在包含mysql数据库的目录下所有“*.frm”, : |1 x- j9 B& G/ w2 S' w' D
“*.MYI”和“*.MYD”文件。(这是在数据库目录下面命名为“mysql”的目录,
" Q6 C/ k# A0 f当你运行mysqld --help时,它被列出。)然后运行mysql_install_db脚本,可能 " h/ @6 A/ ?; n: A# M6 B
在首先编辑它拥有你想要的权限之后。 & ]0 Z# r+ n# Y$ p% a* I
3 u6 O  z, h9 j+ @/ ^! j, W
注意:对于比MySQL 3.22.10旧的版本,你不应该删除“*.frm”文件。如果 % Q' e+ k# Y. N, S+ r
你偶然做了,你应该在运行mysql_install_db之前你的MySQL分发中拷回它们。
- A( X% Z+ `4 p9 t+ ^; U6 J: X" }4 t: z* j: D8 @
向MySQL增加新用户权限 7 D4 d' b* Y, u3 X8 U
你可以有2个不同的方法增加用户:通过使用GRANT语句或通过直接操作MySQL授 + Q2 _7 u0 s; @6 o; _7 ~0 H- k
权表。比较好的方法是使用GRANT语句,因为他们是更简明并且好像错误少些。 ( t1 `  K8 {7 n/ P1 d

: f6 G4 c) k; Q- L1 f+ y, Q下面的例子显示出如何使用mysql客户安装新用户。这些例子假定权限根据以前
5 G) Y5 H. x. @2 T& t的章节描述的缺省被安装。这意味着为了改变,你必须在mysqld正在运行同一台 ( _8 D  r7 u# |" E# x
机器上,你必须作为MySQL root用户连接,并且root用户必须对mysql数据库有 - ]$ A. Y5 M+ z3 Z  I/ E( m
insert权限和reload管理权限。另外,如果你改变了root用户口令,你必须如下
8 F) f" y( J3 l2 r的mysql命令指定它。
6 e, c5 B, C5 b8 a& @/ Y6 ^8 D6 ~7 H" O8 M& O: C- ?# b6 R* z7 R0 q
你可以通过发出GRANT语句增加新用户:
5 M' p$ s- N  T( U9 N8 N6 g" x5 R; M5 s8 R; U  U
shell> mysql --user=root mysql   d: E( |/ r! s/ ~# W2 s
mysql> GRANT ALL PRIVILEGES ON *.* TO monty@localhost % V* o; j5 Q7 m# U# C# i) ]
IDENTIFIED BY 'something' WITH GRANT OPTION;
! d3 ^0 F, [4 b1 S1 `8 xmysql> GRANT ALL PRIVILEGES ON *.* TO monty@"%"
6 Y% Q4 F( ^* v4 ]% D9 i4 EIDENTIFIED BY 'something' WITH GRANT OPTION; & P0 U5 X! m) \4 J, b+ z
mysql> GRANT RELOAD,PROCESS ON *.* TO admin@localhost; 7 R; ?: Y+ l# S- M7 L
mysql> GRANT USAGE ON *.* TO dummy@localhost;
0 {5 Y: u. a2 k: ~. {
5 F* y2 c' l/ E) e2 {这些GRANT语句安装3个新用户: 7 C0 D" b' _- R
3 J& h) v% p- ]  `& n) V
monty
+ B' @; v4 [. Q. l. J  ~: _5 b4 X可以从任何地方连接服务器的一个完全的超级用户,但是必须使用一个
9 `) [8 f7 Z( U. @5 v$ Q口令('something'做这个。注意,我们必须对monty@localhost和monty@"%"
' \6 R2 Q" v5 F! U发出GRANT语句。如果我们增加localhost条目,对localhost的匿名用户条目
  L# }: m' O; S4 y在我们从本地主机连接接时由mysql_install_db创建的条目将优先考虑,因为 ; }( V! W4 i# [7 @  y
它有更特定的Host字段值,所以以user表排列顺序看更早到来。 : G1 O! N( X, N" n! A& W1 n
admin ; ]$ ?( e- A' V4 a& ]4 N$ a5 [
可以从localhost没有一个口令进行连接并且被授予reload和process管理
+ V" A& F6 W: P# v权限的用户。这允许用户执行mysqladmin reload、mysqladmin refresh和
8 u7 q0 _; }* f, Emysqladmin flush-*命令,还有mysqladmin processlist。没有授予数据库有
: N( m+ r' a9 R0 E% I" R5 v关的权限。他们能在以后通过发出另一个GRANT语句授权。 ( G' P0 S* @* d; N, G
dummy 6 Y6 ^+ m( _% T+ q& F; M9 G
可以不用一个口令连接的一个用户,但是只能从本地主机。全局权限被设
* @$ h$ g* V0 f置为'N'--USAGE权限类型允许你无需权限就可设置一个用户。它假定你将在以 1 Z7 U; |+ R* x% r$ r' {% p( S1 I
后授予数据库相关的权限。 & k, ~4 z$ ^* B* c) G
你也可以直接通过发出INSERT语句增加同样的用户存取信息,然后告诉服
0 C3 _: o6 r- m务器再次装入授权表: . W' ^  q8 h9 E0 f
. }- u: e  t8 `2 D
shell> mysql --user=root mysql 7 R4 s$ L) @( T: _
mysql> INSERT INTO user VALUES('localhost','monty',PASSWORD ; C: X* k  E3 E5 Z. ~
('something'),
9 e0 v9 N% s& O/ g! O6 K'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y', 3 @- H8 L1 V6 j& O0 a0 s
'Y','Y') & O7 A( M6 B0 N' K
mysql> INSERT INTO user VALUES('%','monty',PASSWORD('something'), / I" e! K& W8 a6 Y! H7 {) A
'Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y',
5 T/ O- b$ x. @, a, o% s1 W'Y')
. B+ ^' E2 r* vmysql> INSERT INTO user SET Host='localhost',User='admin', 1 y. W' i9 I, K4 z9 G6 }5 c
Reload_priv='Y', Process_priv='Y'; % v3 L8 W6 n: ?  W
mysql> INSERT INTO user (Host,User,Password) 5 s) x5 ~7 v  W8 J3 |
VALUES('localhost','dummy','');
5 u5 C2 ~6 ~2 B  K5 Vmysql> FLUSH PRIVILEGES;
/ \4 y( A9 ?0 q) A5 G" V
/ Q& A5 Y! f  p' p取决于你的MySQL版本,对上述,你可能必须使用一个不同数目'Y'值(在
. M* H4 @0 J! M, Y3.22.11以前的版本有更少的权限列)。对admin用户,只用在3.22.11开始的版
# a1 E+ o) X0 O. ]: ~本具有的更加可读的INSERT扩充的语法。
4 T; t, D/ k$ O
9 v9 j8 P+ x! E% w4 Z( D2 Q) d注意,为了设置一个超级用户,你只需创造一个user表条目,其权限字段设为 " m  f1 w+ u' C
'Y'。不需要db或host表的条目。 $ t$ S4 p% G' p* c( \7 L; w) l/ T

6 i: J' }+ W) F5 _$ Q/ G" d在user表中的权限列不是由最后一个INSERT语句明确设置的(对dummy用户), , V% g  P- Z2 }# k8 ]# {- f
因此那些列被赋予缺省值'N'。这是GRANT USAGE做的同样的事情。
2 K/ A; ]+ i0 d) `( I" `  Y% A- `, W" W0 ^- w8 p8 A: v) f
下列例子增加一个用户custom,他能从主机localhost、server.domain和
4 W7 e$ k' Q8 g% a# ?whitehouse.gov连接。他只想要从localhost存取bankaccount数据库,从
, a/ c0 v: S; z+ ]% zwhitehouse.gov存取expenses数据库和从所有3台主机存取customer数据库。他 . o4 V% |: d8 L2 f/ w) e; g
想要从所有3台主机上使用口令stupid。
% L" F6 \# O4 E% t2 ?% s
  B3 X, o! [: k# Q为了使用GRANT语句设置个用户的权限,运行这些命令: 3 L6 M0 Z0 h0 N9 H- i
2 c: m0 W3 f; k2 K
shell> mysql --user=root mysql ' F" m5 |  v3 `: g
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
% q; f+ n2 g9 W  a. g; {3 ~" S+ t  r9 UON bankaccount.*
8 E/ H% z5 E0 d" Y8 D! XTO custom@localhost + d) P6 ~6 d& m9 p1 S! Y" f
IDENTIFIED BY 'stupid'; 1 [$ o4 R1 v' q
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ' a$ J4 d( L1 A  D
ON expenses.*
4 f0 ]; P9 V& ]- \: n' n3 A6 v2 xTO custom@whitehouse.gov . v0 z4 O" `9 W. [
IDENTIFIED BY 'stupid'; 8 W2 Z4 j$ x- ?, h) Z$ F5 p
mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP
. W7 S; Q6 ?+ y( c1 D$ @ON customer.*
" c; L2 `3 K. L7 M* TTO custom@'%' % i* r( S- _- W5 M2 \6 N2 a
IDENTIFIED BY 'stupid'; - F" P- ?* R: o' x/ e
1 r' r- u- d* Q4 Q" H
通过直接修改授权表设置用户权限,运行这些命令(注意,在结束时
- j% F+ z. r5 _6 J2 [FLUSH PRIVILEGES): % l5 r4 R. r$ |+ u3 a! @/ d5 @& T

  {7 q# \$ O+ u! w, p% j! A4 j$ V0 `shell> mysql --user=root mysql * K& L9 D0 B8 c6 N! I
mysql> INSERT INTO user (Host,User,Password)
4 h) M/ L$ J) u1 V1 U. S2 [VALUES('localhost','custom',PASSWORD('stupid'));
) ~0 @/ V  n% rmysql> INSERT INTO user (Host,User,Password) / F/ [  J, Q  v. X3 H; T
VALUES('server.domain','custom',PASSWORD('stupid'));   \/ a* a1 r3 n
mysql> INSERT INTO user (Host,User,Password)
. \' Q; |! L- sVALUES('whitehouse.gov','custom',PASSWORD('stupid'));
+ t( }9 F' y3 _% wmysql> INSERT INTO db 8 F6 Y* Q0 {  e5 V
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, 3 D% I) |. w- E$ U+ U/ R  o
Create_priv,Drop_priv) 5 n/ b1 F1 g+ K. ?- @
VALUES 6 l& m2 }" x! E' P
('localhost','bankaccount','custom','Y','Y','Y','Y','Y','Y');
. V9 \; u3 Q* H6 x: o* f+ Imysql> INSERT INTO db % X* l* ]' q: h% F& s' |" b
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv,
" m& q# P% D% [. UCreate_priv,Drop_priv) # W/ q$ T$ [8 [
VALUES , D2 V( J# q. c# [# x
('whitehouse.gov','expenses','custom','Y','Y','Y','Y','Y','Y'); 2 Y8 y* `' ~, e0 q  I1 ]
mysql> INSERT INTO db $ c8 M9 K# m4 ^3 j+ b7 k
(Host,Db,User,Select_priv,Insert_priv,Update_priv,Delete_priv, , l' N2 v, J# d5 n
Create_priv,Drop_priv)
+ Z7 s" Y& J9 {VALUES('%','customer','custom','Y','Y','Y','Y','Y','Y'); . p0 C, a( ?& j( B8 |
mysql> FLUSH PRIVILEGES;
+ n3 f1 T5 y9 o& Q  }: }* @* U; ]# N0 }0 F% X5 ~
头3个INSERT语句增加user表条目,允许用户custom用给定口令从不同的主机 ( E" z+ s& \1 H3 T# [
进行连接,但是没有授予任何许可(所有权限被设置为缺省值'N')。后3个INSERT
. q4 K. u* V+ t) R' |) S语句增加db表条目,授予custom以bankaccount、expenses和customer数据库权限, # ~1 k- ], q1 K- M4 y; N9 w
但是只能在从正确的主机存取时。通常,在授权表直接被修改时,服务器必须被告   Z# y* p3 a* O* S$ }
知再次装入他们(用FLUSH PRIVILEGES)以便使权限修改生效。
: `5 p9 N1 K" O  p7 Q, T! m, z
# S+ P: c) j1 c+ e5 L2 O* Q如果你想要给特定的用户从一个给定的域上的任何机器上存取权限,你可以发 ) L, Q/ t" E+ t( C0 x8 H2 q
出一个如下的GRANT语句: $ r0 i* g  T( d' c5 m
# I3 ]# v5 _) H' b, c  `
mysql> GRANT ...
4 v. @3 q7 G; f* F, a# zON *.* & J5 Q; C5 }) h5 a
TO myusername@"%.mydomainname.com"
; {4 h+ E2 ~* s2 p( X! x3 iIDENTIFIED BY 'mypassword';
: U0 J6 P$ M- @* I
/ |% Q$ T- r3 V) G7 D" e为了通过直接修改授权表做同样的事情,这样做: # \/ U0 s, m$ Q2 d9 |

) ?5 m) I; {7 y- @( s) z6 ]mysql> INSERT INTO user VALUES ('%.mydomainname.com', 'myusername', : y( W7 T# \9 p- l
PASSWORD('mypassword'),...); + o$ h% `+ W7 M. }( H: o
mysql> FLUSH PRIVILEGES;
* F8 D" d4 h6 E" q! ?8 G. c) A. f. u: _% J" h3 ]
你也可以使用xmysqladmin、mysql_webadmin甚至xmysql在授权表中插入、改变
9 k8 z3 X6 c3 ]/ r; K和更新值。你可以在MySQL的Contrib目录找到这些实用程序。
. L2 q. |' N1 O
, p( ]- t3 |* E怎样设置口令 3 G( k# f# h  w
在前面小节的例子里说明了一个重要的原则:当你使用INSERT或UPDATE语句存
$ v1 R: L5 l, w  p8 u储一个非空的口令时,你必须使用PASSWORD()函数加密它。这是因为在user表中以 . e9 l, e- d6 Q  H+ x9 ?: w
加密形式存储口令,而不是作为纯文本。如果你忘记这个事实,你可能像这样试图 ; b7 G" ]/ h$ ?6 \8 L1 w6 i
设置口令: : r  ?; B- [2 [$ l. N0 `7 b( P
/ i& j2 P& N" q6 v: H
shell> mysql -u root mysql
; b, _# p* F9 b6 H1 l8 B$ W# dmysql> INSERT INTO user (Host,User,Password) VALUES('%','jeffrey',
2 J7 S  w% n* ?% G5 ~$ Y6 a'biscuit'); , E: V" k) M0 Y- D  W4 o+ f7 t+ s, d
mysql> FLUSH PRIVILEGES
* O1 g: P0 R/ o( K+ @* C
+ @( x; X* p) X6 \' O# A) k结果是纯文本值'biscuit'作为口令被存储在user表中。在用户jeffrey试图用
  o% g4 {- a- e% i# S这个口令连接服务器时,mysql客户用PASSWORD()加密它并且将结果送给服务器,服
% f% }2 ]$ W# p3 f" A务器比较在user表中的值(它是纯文本值'biscuit')和加密的口令(而不是 1 f9 x$ o' D' o
'biscuit'),比较失败并且服务器拒绝连接:
; k5 D1 e" ?* X4 X# d) N' T3 L6 d0 o8 ]- _3 J! ^/ p, @3 U0 o7 Q. t. T( e
shell> mysql -u jeffrey -pbiscuit test - B: `+ j' ]0 b9 X
Access denied
' p* C2 L2 g9 H4 C) r4 c
( u4 x6 {7 `! s- A9 u; F因为当他们被插入user表时,口令必须被加密,相反,INSERT语句应该象这样
+ y4 X; U0 b6 ^6 \4 X被指定:
9 U+ g# W; T/ ?& u
& X9 K: {& w7 Y  c- G, y. L" bmysql> INSERT INTO user (Host,User,Password) 7 q) t0 X3 W0 u! v* j
VALUES('%','jeffrey',PASSWORD('biscuit')); 5 B: b6 T) G5 |5 @

  z  \. t; }2 P' F; B  z/ C" u+ Q当你使用SET PASSWORD语句时,你也必须使用PASSWORD()函数: ; k+ v6 g; m8 b& q; Q- g

. t, x( e. c0 j; G% s) W% Cmysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit');
7 h( }% S  Z; o; q5 @/ l
) H% x. t, x& P- D+ n如果你使用GRANT ... IDENTIFIED BY语句或mysqladmin password命令设置口
4 g0 F; X. r8 F1 V+ F+ |令,PASSWORD()函数是不必要的。他们都考虑到为你加密口令,多以你可像这样指
  H$ N2 z  \* N" W, {: @: |定一个口令'biscuit':
/ \3 a5 |. U& O7 S5 W) ~+ @* N: k
  e' y& t5 `9 F  a" k+ J+ p  m( amysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit'; * k' j0 [* w) ^* v

6 T2 H* Q/ F, u" [: g: i0 r- O* z- b& g# W$ q

4 s; ]4 J: j  eshell> mysqladmin -u jeffrey password biscuit
- ^2 _  X) [4 S注意: PASSWORD()不是以在Unix口令加密的同样方法施行口令加密。你不应 ( g5 }7 @& p% l- r1 f3 I
该假定如果你的Unix口令和你的MySQL口令是一样的,PASSWORD()将导致与在Unix
/ h9 i0 p2 s6 T8 p! L口令文件被存储的同样的加密值。见6.2 MySQL 用户名和口令。
; V& ~- w) i9 Y/ R& L- r- A; P/ D2 ]9 Z8 D; w1 G+ u  `: @
Access denied错误的原因 : y! y; a1 t& g0 {3 |$ x' k5 x: k
当你试着联接MySQL服务器时,如果你碰到Access denied错误,显示在下面 ( @+ G& V  \  u# C2 E
的表指出一些你能用来更正这个问题的动作: & [- L! a. Y) l4 c' y/ Z7 o4 @& O
: a# H9 A6 F5 F- P! G+ i
你是在安装MySQL以后运行mysql_install_db的脚本,来设置初始授权表内容
; `$ N0 _3 }4 }  |" G" k吗?如果不是,这样做。见6.10 设置初始MySQL权限。通过执行这个命令测试初
, N% C& b7 A4 E始权限:
& @8 a( c* w( s3 K6 Oshell> mysql -u root test
) s2 V9 D4 d+ s8 _! J
# p5 D$ c! G2 P7 D9 m服务器应该让你无误地连接。你也应该保证你在MySQL数据库目录有一个文件 5 Q) t# K0 N) h& {- \
“user.MYD”。通常,它是“PATH/var/mysql/user.MYD”,在此PATH是MySQL安
- Z* ?- l8 @# ?% `, J" U% t9 v/ q( z装根目录的路径。
; ~8 L& G4 a+ v$ s! R2 C$ }  K# v% t6 ~" Q' F: @# M" ?% M
在一个新的安装以后,你应该连接服务器并且设置你的用户及其存取许可:
$ t" R6 z9 v# Q4 L, ~0 L5 }shell> mysql -u root mysql
( J6 q! G3 M0 [
& k8 {7 R0 m0 S* S+ L+ x服务器应该让你连接,因为MySQL root用户初始时没有口令。既然那也是一个
& C' r7 t% W! U" k6 E! L" s) n7 {安全风险,当你正在设置其他MySQL用户时,设定root口令是一件重要的事请。如
: f; N" I* I2 g  C4 X( o, s果你作为root尝试连接并且得到这个错误: / u5 q, _$ q7 v, U

5 u) q, W+ H. H& _2 ]Access denied for user: '@unknown' to database mysql
5 W3 _8 ]/ c. {/ V; B: u$ P
& w4 C* q+ X- O2 L# B: J- d这意味着,你没有一个条目在user表中的一个User列值为'root'并且mysqld 7 L" A% ~' h, V  S) M. T
不能为你的客库解析主机名。在这种情况下,你必须用--skip-grant-tables选项
: H) ~, ~4 Z5 p8 c2 v/ S- n" E4 B重启服务器并且编辑你的“/etc/hosts”或“\windows\hosts”文件为你的主机 . _! ^# R4 ]- H
增加一个条目。 3 q* O2 J9 F8 X/ w( l
& z( r5 H* l+ g" K' Y
如果你从一个3.22.11以前的版本更新一个现存的MySQL安装到3.22.11版或以 5 G, Y  z8 J! ?' z* S: e
后版本,你运行了mysql_fix_privilege_tables脚本吗?如果没有,运行它。在 ) I! |5 q6 O# [% W
GRANT语句变得能工作时,授权表的结构用MySQL 3.22.11修改 。 + A+ K4 }% [4 k) G# ~
如果你直接对授权表做修改(使用INSERT或UPDATE语句)并且你的改变似乎被 / P5 O0 m( }# S5 r* v/ d7 h* z6 _& t
忽略,记住,你必须发出一个FLUSH PRIVILEGES语句或执行一个mysqladmin
6 u: x4 I3 C& A/ F( I* Pflush-privileges命令导致服务器再次读入表,否则你的改变要道下一次服务器被
- j/ b3 Q" w- J8 w/ c重启时再生效。记住在你设定root口令以后,你将不需要指定它,直到在你清洗
% t2 l! h0 W; _6 |(flush)权限以后,因为服务器仍然不会知道你改变了口令! ( c4 ]+ P/ @7 I& R+ ~( Y$ ~
如果你的权限似乎在一个会话(session)当中改变了,可能是一个超级用户改变
7 W% k+ J2 o- ]" F2 s了他们。再次装入授权表作用于新客户连接,但是它也影响现存的连接,如6.9 权 $ a# d9 b( }8 R8 h1 b9 x- f
限改变何时生效小节所述。 ! `. _; U; a7 p, x% d
为了测试,用--skip-grant-tables选项启动mysqld守护进程,然后你可以改变
* z; i' \  ~( `0 K/ d' w# TMySQL授权表并且使用mysqlaccess脚本检查你的修改是否有如期的效果。当你对你的
, D. ^) j* I- ^6 \6 W/ G& f/ s改变满意时,执行mysqladmin flush-privileges告诉mysqld服务器开始使用新的权
3 F  f, X/ {; Y/ T. {限表。注意:再次装入授权表覆盖了--skip-grant-tables选项。这允许你告诉服务
' Y0 h5 n, J. Z3 x, v7 j/ v器开始使用授权表,而不用停掉并重启它。 1 A' g! q; _7 e3 t  h
如果你有一个Perl、Python或ODBC程序的存取问题,试着用mysql -u user_name
$ C- Q: [; }+ U7 G5 g6 p: I% Qdb_name或mysql -u user_name -pyour_pass db_name与服务器连接。如果你能用 . M1 T6 f5 f+ V3 c( b( H5 d
mysql客户连接,这是你程序的一个问题而不是存取权限的问题。(注意在-p和口令 7 Z3 x/ J9 l6 A" i3 `
之间没有空格;你也能使用--password=your_pass句法指定口令。)
* x% v8 Y2 y9 {; n如果你不能让口令工作,记得如果你用INSERT, UPDATE或SET PASSWORD语句
& @+ \4 L2 m' Y5 r: Q' J* f设置口令,你必须使用PASSWORD()函数。如果你用GRANT ... INDENTIFIED BY语 ( N$ w' F5 `3 V
句或mysqladmin password命令指定口令,PASSWORD()函数是不需要的。
( i6 C1 z! W9 a! f/ q6 C3 f" Y7 k3 S  Jlocalhost是你本地主机名的一个同义词,并且也是如果你不明确地指定主机 6 T0 d$ |# X2 K- `
而客户尝试连接的缺省主机。然而,如果你正在运行于一个使用MIT-pthreads的系 * v' @2 b! \( b: M
统上,连接localhost是不行的(localhost连接使用Unix套接字进行,它没被 MIT
4 k* i$ v' P) R: Y/ w8 H! d-pthreads支持),为了在这样的系统上避免这个问题,你应该使用--host选项明确
  c- S$ X! }  I) C地命名服务器主机,这将做一个 TCP/IP连接到mysqld服务器。在这种情况下,你
- R% a$ e7 A- S/ q: G必须有在服务器主机上的user表中条目的你真实的主机名。(即使你在服务器同一
- X& O* y, |9 B' y" n8 E1 Y1 ]台的主机上运行一个客户程序,这也是真的。) 9 {6 U# _: ~7 F5 e4 j8 s1 J5 H4 d
当尝试用mysql -u user_name db_name与数据库连接时,如果你得到一个
4 d" M; x, E) E, j) n: fAccess denied错误,你可能有与user桌有关的问题,通过执行mysql -u root ) `& N" ~7 S: \, q
mysql并且发出下面的SQL语句检查:
# d, `8 J0 C! o+ @# ^mysql> SELECT * FROM user;
0 }; t+ ]+ R8 K- I, K% z- m" i& ^8 K7 }0 M( |
结果应该包含一个有Host和User列的条目匹配你的计算机主机名和你的MySQL用户 ) @2 i. F* M6 k. q# e
名。 - {. n# g8 N6 ~; Q% w
% A3 m% A! V0 y+ x0 V. r
Access denied错误消息将告诉你,你正在用哪个用户尝试登录,你正在试图 ; Y4 _. a/ g7 K0 T, p0 x
用连接哪个主机,并且你是否正在使用一个口令。通常,你应该在user表中有一 7 E! A) @: i: m! L8 \
个条目,正确地匹配在错误消息给出的主机名和用户名。
& t2 v7 ^! U+ [4 m3 E* k4 n如果当你试着从一个不是MySQL服务器正在运行的主机上连接时,你得到下列
' o* T: w$ d2 F1 A* I错误,那么在user表中没有匹配那台主机行:
% M7 I4 [# E( x; M6 E. p+ f4 h- XHost ... is not allowed to connect to this MySQL server 5 a: r4 ?  n0 u5 c+ F" E

1 q) q" b9 v: g* b  q  q/ J你可以通过使用mysql命令行工具(在服务器主机上!)修正它,把你正在试
% Y9 I7 o$ k% u" O3 Z+ V图连接的用户/主机名组合新加一行到user表中。如果你不在运行MySQL 3.22并且
8 p. u  n  G/ F& A+ I, p, D你不知道你正在从它连接的机器的IP数字或主机名,你应该把一个'%'条目作为
# R1 Y6 s/ I" u% t! `2 pHost列值放在user表中并且在服务器机器上使用--log选项重启mysqld。在试图从 8 U0 b: E' k) f4 U7 R
客户机器连接以后,在MySQL记录文件中的信息将显示你如何真正进行连接。( . W; ~, G* [1 ~
然后用在记录文件上面显示出的实际的主机名代替user表中的'%'条目。否则, 5 P; E& F8 I# s, q6 t3 P7 g: O
你将有一个不安全的系统。) $ x4 K6 ]- M1 d4 T  {" k

) E$ R5 z6 B3 U4 k6 [; ]4 k- l如果mysql -u root test工作但是mysql -h your_hostname -u root test
9 ?  h0 o3 s' r& i导致Access denied,那么在user表中你可能没有你的主机的正确名字。这里的
7 X  F9 k" W: f) A) F一个普遍的问题是在user表条目中的Host值指定一个唯一的主机名,但是你系统
% v, @$ U" C+ V5 L6 S的名字解析例程返回一个完全正规的域名(或相反)。例如,如果你在user表中有
4 u7 e0 m7 ~) P. R* ?/ X6 `一个主机是'tcx'的条目,但是你的 DNS告诉MySQL你的主机名是'tcx.subnet. ' F& R1 F# _6 b3 z
se',条目将不工作。尝试把一个条目加到user表中,它包含你主机的IP数字作
! G# i  `: O& C( E' X0 k+ B% ?为Host列的值。(另外,你可以把一个条目加到user表中,它有包含一个通配符 # x2 m( S+ d. t# z& Z- n5 O' v( L
如'tcx.%'的Host值。然而,使用以“%”结尾的主机名是不安全的并且不推荐!) 9 T+ }" V, N9 V+ |6 N2 M
如果mysql -u user_name test工作但是mysql -u user_name other_db_name
. ~- L& b; Z' K( `6 u% e9 ^9 Z4 H7 }不工作,对other_db_name,你在db表中没有没有一个条目列出。 , H9 j7 T2 o/ |) c: V# \7 Y" ]
当在服务器机器上执行mysql -u user_name db_name时,它工作,但是在其
. G$ ?& k3 {/ ~, R( p  ?9 H它客户机器上执行mysql -h host_name -u user_name db_name时,它却不工作,
* r$ e* r; _- j5 q, t! D; A5 M3 R你没有把客户机器列在user表或db表中。 ; c) R. O! G3 Q# \% r! G6 a
如果你不能弄明白你为什么得到Access denied,从user表中删除所有Host
. q7 |8 O. a  g) t, O8 V; B4 L包含通配符值的条目(包含“%”或“_”的条目)。一个很普遍的错误是插入用 4 o) [8 l1 W- ^
Host='%'和User='some user'插入一个新条目,认为这将允许你指定localhost
( g0 m' ^. u% W* C4 p1 F7 i从同一台机器进行连接。它不工作的原因是缺省权限包括一个有Host='localhost'
& [) r. }7 h1 R  c5 ]$ x3 j* P和User=''的条目,因为那个条目一个比'%'更具体的Host值'localhost',当从   [# k! x7 Y2 V
localhost连接时,它用于指向新条目!正确的步骤是插入Host='localhost'和
$ d) h% x  l. _& @. b  v8 uUser='some_user'的第2个条目,或删除Host='localhost'和User=''条目。 8 a7 |3 r3 q9 D* L  g+ F$ m
如果你得到下列错误,你可以有一个与db或host表有关的问题: $ X# [2 z( S$ L6 T, F
Access to database denied
0 h4 U% V$ ]: N( ?: B, d" O5 [9 b
! D$ V, c. a. W& P& e; T如果从db表中选择了在Host列有空值的条目,保证在host表中有一个或多
4 A; y  \* x" `" f: k1 H$ X个相应的条目,指定运用db表中的哪些主机。如果在使用SQL命令SELECT ... ; R- L3 r& I. z- u
INTO OUTFILE或LOAD DATA INFILE时,你得到错误,在user表中的你的条目可
3 [8 o$ [7 H. [' n1 ^能启用file权限。
5 s$ \6 x4 q1 G3 |3 Y4 V' Q5 z5 t' \- T+ @9 I# m$ O
记住,客户程序将使用在配置文件或环境变量被指定了的连接参数。如果 8 N* `9 w1 O8 {0 [  h% z3 b
当你不在命令行上指定他们时,一个客户似乎正在发送错误的缺省连接参数,
6 k* R( M; R! w- Q0 ]检查你的环境和在你的主目录下的“.my.cnf”文件。你也可以检查系统范围
* a, H6 V3 O1 O的MySQL配置文件,尽管更不可能将在那里指定那个客户的连接参数。如果当 " r( {+ z) q4 \
你没有任何选项运行一个客户时,你得到Access denied,确认你没在任何选 ) I+ m' Y. t- r: E6 |4 s
项文件里指定一个旧的口令!见4.15.4 选项文件。
8 ^' _* _$ }' u3 D3 L0 ~如果任何其它事情失败,用调试选项(例如,--debug=d,general,query) % n% _8 Q. K7 j* u$ ]' |- m
启动mysqld守护进程。这将打印有关尝试连接的主机和用户信息,和发出的每
' U2 U1 ?/ F; f; M/ B5 f个命令的信息。见G.1 调试一个MySQL服务器。 * m# D# }; c- o5 r# g
如果你有任何与MySQL授权表的其它问题,而且觉得你必须邮寄这个问题 : x) k2 Q) J7 F$ i0 S- f
到邮寄表,总是提供一个MySQL授权表的倾倒副本(dump)。你可用mysqldump ' x5 O% J! v1 b
mysql命令倾倒数据库表。象平时一样,用mysqlbug脚本邮寄你的问题。在一 + j5 e8 L- M8 [2 i' X) {
些情况下你可能用--skip-grant-tables重启mysqld以便能运行mysqldump。 6 j- E5 W2 i+ g4 r7 b$ [, @
怎样使MySQL安全以对抗解密高手 1 q/ T- e& s, |& H+ _8 q
当你连接一个MySQL服务器时,你通常应该使用一个口令。口令不以明文 0 a5 L) r1 m: M  p. Q
在连接上传输。 8 W& L/ b. s% |2 }$ f/ r/ l
6 p6 |! \1 {/ j) K
所有其它信息作为能被任何人读懂的文本被传输。如果你担心这个,你可
$ v. w, O. w3 O9 X. ?4 v  m; {) M. l/ O使用压缩协议(MySQL3.22和以上版本)使事情变得更难。甚至为了使一切更安全 / W. H3 O( A# {2 b& E& I, |/ U; b3 O) z
,你应该安装ssh(见http://www.cs.hut.fi/ssh)。用它,你能在一个MySQL服
& e- t' v; j! R2 {  Y" P' o: q务器与一个MySQL客户之间得到一个加密的TCP/IP连接。
# S& y0 E8 U1 y  x
; f* r" Q! S  L为了使一个MySQL系统安全,强烈要求你考虑下列建议:
. M4 x% @7 {8 }+ T9 Q+ @% s
- g. F; w- F* V$ g5 R对所有MySQL用户使用口令。记住,如果other_user没有口令,任何人能简
* U% y: ]% ?( b. W单地用mysql -u other_user db_name作为任何其它的人登录。对客户机/服务器 ) M# }0 L0 K5 c6 f
应用程序,客户可以指定任何用户名是常见的做法。在你运行它以前,你可以通 . Q# d5 R% u3 K2 ]& o1 X
过编辑mysql_install_db脚本改变所有用户的口令,或仅仅MySQL root的口令,
7 b( C. R- s* e# ~象这样:
+ ~& s/ n; q5 e! l5 N4 [shell> mysql -u root mysql . y0 |2 j5 W4 _$ I9 N2 N- b
mysql> UPDATE user SET Password=PASSWORD('new_password')
3 {! [# i8 O& h9 h' g* M" vWHERE user='root';
$ f% M5 K5 F- a3 Y  o. D' Cmysql> FLUSH PRIVILEGES; 5 u: ^( m; R0 j
/ E& o; a- l4 M4 C( A2 ^
不要作为Unix的root用户运行MySQL守护进程。mysqld能以任何用户运行, 7 x7 u! \- M' \! N( c
你也可以创造一个新的Unix用户mysql使一切更安全。如果你作为其它Unix用户
: \" l0 g5 }7 W  I9 e运行mysqld,你不需要改变在user表中的root用户名,因为MySQL用户名与Unix ' i' Q" t+ i3 L1 p
用户名没关系。你可以作为其它Unix用户编辑mysql.server启动脚本mysqld。 ; h7 H- x# a" n' c0 U7 M
通常这用su命令完成。对于更多的细节,见18.8 怎样作为一个一般用户运行
5 ^; ?" M) f/ I+ b0 [: E. Y) TMySQL。
. A3 X, |! D: t! R! P如果你把一个Unix root用户口令放在mysql.server脚本中,确保这个脚本 ) y" ]2 t. K6 ~9 G0 {$ G/ `
只能对root是可读的。 8 T% V8 G9 p- B, {4 D
检查那个运行mysqld的Unix用户是唯一的在数据库目录下有读/写权限的用
' i5 f# H6 G( ^4 }" B户。
& s8 ~; J; \2 `4 f不要把process权限给所有用户。mysqladmin processlist的输出显示出当 6 K: n+ \" l+ H4 A# O
前执行的查询正文,如果另外的用户发出一个UPDATE user SET password= 5 z' s% p3 ~5 I, P' {  x
PASSWORD('not_secure')查询,被允许执行那个命令的任何用户可能看得到。
# c3 c  U6 U! O* t" E: |7 V  dmysqld为有process权限的用户保留一个额外的连接, 以便一个MySQL root用 $ o: k, S( ~3 b: w" Z' h
户能登录并检查,即使所有的正常连接在使用。 * B5 w$ v6 E* {
不要把file权限给所有的用户。有这权限的任何用户能在拥有mysqld守护
& m8 j, L! h: V# \0 V进程权限的文件系统那里写一个文件!为了使这更安全一些,用SELECT ... , r9 z0 y* U1 Y  U9 B
INTO OUTFILE生成的所有文件对每个人是可读的,并且你不能覆盖已经存在的
( ?  N; b" o2 K' @4 y文件。file权限也可以被用来读取任何作为运行服务器的Unix用户可存取的文 ' {9 e* B; R) b  S% Y9 m- |* o
件。这可能被滥用,例如,通过使用LOAD DATA装载“/etc/passwd”进一个数 8 c1 \2 O0 S" a8 D: @( A2 k
据库表,然后它能用SELECT被读入。
8 V, T7 B3 m, [如果你不信任你的DNS,你应该在授权表中使用IP数字而不是主机名。原则 $ V  }& H7 `& X/ a" x8 x" `
上讲,--secure选项对mysqld应该使主机名更安全。在任何情况下,你应该非常
! ]9 b& f" m% u小心地使用包含通配符的主机名! ! y3 y( u) O" ?( o
下列mysqld选项影响安全:
' Q9 ^; m. W' }. J5 F3 n  d6 K( ?  L  L9 S' v
--secure 5 x! x( C2 v: e) l7 H
由gethostbyname()系统调用返回的IP数字被检查,确保他们解析回到原来
, s3 Z  [1 K( ]9 W. `$ r3 B的主机名。这对某些外人通过模仿其它主机获得存取权限变得更难。这个选项也 ( p( N5 z: ?" }, c( R
增加一些聪明的主机名检查。在MySQL3.21里,选择缺省是关掉的,因为它有时
+ G) u- d& V" X" f4 a. a3 I. n它花很长时间执行反向解析。MySQL 3.22缓存主机名并缺省地启用了这个选项。 ! R  Z. n- }( [, `% b3 t+ `" o, w
--skip-grant-tables 2 s+ T% W& O' x% h# T) N
这个选项导致服务器根本不使用权限系统。这给每个人以完全存取所有的数
  a* T) O$ V+ i5 d6 \  e9 q' A据库的权力!(通过执行mysqladmin reload,你能告诉一个正在运行的服务器 8 }& ]+ _5 ?0 A+ e
再次开始使用授权表。) ; {4 P6 o2 [" u0 D- O7 }6 ~
--skip-name-resolve # C. U" k0 K/ @. x
主机名不被解析。所有在授权表的Host的列值必须是IP数字或localhost。
! ?+ T6 i5 G- m) e--skip-networking
6 ~# W% j" b. S& j9 G7 Z在网络上不允许TCP/IP连接。所有到mysqld的连接必须经由Unix套接字进
+ l6 T- F7 A- `行。这个选项对使用MIT-pthreads的系统是不合适的,因为MIT-pthreads包不 * U/ U4 X1 }3 ?
支持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 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
看了一屏就晕了。。。  i- \" f$ J* x. o2 C
汗。。
2 N6 b1 o0 l; r" e6 T$ ?水平不够,消化不了。。
4 @3 y/ r8 k1 Z5 ^' n2 B/ r+ ~不过还是顶一下
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享分享 顶 踩

本版积分规则

关闭

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

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