MySQL 8創建用戶與用戶管理

1. 創建user

  對於每個帳戶,CREATE USER在mysql.user系統表中創建一條新數據行,包括創建語句中指定的屬性,未指定的屬性設置爲其默認值:

  • 身份驗證:由default_authentication_plugin系統變量定義的身份驗證插件和空憑據;
  • 默認角色: NONE;
  • SSL/TLS: NONE;
  • 資源限制:無限制;
  • 密碼管理:PASSWORD EXPIRE DEFAULT PASSWORD HISTORY DEFAULT PASSWORD REUSE INTERVAL DEFAULT PASSWORD REQUIRE CURRENT DEFAULT;禁用登錄失敗跟蹤和臨時帳戶鎖定。
  • 帳戶鎖定: ACCOUNT UNLOCK

  Create user語法:

CREATE USER [IF NOT EXISTS]
    user [auth_option] [, user [auth_option]] ...
    DEFAULT ROLE role [, role ] ...
    [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
    [WITH resource_option [resource_option] ...]
    [password_option | lock_option] ...
    [COMMENT 'comment_string' | ATTRIBUTE 'json_object']

1.1 USER

  MySQL帳戶名由用戶名和主機名組成,這可以爲具有相同用戶名且從不同主機進行連接的用戶創建不同的帳戶。

  • 使用反引號(`),單引號(’)或雙引號(")將用戶名和主機名作爲標識符或字符串引號,USER名稱的語法爲:‘user_name’@‘host_name’,帳戶名的主機名部分(如果省略)默認爲’%’,僅包含用戶名的帳戶名等效於’user_name’@’%’,例如’cy’等效於’cy’@’%’;
  • 主機值可以是主機名或IP地址(IPv4或IPv6),‘localhost’表示本地主機,IP地址’127.0.0.1’ 表示IPv4環回接口,IP地址 '::1’表示IPv6環回接口;
  • 主機名或IP地址值中允許使用%和_通配符,例如,主機值’%‘匹配任何主機名,而值’%.mysql.com’匹配mysql.com域中的任何主機, '198.51.100.%'匹配198.51.100 C類網絡中的任何主機。

  示例1,創建最簡單的本地賬戶(從MySQL 8.0.21開始,可以創建具有註釋或用戶屬性的用戶):

mysql> CREATE USER 'cy'@'localhost' IDENTIFIED BY 'cy123' COMMENT 'Information about ChengYu';
mysql> CREATE USER 'yx'@'localhost' ATTRIBUTE '{"fname": "Zhong", "lname": "yx", "phone": "136-86**-****"}';

  示例2:創建一個使用caching_sha2_password身份驗證插件和給定密碼的帳戶,要求每365天更新一次密碼,並啓用登錄失敗跟蹤,3次連續的錯誤密碼輸入就鎖定賬戶2天:

mysql> CREATE USER 'cy'@'localhost'
  IDENTIFIED WITH caching_sha2_password BY 'cy123'
  PASSWORD EXPIRE INTERVAL 365 DAY
  FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 2;

  示例3:創建多個帳戶,可以設置每個帳戶有私有屬性和一些全局屬性:

  • 必須使用有效的X.509證書進行連接;
  • 每小時最多允許60個查詢;
  • 密碼更改不能複用5個最近使用的密碼中的任何一個;
  • 該帳戶最初是被鎖定的,因此實際上是一個佔位符,只有在管理員將其解鎖後才能使用。
mysql> CREATE USER
  'cy'@'localhost' IDENTIFIED WITH mysql_native_password BY 'cy123',
  'yx'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'yx456'
  REQUIRE X509 WITH MAX_QUERIES_PER_HOUR 60
  PASSWORD HISTORY 5
  ACCOUNT LOCK;

1.2 auth_option

  auth_option指定帳戶身份驗證插件,插件名稱可以是帶引號的字符串文字或不帶引號的名稱,插件名稱存儲在系統表的plugin列中 mysql.user。

auth_option: {
    IDENTIFIED BY 'auth_string'
  | IDENTIFIED BY RANDOM PASSWORD
  | IDENTIFIED WITH auth_plugin
  | IDENTIFIED WITH auth_plugin BY 'auth_string'
  | IDENTIFIED WITH auth_plugin BY RANDOM PASSWORD
  | IDENTIFIED WITH auth_plugin AS 'auth_string'
}
  • IDENTIFIED BY ‘auth_string’:將明文密碼傳遞給該插件以進行散列處理,並將結果存儲在mysql.user系統表中。

  • IDENTIFIED BY RANDOM PASSWORD:生成隨機密碼,將明文密碼值傳遞給該插件以進行散列處理,並將結果存儲在mysql.user系統表中。

  • IDENTIFIED WITH auth_plugin:將帳戶身份驗證插件設置爲auth_plugin,將憑據清除爲空字符串,並將結果存儲在mysql.user系統表中。

  • IDENTIFIED WITH auth_plugin BY ‘auth_string’:將帳戶身份驗證插件設置爲auth_plugin,將明文密碼傳遞給該插件以進行散列處理,並將結果存儲在系統表的帳戶行中。

  • IDENTIFIED WITH auth_plugin BY RANDOM PASSWORD:將帳戶身份驗證插件設置爲auth_plugin,生成一個隨機密碼,將明文密碼值傳遞給該插件以進行散列處理,並將結果存儲在mysql.user系統表中。

  • IDENTIFIED WITH auth_plugin AS ‘auth_string’:將帳戶身份驗證插件設置爲auth_plugin並將密碼存儲到帳戶行中,如果插件需要哈希字符串,則假定該字符串已經以插件所需的格式進行哈希處理。

# 使用默認插件並將密碼指定爲明文
mysql> CREATE USER 'yx'@'localhost' IDENTIFIED BY 'yx456';
Query OK, 0 rows affected (0.07 sec)

mysql> select plugin,authentication_string from mysql.user where user='yx'\G
*************************** 1. row ***************************
                  plugin: caching_sha2_password
   authentication_string: $A$005${__(RC>xwH:,iHdxMEtMoYy4emipZbr2fIVE2WklKpbcnYZSr3gQYPM0y5
1 row in set (0.00 sec)

# 指定身份驗證插件以及明文密碼
mysql> CREATE USER 'yx'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yx456';
Query OK, 0 rows affected (0.07 sec)

mysql> select plugin,authentication_string from mysql.user where user='yx'\G
                  plugin: mysql_native_password
   authentication_string: *966262893486B77167411EBDE108C027282B03A5

# 隨機密碼
mysql> CREATE USER 'yx'@'localhost' IDENTIFIED WITH mysql_native_password BY RANDOM PASSWORD;
+------+-----------+----------------------+
| user | host      | generated password   |
+------+-----------+----------------------+
| yx   | localhost | q;x.q4qrZSWb1+QfJI,d |
+------+-----------+----------------------+
1 row in set (0.07 sec)
mysql> select plugin,authentication_string from mysql.user where user='yx'\G
*************************** 1. row ***************************
               plugin: mysql_native_password
authentication_string: *BE895BDCEFEF2284A4F07ECA4A2E1855C24C9FCF
1 row in set (0.00 sec)

1.3 用戶密碼

  MySQL支持以下密碼管理功能:

  • 密碼到期,要求定期更改密碼;
  • 密碼重用限制,以防止再次選擇舊密碼;
  • 密碼驗證,要求更改密碼還指定要替換的當前密碼;
  • 雙密碼,使客戶端可以使用主密碼或輔助密碼進行連接;
  • 密碼強度評估,要求使用強密碼;
  • 隨機密碼生成,作爲要求管理員指定明確的文字密碼的替代方法;
  • 密碼失敗跟蹤,用於在連續多次錯誤密碼登錄失敗後啓用臨時帳戶鎖定。

  示例,手動使帳戶密碼失效,在mysql.user系統表的相應行中標記密碼已過期:

mysql> ALTER USER 'cy'@'localhost' PASSWORD EXPIRE;

  要建立密碼有效期爲全局策略,可以在my.cnf文件中使用如下參數來控制,N爲天數,爲0是表示永不過期:
[mysqld]
default_password_lifetime=N

  也可以在運行時設置和持久化:

mysql> SET PERSIST default_password_lifetime = N;

  全局密碼過期策略適用於尚未設置覆蓋該策略的所有用戶,要爲單個用戶建立政策,請使用PASSWORD EXPIRE。

# 每隔180天更新一次密碼
mysql> CREATE USER 'cy'@'localhost' PASSWORD EXPIRE INTERVAL 180 DAY;
mysql> ALTER USER 'cy'@'localhost' PASSWORD EXPIRE INTERVAL 180 DAY;

# 禁用密碼有效期:
mysql> CREATE USER 'cy'@'localhost' PASSWORD EXPIRE NEVER;
mysql> ALTER USER 'cy'@'localhost' PASSWORD EXPIRE NEVER;

# 對語句命名的所有用戶遵循全局到期策略
mysql> CREATE USER 'cy'@'localhost' PASSWORD EXPIRE DEFAULT;
mysql> ALTER USER 'cy'@'localhost' PASSWORD EXPIRE DEFAULT;

# 在允許重複使用之前,至少需要更改5次密碼,至少需要經過365天
mysql> CREATE USER 'cy'@'localhost' PASSWORD HISTORY 5 PASSWORD REUSE INTERVAL 365 DAY;
mysql> ALTER USER 'cy'@'localhost' PASSWORD HISTORY 5 PASSWORD REUSE INTERVAL 365 DAY;

  密碼重用策略:使用 password_history和 password_reuse_interval系統變量控制,例如,禁止重複使用最近6個密碼或365天以內的密碼:
[mysqld]
password_history=6
password_reuse_interval=365

  關於用戶雙密碼、隨機密碼另起專題討論。

1.4 tls_option

  除基於用戶名和憑據的常規身份驗證外,MySQL還可以檢查X.509證書屬性,要爲MySQL帳戶指定與SSL/TLS相關的選項,請使用REQUIRE子句指定一個或多個tls_option值;REQUIRE選項的順序無關緊要,但是不能重複指定同一選項,可使用AND關鍵字指定多個REQUIRE。

tls_option: {
   SSL 表示該語句命名的所有帳戶都沒有SSL或X.509要求
 | X509
 | CIPHER 'cipher'
 | ISSUER 'issuer'
 | SUBJECT 'subject'
}

  tls_option值:

  • NONE:REQUIRE默認值,表示該語句命名的所有帳戶都沒有SSL或X.509要求,如果用戶名和密碼有效,則允許未加密的連接;如果客戶端具有正確的證書和密鑰文件,則可以選擇使用加密連接。

  • SSL:服務器僅允許該語句命名的所有帳戶的加密連接,客戶端默認嘗試建立安全連接,對於REQUIRE SSL帳戶,如果無法建立安全連接,則連接將失敗。

  • X509:對於該語句命名的所有帳戶,要求客戶出示有效的證書,但是確切的證書,頒發者和主題不重要。唯一的要求是其中有CA證書來進行身份驗證,X.509證書是加密使用的,因此SSL在這種情況下並不是必要的。對具有REQUIRE X509的帳戶,客戶必須指定–ssl-key 和–ssl-cert選項進行連接(建議但不要求指定–ssl-ca,以便可以驗證服務器提供的公共證書)。

  • ISSUER ‘issuer’:對於該語句命名的所有帳戶,要求客戶端出示由CA頒發的有效的X.509證書 ,如果客戶端出示的證書有效但頒發者不同,則服務器將拒絕連接;X.509證書是加密使用的,因此SSL在這種情況下並不是必要的。因爲ISSUER需要X509,所以客戶端必須指定–ssl-key和–ssl-cert選項進行連接。(建議但不要求指定–ssl-ca,以便可以驗證服務器提供的公共證書。)

  • SUBJECT ‘subject’:對於該語句命名的所有帳戶,要求客戶端出示包含subject的有效X.509證書;如果客戶端出示的證書有效但subject不同,則服務器拒絕連接;X.509證書的使用暗含加密,因此SSL在這種情況下並不是必要的。

  • CIPHER ‘cipher’:對於該語句命名的所有帳戶,都需要使用特定的加密方法來加密連接,需要使用此選項來確保使用足夠強度的密碼和密鑰長度,如果使用使用短加密密鑰的舊算法,則加密可能會很弱。
    REQUIRE clause裏SUBJECT,ISSUER和CIPHER選項可組合使用。

1.5 resource_option

  限制客戶端使用MySQL服務器資源的一種方法是將全局max_user_connections系統變量設置爲非零值,這限制了任何給定帳戶可以建立的同時連接的數量,但是對客戶端一旦連接後可以執行的操作沒有任何限制,此外,設置max_user_connections無法啓用單個帳戶的管理,爲此,MySQL允許限制使用這些服務器資源的個人帳戶:

  • 帳戶每小時可發出的查詢數量
  • 帳戶每小時可以發佈的更新次數
  • 帳戶每小時可以連接到服務器的次數
  • 帳戶同時連接到服務器的數量

  客戶端發出的任何語句都將計入查詢限制,但計入更新限制的只有修改數據庫或表的語句。

resource_option: {
    MAX_QUERIES_PER_HOUR count
  | MAX_UPDATES_PER_HOUR count
  | MAX_CONNECTIONS_PER_HOUR count
  | MAX_USER_CONNECTIONS count
}

  resource_option可以限制帳戶對服務器資源的使用,使用WITH指定一個或多個resource_option值,WITH選項的順序無關緊要,多次指定給定的某個資源限制,以最後的爲準。

  CREATE USER的resource_option值:

  • MAX_QUERIES_PER_HOUR count,MAX_UPDATES_PER_HOUR count,MAX_CONNECTIONS_PER_HOUR count:對於該語句命名的所有帳戶,這些選項限制了在任何給定的每小時內允許帳戶進行查詢、更新和與服務器的連接的次數,如果count爲 0(默認值),則表示該帳戶沒有限制。

  • MAX_USER_CONNECTIONS count:對於該語句命名的所有帳戶,限制每個帳戶同時連接到服務器的最大數量(併發數);如果 count爲0 (默認值),則服務器根據max_user_connections系統變量的全局值確定該帳戶的併發連接數 ,如果max_user_connections也爲零,則該帳戶沒有限制。

1.6 password_option

password_option: {
    PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL N DAY]
  | PASSWORD HISTORY {DEFAULT | N}
  | PASSWORD REUSE INTERVAL {DEFAULT | N DAY}
  | PASSWORD REQUIRE CURRENT [DEFAULT | OPTIONAL]
  | FAILED_LOGIN_ATTEMPTS N
  | PASSWORD_LOCK_TIME {N | UNBOUNDED}
}

  CREATE USER支持多個password_option密碼管理值:

  • 密碼到期選項:可以手動使帳戶密碼到期並建立其密碼到期策略。策略選項不會使密碼失效,而是根據密碼有效期來確定服務器如何將自動過期應用於帳戶,該有效期是根據最近的帳戶密碼更改的日期和時間來確定。

  • 密碼重用選項:可以基於密碼更改次數、經過時間或兩者兼而有之來限制密碼重用。

  • 密碼驗證所需的選項:可以規定更改帳戶密碼時是否必須輸入當前密碼,以驗證嘗試進行更改的用戶實際上是否知道當前密碼。

  • 錯誤密碼失敗登錄跟蹤選項:跟蹤登錄失敗並暫時鎖定多次密碼輸入錯誤的賬戶,失敗次數和鎖定時間是可配置的。

  注意:除了與失敗登錄跟蹤有關的選項外,密碼管理選項僅適用於使用身份驗證插件的帳戶,該身份驗證插件將憑據存儲在內部。對於使用插件對MySQL外部的憑據系統執行身份驗證的帳戶,密碼管理也必須在外部針對該系統進行處理。
  如果帳戶密碼是手動過期的,或者根據自動過期策略,密碼年齡超過定義的生存期,則客戶端的密碼將過期;在這種情況下,服務器要麼斷開與客戶端的連接,要麼限制其允許的操作,受限制的客戶端執行的操作會導致錯誤,直到用戶建立新的帳戶密碼。

  CREATE USER允許使用以下password_option值來控制密碼的有效期:

  • PASSWORD EXPIRE:立即將該語句命名的所有帳戶的密碼標記爲過期。
  • PASSWORD EXPIRE DEFAULT:該參數定義的賬戶將應用default_password_lifetime系統全局到期策略。
  • PASSWORD EXPIRE NEVER:該到期選項將覆蓋該語句命名的所有帳戶的全局策略,對於每個密碼,它都會禁用密碼過期,以使密碼永不過期。
  • PASSWORD EXPIRE INTERVAL N DAY:該到期選項將覆蓋該語句命名的所有帳戶的全局策略,對於每個密碼,它將密碼有效期設置爲N幾天。
# 每365天更換一次密碼
mysql> CREATE USER 'cy'@'localhost' PASSWORD EXPIRE INTERVAL 365 DAY;

  用於根據所需的最小密碼更改次數來控制先前密碼的重用,CREATE USER允許這些password_option值:

  • PASSWORD HISTORY DEFAULT:該參數定義的賬戶會應用有關密碼歷史記錄長度的全局策略,禁止在password_history系統變量指定的更改次數之前重複使用密碼 。
  • PASSWORD HISTORY N:此歷史記錄長度選項將覆蓋該語句命名的所有帳戶的全局策略,將密碼歷史記錄設置爲N,則禁止重複使用之前任何N以內的密碼,以下語句禁止重用之前的6個密碼:
mysql> CREATE USER 'cy'@'localhost' PASSWORD HISTORY 6;

  根據經過的時間來控制先前密碼的重用,CREATE USER允許這些password_option值用:

  • PASSWORD REUSE INTERVAL DEFAULT:該值定義的帳戶將應用有關經過時間的全局策略,以禁止重複使用password_reuse_interval指定的天數內的新密碼。
  • PASSWORD REUSE INTERVAL N DAY:這個選項會覆蓋該語句命名的所有帳戶的全局策略,密碼重用間隔設置爲N天,即禁止重用N天內的新密碼。

  CREATE USER允許使用這些 password_option值來控制嘗試更改帳戶密碼是否必須指定當前密碼,以驗證嘗試進行更改的用戶實際上是否知道當前密碼:

  • PASSWORD REQUIRE CURRENT:該驗證選項將覆蓋該語句命名的所有帳戶的全局策略,對於每個密碼,要求更改密碼時指定當前密碼。

  • PASSWORD REQUIRE CURRENT OPTIONAL:該驗證選項將覆蓋該語句命名的所有帳戶的全局策略,對於每個密碼,不需要更改密碼即可指定當前密碼(可以但不必提供當前密碼)。

  • PASSWORD REQUIRE CURRENT DEFAULT:該選項定義的賬戶將應用password_require_current有關密碼驗證的全局策略 。

  從MySQL 8.0.19開始,CREATE USER允許使用以下password_option值來控制登錄失敗跟蹤:

  • FAILED_LOGIN_ATTEMPTS N:N必須爲0到32767之間的數字,值0會禁用登錄失敗跟蹤,大於0的值表示有多少連續密碼失敗導致臨時帳戶鎖定(如果PASSWORD_LOCK_TIME也是非零的話)。

  • PASSWORD_LOCK_TIME {N | UNBOUNDED}:定義連續多次密碼輸入錯誤後的賬戶鎖定時長, N必須是0到32767之間的數字、或者UNBOUNDED,值爲0將禁用臨時帳戶鎖定,大於0的值表示鎖定帳戶的天數,值 UNBOUNDED導致帳戶鎖定時間不受限制;一旦鎖定,該帳戶將保持鎖定狀態,直到被解鎖。

  爲了進行失敗的登錄跟蹤和臨時鎖定,帳戶FAILED_LOGIN_ATTEMPTS和 PASSWORD_LOCK_TIME選項都必須爲非零,創建帳戶在連續6次密碼失敗後保持鎖定狀態3天:

mysql> CREATE USER 'cy'@'localhost' FAILED_LOGIN_ATTEMPTS 6 PASSWORD_LOCK_TIME 3;

1.7 lock_option

lock_option: {
    ACCOUNT LOCK
  | ACCOUNT UNLOCK
}

  MySQL支持使用ACCOUNT LOCK和ACCOUNT UNLOCK選項鎖定和解鎖帳戶,在CREATE USER和ALTER USER子句中使用, ALTER USER … UNLOCK解鎖由由於登錄失敗次數過多而暫時鎖定的任何帳戶。

  帳戶鎖定狀態記錄在系統表mysql.user的account_locked列中,SHOW CREATE USER可查看帳戶是鎖定還是未鎖定,如果客戶端嘗試連接到鎖定的帳戶,連接將失敗,同時服務器端的Locked_connects狀態變量值遞增,並返回 ER_ACCOUNT_HAS_BEEN_LOCKED錯誤,並將消息寫入錯誤日誌:

Access denied for user 'user_name'@'host_name'.
Account is locked.

2. 用戶管理

2.1 ALTER用戶

  ALTER USER允許爲現有帳戶修改身份驗證,角色,SSL / TLS,資源限制和密碼管理屬性,也可以用於鎖定和解鎖帳戶;在大多數情況下,ALTER USER需要全局CREATE USER或系統UPDATE權限。

# 語法
ALTER USER [IF EXISTS]
    user [auth_option] [, user [auth_option]] ...
    [REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
    [WITH resource_option [resource_option] ...]
    [password_option | lock_option] ...
    [COMMENT 'comment_string' | ATTRIBUTE 'json_object']

  來幾個例子:

mysql> ALTER USER 'cy'@'localhost' IDENTIFIED BY 'King_123';

mysql> ALTER USER 'cy'@'localhost' ACCOUNT UNLOCK;

mysql> ALTER USER 'cy'@'localhost' IDENTIFIED BY '123456',
  'yx'@'localhost' IDENTIFIED BY '789012' 
  REPLACE 'josh_current_password' RETAIN CURRENT PASSWORD
  REQUIRE SSL WITH MAX_USER_CONNECTIONS 2
  PASSWORD HISTORY 5;
  
mysql> ALTER USER 'cy'@'localhost'
  IDENTIFIED WITH mysql_native_password BY '123456'
  REPLACE 'current_password';
  
mysql> ALTER USER 'jeffrey'@'localhost'
FAILED_LOGIN_ATTEMPTS 6 PASSWORD_LOCK_TIME 3;

2.2 DROP用戶

  執行drop操作必須具有全局CREATE USER權限或系統級別的DELETE權限,對於只讀環境,DROP USER還需要CONNECTION_ADMIN權限。

# 語法
DROP USER [IF EXISTS] user [, user] ...
# 例子
mysql> DROP USER 'cy'@'localhost';
mysql> DROP USER 'cy'@'%';
mysql> DROP USER 'cy';

  注意:帳戶名的主機名部分(如果省略)默認爲’%’,所以’cy’@’%'與’cy’爲同一用戶;DROP USER不會自動關閉任何打開的用戶會話,相反,如果刪除了具有打開的會話的用戶,則該語句在該用戶的會話關閉之前不會生效,直到該會話關閉drop才生效,並且該用戶的下一次登錄將失敗。

  用SELECT和CONCAT來批量刪除的SQL語句:

mysql> SELECT DISTINCT CONCAT(' drop user ''',user,'''@''',host,''';') AS query FROM mysql.user;
+--------------------------------------------+
| query                                      |
+--------------------------------------------+
|  drop user 'cy'@'192.183.3.147';           |
|  drop user 'cy'@'localhost';               |
|  drop user 'mysql.infoschema'@'localhost'; |
|  drop user 'mysql.session'@'localhost';    |
|  drop user 'mysql.sys'@'localhost';        |
|  drop user 'root'@'localhost';             |
|  drop user 'yx'@'localhost';               |
+--------------------------------------------+
7 rows in set (0.03 sec)

2.3 RENAME USER

   要使用RENAME USER必須具有全局CREATE USER權限或系統級別的UPDATE權限,在read_only環境下,RENAME USER還需要CONNECTION_ADMIN 權限,對於不存在的舊帳戶或已經存在的新帳戶,將發生錯誤。

# 語法
RENAME USER old_user TO new_user
    [, old_user TO new_user] ...

# 例子   
mysql> RENAME USER 'cy'@'localhost' TO 'cy'@'127.0.0.1';

  RENAME USER使舊用戶擁有的權限成爲新用戶擁有的權限,但是, RENAME USER不會自動刪除舊用戶創建的數據庫或其中的數據庫或對象或使它們無效,這包括DEFINER屬性名稱爲舊用戶的存儲程序或視圖。

2020年6月19日
   “有時候會想,生命裏某些當時充滿怨懟的曲折,在後來好像都成了一種能量和養分,因爲若非這些曲折,好像就不會在人生的岔路上遇見別人可能求之亦不得見的人與事;而這些人、那些事在經過時間的篩濾之後,幾乎都只剩下笑與淚與感動和溫暖,曾經的怨與恨與屈辱和不滿彷彿都已雲消霧散。” ——吳念真《這些人,那些事》
   翻篇了……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章