原文來自靜雅齋,轉載請註明出處。node
筆者博客是用 Ghost + PostgreSQL 搭建的,最近官方出了 RoadMap 作了 LTS 支持,所以作了 Ghost 的升級,同時也順手把 node 升級到了 6.x 版本,本覺得小版本升級輕鬆無壓力,結果重啓 Ghost 的時候直接報錯git
ERROR: password authentication failed for user "ghost" error: password authentication failed for user "ghost" at Connection.parseE (/home/ghost/node_modules/.4.1.1@pg/lib/connection.js:534:11) at Connection.parseMessage (/home/ghost/node_modules/.4.1.1@pg/lib/connection.js:361:17) at TLSSocket.<anonymous> (/home/ghost/node_modules/.4.1.1@pg/lib/connection.js:105:22) at emitOne (events.js:96:13) at TLSSocket.emit (events.js:188:7) at readableAddChunk (_stream_readable.js:176:18) at TLSSocket.Readable.push (_stream_readable.js:134:10) at TLSWrap.onread (net.js:548:20)
碰到升級出錯,第一反應就是回滾版本,已是習慣了,可是忘記以前的版本號了,只能嘗試着回滾版本,可是發現全部版本都有這個問題,開始陷入僵局(筆者忘了 node 從 4.x 被升級到了 6.x)。因此只能暫時先將數據庫從 PostgreSQL 遷移到了 MySQLgithub
從上面的錯誤信息來看是因爲密碼認證出錯的問題致使的,可是實際上密碼是正確的,PostgreSQL 支持 md5 和 password 兩種方式認證,password 就是明文發送,筆者使用的是 ssl 加密而且使用 md5 認證,因而乎上服務器查 PostgreSQL 日誌,可是並無發現認證出錯的狀況,照理來講這裏已經能夠排除是數據庫服務器的問題了,可是筆者又多作了一步,致使後面走了彎路。筆者將密碼認證方式改成 password 明文發送,就 OK 了。結果就開始懷疑 pg 庫和數據庫的問題了。可是摸索了半天並無發現問題所在,而後 google 了也沒有找到相似的狀況,通常來講,遇到問題就 google,80% 的問題都能解決,google 不到就去 github issue 上找,若是還找不到就只有兩種狀況,低級 bug 或者前無古人的 bug。數據庫
過了一段時間,偶然去了 npm 上面找了一下 pg 依賴包,發現這個版本已經到了 6.1.2 版本了,而 Ghost 官方依賴的版本是 4.1.1,就開始懷疑是否是 pg 版本太低的緣由了。與此同時,在 Ghost 官方博客上面也找到了一條聲明,表示因爲你們都用 MySQL,PostgreSQL 沒人能提交意見,所以準備將 PostgreSQL 降級爲「二等公民」。因此就前往 pg 庫的 issue 上找了一下,還真找到了兩條用戶關於升級 node 後的問題。升級到最新版本的 pg 依賴就解決了問題。npm
因爲是升級 node6.x 帶來的問題,應該是 API 上作了改動,最終發現是 Buffer 上出現的問題,源代碼以下服務器
//password request handling con.on('authenticationMD5Password', checkPgPass(function(msg) { var inner = Client.md5(self.password + self.user); var outer = Client.md5(inner + msg.salt.toString('binary')); var md5password = "md5" + outer; con.password(md5password); }));
改爲以下代碼就成功了google
//password request handling con.on('authenticationMD5Password', checkPgPass(function(msg) { var inner = Client.md5(self.password + self.user); var outer = Client.md5(Buffer.concat([new Buffer(inner), msg.salt])); var md5password = "md5" + outer; con.password(md5password); }));
實際上也不算是 Buffer 的問題,而是 crypto 模塊如今默認認爲字符串爲 utf8,而不是 binary,若是沒有指定 encoding,就會出現這個問題。加密
既然上游代碼都已經修復了這個 bug,直接升級版本就好了,而後提一個 PR 到官方就 ok。日誌