Qt MySQL 通过 SSL 连接到 Azure

Eej*_*jin 6 mysql ssl qt azure mysql-connector

我正在尝试使用 SSL 连接到 Azure MySQL 5.7,但遇到了一个似乎无法解决的错误。

连接适用于

  • mysql.exe
  • MySQL 工作台 8.0

连接不适用于

  • Qt
  • MySQL 连接器/C 8.0.18

我使用以下工作命令调用 mysql.exe

mysql.exe -h server.mysql.database.azure.com -u user@server -p --ssl

这会连接并且不会出现任何问题。MySQL Workbench 8.0 也能正常工作。

但是随后使用 Qt MySQL 插件进行连接会产生此错误。

SSL connection error: socket layer receive error

这是我用来连接的 Qt 代码

QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");

db.setHostName("server.mysql.database.azure.com");
db.setPort(3306);
db.setDatabaseName("databasename");
db.setUserName("user@server");
db.setPassword("password");
db.setConnectOptions("SSL_CA=C:/Users/User/Downloads/BaltimoreCyberTrustRoot.crt.pem");
if (!db.open()) {
    std::cout << db.lastError().text().toStdString() << "\n";   
}
Run Code Online (Sandbox Code Playgroud)

接下来我尝试使用 MySQL Connector/C(Qt 在下面使用)直接连接到 Azure 数据库。

MYSQL* mysql = mysql_init(nullptr);

char* t = "C:/Users/User/Downloads/BaltimoreCyberTrustRoot.crt.pem";

mysql_ssl_set(mysql, nullptr, nullptr, t, nullptr, nullptr);

if (!mysql_real_connect(mysql, "server.mysql.database.azure.com", "user@server", "password", "databasename", 3306, nullptr, 0)) {
    fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(mysql));
}
mysql_close(mysql);
Run Code Online (Sandbox Code Playgroud)

这两者都会产生套接字层错误。

在 Azure 中禁用 SSL 允许我连接 Qt 和 MySQL Connector/C。这意味着连接数据(用户名、密码、主机名)是正确的,但设置 SSL 选项可能存在问题。

Qt 版本 5.13.1
MySQL 连接器/C 8.0.18
MySQL DB 5.7

小智 2

我没有接触过 Qt,但我接触过 MySQL 和 SSL,所以读完你的问题后我很感兴趣。

我不敢告诉您,Qt 似乎无意中通过此更新编码了传输安全功能:

https://codereview.qt-project.org/c/qt/qtbase/+/96849/11/src/sql/drivers/mysql/qsql_mysql.cpp

我无意中这么说是因为我不敢相信他们打算用客户端证书身份验证替换 CLIENT_SSL。CLIENT_SSL 仍然是 mysql_real_connect 接口的有效选项,但选项验证忽略它。如果没有联系,我只能假设开发人员的任务是更新代码以支持客户端证书和混淆客户端证书与传输加密,交换功能而不是添加功能。

这一重大更改是在 5.5 版本中引入的。如果您足够大胆,您可以提取代码库并进行更改:

    else if (opt == QLatin1String("CLIENT_SSL"))
        qWarning("QMYSQLDriver: SSL_KEY, SSL_CERT and SSL_CA should be used instead of CLIENT_SSL.");
Run Code Online (Sandbox Code Playgroud)

到:

    else if (opt == QLatin1String("CLIENT_SSL"))
        optionFlags |= CLIENT_SSL;
Run Code Online (Sandbox Code Playgroud)

编译&祝你好运...或者你有这些选择。

  1. 降级到 Qt 5.2(是的,我知道,但是......)
  2. 如果您有 CA 私钥,请生成由 CA 签名的客户端证书并添加 SSL_CERT 和 SSL_KEY 连接选项,并希望这足够了(我没有更深入地研究代码)