配置应用程序的 SSL 连接性以安全连接到 Azure Database for MySQL

备注

将要查看的是 Azure Database for MySQL 的新服务。 若要查看经典 MySQL Database for Azure 的文档,请访问此页

Azure Database for MySQL 支持使用安全套接字层 (SSL) 将 Azure Database for MySQL 服务器连接到客户端应用程序。 通过在数据库服务器与客户端应用程序之间强制实施 SSL 连接,可以加密服务器与应用程序之间的数据流,有助于防止“中间人”攻击。

步骤 1:获取 SSL 证书

https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt.pem 下载通过 SSL 与 Azure Database for MySQL 服务器通信所需的证书,再将证书文件保存到本地驱动器(例如,本教程使用 c:\ssl)。

步骤 2:绑定 SSL

对于特定的编程语言连接字符串,请参考下面的示例代码

使用 MySQL Workbench 通过 SSL 连接到服务器

配置 MySQL Workbench,以便安全地通过 SSL 连接。

  1. 从“设置新连接”对话框,导航到“SSL”选项卡 。

  2. 将“使用 SSL” 字段更新为“必需”。

  3. 在“SSL CA 文件:”字段中,输入 DigiCertGlobalRootCA.crt.pem 的文件位置。

    保存 SSL 配置

对于现有连接,可以通过右键单击“连接”图标并选择“编辑”来绑定 SSL。 然后导航到“SSL”选项卡,并绑定证书文件。

使用 MySQL CLI 通过 SSL 连接到服务器

绑定 SSL 证书的另一种方法是使用 MySQL 命令行接口执行以下命令。

mysql.exe -h mydemoserver.mysql.database.chinacloudapi.cn -u Username@mydemoserver -p --ssl-mode=REQUIRED --ssl-ca=c:\ssl\DigiCertGlobalRootCA.crt.pem

备注

在 Windows 上使用 MySQL 命令行接口时,可能会收到错误 SSL connection error: Certificate signature check failed。 如果发生这种情况,请将 --ssl-mode=REQUIRED --ssl-ca={filepath} 参数替换为 --ssl

步骤 3:在 Azure 中强制实施 SSL 连接

使用 Azure 门户

在 Azure 门户中,访问 Azure Database for MySQL 服务器,并单击“连接安全性”。 使用切换按钮来启用或禁用“强制实施 SSL 连接”设置,并单击“保存” 。 Azure 建议你始终启用“强制实施 SSL 连接”设置,以增强安全性。

Azure 门户的屏幕截图,该门户用于在 Azure Database for MySQL 中强制进行 SSL 连接

使用 Azure CLI

可以通过在 Azure CLI 中分别使用“Enabled”或“Disabled”值来启用或禁用“ssl-enforcement”参数。

az mysql server update --resource-group myresource --name mydemoserver --ssl-enforcement Enabled

步骤 4:验证 SSL 连接

执行 mysql status 命令,验证是否已使用 SSL 连接到 MySQL 服务器:

mysql> status

查看输出以确认连接是否已加密,如果已加密,输出应显示为:“SSL: 使用中的密码为 AES256-SHA”

代码示例

若要从应用程序通过 SSL 与 Azure Database for MySQL 建立安全连接,请参阅以下代码示例:

请参阅 Azure Database for MySQL 服务支持的兼容驱动程序列表。

PHP

$conn = mysqli_init();
mysqli_ssl_set($conn,NULL,NULL, "/var/www/html/DigiCertGlobalRootCA.crt.pem", NULL, NULL) ; 
mysqli_real_connect($conn, 'mydemoserver.mysql.database.chinacloudapi.cn', 'myadmin@mydemoserver', 'yourpassword', 'quickstartdb', 3306, MYSQLI_CLIENT_SSL);
if (mysqli_connect_errno($conn)) {
die('Failed to connect to MySQL: '.mysqli_connect_error());
}

PHP(使用 PDO)

$options = array(
    PDO::MYSQL_ATTR_SSL_CA => '/var/www/html/DigiCertGlobalRootCA.crt.pem'
);
$db = new PDO('mysql:host=mydemoserver.mysql.database.chinacloudapi.cn;port=3306;dbname=databasename', 'username@mydemoserver', 'yourpassword', $options);

Python (MySQLConnector Python)

try:
    conn = mysql.connector.connect(user='myadmin@mydemoserver',
                                   password='yourpassword',
                                   database='quickstartdb',
                                   host='mydemoserver.mysql.database.chinacloudapi.cn', 
                                   ssl_ca='/var/www/html/DigiCertGlobalRootCA.crt.pem')
except mysql.connector.Error as err:
    print(err)

Python (PyMySQL)

conn = pymysql.connect(user='myadmin@mydemoserver',
                       password='yourpassword',
                       database='quickstartdb',
                       host = 'mydemoserver.mysql.database.chinacloudapi.cn', 
                       ssl={'ca': '/var/www/html/DigiCertGlobalRootCA.crt.pem'})

Django (PyMySQL)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'quickstartdb',
        'USER': 'myadmin@mydemoserver',
        'PASSWORD': 'yourpassword',
        'HOST': 'mydemoserver.mysql.database.chinacloudapi.cn',
        'PORT': '3306',
        'OPTIONS': {
            'ssl': {'ca': '/var/www/html/DigiCertGlobalRootCA.crt.pem'}
        }
    }
}

Ruby

client = Mysql2::Client.new(
        :host     => 'mydemoserver.mysql.database.chinacloudapi.cn', 
        :username => 'myadmin@mydemoserver',
        :password => 'yourpassword',
        :database => 'quickstartdb',
        :ssl_ca => '/var/www/html/DigiCertGlobalRootCA.crt.pem'
    )

Golang

rootCertPool := x509.NewCertPool()
pem, _ := ioutil.ReadFile("/var/www/html/DigiCertGlobalRootCA.crt.pem")
if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
    log.Fatal("Failed to append PEM.")
}
mysql.RegisterTLSConfig("custom", &tls.Config{RootCAs: rootCertPool})
var connectionString string
connectionString = fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?allowNativePasswords=true&tls=custom",'myadmin@mydemoserver' , 'yourpassword', 'mydemoserver.mysql.database.chinacloudapi.cn', 'quickstartdb')    
db, _ := sql.Open("mysql", connectionString)

Java(适用于 Java 的 MySQL 连接器)

# generate truststore and keystore in code
String importCert = " -import "+
    " -alias mysqlServerCACert "+
    " -file " + ssl_ca +
    " -keystore truststore "+
    " -trustcacerts " +
    " -storepass password -noprompt ";
String genKey = " -genkey -keyalg rsa " +
    " -alias mysqlClientCertificate -keystore keystore " +
    " -storepass password123 -keypass password " +
    " -dname CN=MS ";
sun.security.tools.keytool.Main.main(importCert.trim().split("\\s+"));
sun.security.tools.keytool.Main.main(genKey.trim().split("\\s+"));

# use the generated keystore and truststore
System.setProperty("javax.net.ssl.keyStore","path_to_keystore_file");
System.setProperty("javax.net.ssl.keyStorePassword","password");
System.setProperty("javax.net.ssl.trustStore","path_to_truststore_file");
System.setProperty("javax.net.ssl.trustStorePassword","password");

url = String.format("jdbc:mysql://%s/%s?serverTimezone=UTC&useSSL=true", 'mydemoserver.mysql.database.chinacloudapi.cn', 'quickstartdb');
properties.setProperty("user", 'myadmin@mydemoserver');
properties.setProperty("password", 'yourpassword');
conn = DriverManager.getConnection(url, properties);

Java(适用于 Java 的 MariaDB 连接器)

# generate truststore and keystore in code
String importCert = " -import "+
    " -alias mysqlServerCACert "+
    " -file " + ssl_ca +
    " -keystore truststore "+
    " -trustcacerts " +
    " -storepass password -noprompt ";
String genKey = " -genkey -keyalg rsa " +
    " -alias mysqlClientCertificate -keystore keystore " +
    " -storepass password123 -keypass password " +
    " -dname CN=MS ";
sun.security.tools.keytool.Main.main(importCert.trim().split("\\s+"));
sun.security.tools.keytool.Main.main(genKey.trim().split("\\s+"));

# use the generated keystore and truststore
System.setProperty("javax.net.ssl.keyStore","path_to_keystore_file");
System.setProperty("javax.net.ssl.keyStorePassword","password");
System.setProperty("javax.net.ssl.trustStore","path_to_truststore_file");
System.setProperty("javax.net.ssl.trustStorePassword","password");

url = String.format("jdbc:mariadb://%s/%s?useSSL=true&trustServerCertificate=true", 'mydemoserver.mysql.database.chinacloudapi.cn', 'quickstartdb');
properties.setProperty("user", 'myadmin@mydemoserver');
properties.setProperty("password", 'yourpassword');
conn = DriverManager.getConnection(url, properties);

.NET (MySqlConnector)

var builder = new MySqlConnectionStringBuilder
{
    Server = "mydemoserver.mysql.database.chinacloudapi.cn",
    UserID = "myadmin@mydemoserver",
    Password = "yourpassword",
    Database = "quickstartdb",
    SslMode = MySqlSslMode.VerifyCA,
    SslCa = "DigiCertGlobalRootCA.crt.pem",
};
using (var connection = new MySqlConnection(builder.ConnectionString))
{
    connection.Open();
}

Node.js

var fs = require('fs');
var mysql = require('mysql');
const serverCa = [fs.readFileSync("/var/www/html/DigiCertGlobalRootCA.crt.pem", "utf8")];
var conn=mysql.createConnection({
    host:"mydemoserver.mysql.database.chinacloudapi.cn",
    user:"myadmin@mydemoserver",
    password:"yourpassword",
    database:"quickstartdb",
    port:3306,
    ssl: {
        rejectUnauthorized: true,
        ca: serverCa
    }
});
conn.connect(function(err) {
  if (err) throw err;
});

后续步骤

Connection libraries for Azure Database for MySQL(Azure Database for MySQL 的连接库)中查看各种应用程序连接性选项