NodeJS mysql/xdevapi 'Access denied' 使用 SSL 和 X 协议

NodeJS mysql/xdevapi 'Access denied' using SSL and X Protocol

我正在尝试使用 X 协议和 SSL 连接到我的 mysql 服务器。
要连接到数据库,我使用 MySQL x devapi for NodeJs(mysql/xdevapi)。 MySQL 服务器和我的 nodejs 应用程序都在同一台机器上 运行。然而,每次我尝试建立连接时,我都会收到以下错误:

Error: Access denied for user 'accountservice'@'localhost' (using password: YES)
at AuthenticationHandler.BaseHandler.<computed> (F:\Repositorys\Project\Application\node_modules\@mysql\xdevapi\lib\Protocol\ResponseHandlers\BaseHandler.js:113:19)
at Array.entry (F:\Repositorys\Project\Application\node_modules\@mysql\xdevapi\lib\Protocol\ResponseHandlers\BaseHandler.js:90:29)
at WorkQueue.process (F:\Repositorys\Project\Application\node_modules\@mysql\xdevapi\lib\WorkQueue.js:75:19)
at Client.handleServerMessage (F:\Repositorys\Project\Application\node_modules\@mysql\xdevapi\lib\Protocol\Client.js:201:21)
at Client.handleNetworkFragment (F:\Repositorys\Project\Application\node_modules\@mysql\xdevapi\lib\Protocol\Client.js:245:14)
at Socket.<anonymous> (F:\Repositorys\Project\Application\node_modules\@mysql\xdevapi\lib\Protocol\Client.js:89:36)
at Socket.emit (events.js:315:20)
at addChunk (_stream_readable.js:296:12)
at readableAddChunk (_stream_readable.js:272:9)
at Socket.Readable.push (_stream_readable.js:213:10) {
 info: {
  severity: 0,
  code: 1045,
  sqlState: 'HY000',
  msg: "Access denied for user 'username'@'localhost' (using password: YES)"
 }
}

起初我以为我的密码可能是错误的或者我的证书无效但是使用
mysql -u username -p --ssl-ca=/etc/certs/ca.pem --ssl-cert=../res/certs/mysql/client-cert.pem --ssl-key=../res/certs/mysql/client-key.pem
登录我没有错误。

除此之外,我还授予我的用户对所有数据库和表的所有权限,以确保缺少权限不是连接失败的原因。
我能想到的唯一可能性是验证服务器证书时出错,即使 openssl verify -CAfile ca.pem server-cert.pem returns server-cert.pem: OK.

为了连接到数据库,我使用以下用 TypeScript 编写的代码

const conf = {
    host: 'localhost',//config.getHost(),
    port: 33060,//config.getPort(),
    user: 'username',//config.getUsername(),
    password: 'password',//config.getPassword(),
    schema: 'database',//config.getDatabase(),

    auth: 'SHA256_MEMORY', //removing this results in "Invalid authentication method PLAIN"

    ssl: {
        key: config.getCertKey(),
        cert: config.getCert(),
        ca: config.getCa()
    }
}

this.client = mysql.getClient(conf);

connect(next) {
    console.log('Connecting to database ' + this.config.getDatabase() + '(' + this.config.getHost() + ':' + this.config.getPort() + ')...');
    this.client.getSession().then(session => {
        this.session = session;
        console.log('Connection to database ' + this.config.getDatabase() + '(' + this.config.getHost() + ':' + this.config.getPort() + ') established.');
        listen(this, next);
    }).catch((err) => {
        console.log('Failed to establish connection to database ' + this.config.getDatabase() + '(' + this.config.getHost() + ':' + this.config.getPort() + ').');
        console.log(err);
    });
}

也许我错过了一个非常重要的步骤,但目前我不知道是什么导致了这个问题,尽管在 Whosebug 和其他页面上阅读了多个答案。

Public-密钥身份验证不是首要问题-class API 但没有什么能阻止您提供密钥,在这种情况下,在 sslOptions 属性(不是配置对象中的 ssl 属性)。这些选项将在调用 tls.connect(). By contrast, there's API support for certificate authority validation, which in that case only requires you to define the path to the CA file (as described here).

时简单地合并

像下面这样的东西应该可以解决问题:

const conf = {
  //...
  sslOptions: {
    // read contents of key.pem and cert.pem
    key: fs.readFileSync('/path/to/key.pem')
    cert: fs.readFileSync('/path/to/cert.pem'),
    // path (only) to ca.pem
    ca: '/path/to/ca.pem'
  }
}

如果您已经在使用 8.0.20 版,则此风格已被弃用,您应该改用:

const conf = {
  //...
  tls: {
    key: fs.readFileSync('/path/to/key.pem')
    cert: fs.readFileSync('/path/to/cert.pem'),
    ca: '/path/to/ca.pem'
  }
}

你得到 Invalid authentication method PLAIN 错误的原因是因为客户端天真地假设因为 ssl 不是 true,那么这意味着 TLS 应该被禁用,这并不使用默认身份验证机制 PLAIN

无论如何,一旦您开始使用 sslOptions,这种情况就会消失。

免责声明:我是 MySQL X DevAPI Connector for Node.js

的首席开发人员