原文来自静雅斋,转载请注明出处。0x00Status作者的博客是用Ghost+PostgreSQL搭建的。最近,官方发布了支持LTS的RoadMap。因此,Ghost得到了升级。同时node也升级到了6.x版本。我认为升级小版本会很容易而且没有压力。结果重启Ghost直接报错ERROR:passwordauthenticationfailedforuser"ghost"error:passwordauthenticationfailedforuser"ghost"atConnection.parseE(/home/ghost/node_modules/.4.1.1@pg/lib/connection.js:534:11)在Connection.parseMessage(/home/ghost/node_modules/.4.1.1@pg/lib/connection.js:361:17)在TLSSocket.(/home/ghost/node_modules/.4.1.1@pg/lib/connection.js:105:22)在emitOne(events.js:96:13)在TLSSocket.emit(events.js:188:7)在readableAddChunk(_stream_readable.js:176:18)atTLSSocket.Readable.push(_stream_readable.js:134:10)atTLSWrap.onread(net.js:548:20)0x01回滚版本遇到升级错误,第一反应是回滚版本,这已经是一种习惯了,但是忘记了之前的版本号,只能尝试回滚版本,结果发现所有版本都有这个问题,开始陷入僵局(忘记了该节点已从4.x升级到6.x)。所以只能暂时将数据库从PostgreSQL迁移到MySQL0x02来分析问题。从上面的报错信息来看,是密码验证错误导致的,但实际上密码是正确的。PostgreSQL支持md5和密码验证。password以明文形式发送。作者使用了ssl加密和md5认证,于是查看了服务器上的PostgreSQL日志,没有发现认证错误。按理来说,这里可以排除数据库服务器的问题,但是作者多了一步,导致后面走了弯路。作者把密码验证方式改成password,明文发送,就OK了。于是开始怀疑是pg库和数据库有问题。但是摸索了半天也没找到问题所在,再google也没有找到类似的情况。一般来说,遇到问题可以google一下。80%的问题都可以解决。google不到就去githubissue找。如果找不到,只有两种情况,低级bug或者前所未有的bug。0x03过段时间无意中去npm找pg依赖包,发现这个版本已经到了6.1.2版本,而Ghost官方的依赖版本是4.1.1,于是开始怀疑pg版本是不是太高了低的原因。同时,在Ghost官博上也发现了一个说法,称因为大家都在用MySQL,PostgreSQL里没有人可以发表评论,所以PostgreSQL要降级为“二等公民”。于是就去pg库的issue搜索,果然找到了两个用户关于升级node的问题。升级到最新版本的pg依赖项解决了问题。0x04源码是升级node6.x导致的问题。应该是API改了。最后发现问题出在Buffer上。源码如下msg.salt.toString('binary'));varmd5password="md5"+outer;con.password(md5password);}));改成下面的代码就可以成功//passwordrequesthandlingcon.on('authenticationMD5Password',checkPgPass(function(msg){varinner=Client.md5(self.password+self.user);varouter=Client.md5(Buffer.concat([newBuffer(inner),msg.salt]));varmd5password="md5"+outer;con.password(md5password);}));其实都不是Buffer的问题,只是crypto模块现在默认认为字符串是utf8而不是binary。如果没有指定编码,就会出现这个问题。0x05解决方案由于上游代码已经修复了这个bug,直接升级版本,然后到官网提交PR就可以了。