You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CA证书配置Vapor中MySQLKit的MySQL连接

问题描述

我在Vapor后端项目中使用MySQLKit,本地数据库连接配置如下,可正常工作:

let config = MySQLConfiguration(hostname: "127.0.0.1", port: 3306, username: "root", password: "s3#12412r657f", database: "Admin", tlsConfiguration: nil)

现在需要连接远程MySQL数据库,该数据库需要SSL CA证书(PEM格式的ca_cert.crt),在MySQL Workbench的SSL标签页指定该CA文件路径后可正常连接,但在Vapor中配置TLS时遇到问题。

我尝试的配置如下:

static let prod: MySQLConfiguration = {
    
    var tls = TLSConfiguration.makeClientConfiguration()
      
    do {

        let bytes = [UInt8]("""
        -----BEGIN CERTIFICATE-----
        EX_CERTIFICATE_STRINGS...
        -----END CERTIFICATE-----
        """.data(using: .utf8)!)
        let cert: NIOSSLCertificate = try .init(bytes: bytes, format: .pem)
        tls.certificateChain = [.certificate(cert)]
        tls.privateKey = nil
        let config = MySQLConfiguration(hostname: "192.65.85.577", port: 3658, username: "testadmin", password: "dd#246$@erjt!df^67", database: "Elevate", tlsConfiguration: tls)
        return config
        
    } catch {
        
        fatalError("DB SSL CA Error: \(error.localizedDescription)")
    }
}()

执行数据库查询时出现证书验证失败错误:

{
    "error": true,
    "reason": "handshakeFailed(NIOSSL.BoringSSLError.sslError([Error: 268435581 error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED at /Users/At4/Library/Developer/Xcode/DerivedData/Elevate-xcftyy3423/SourcePackages/checkouts/swift-nio-ssl/Sources/CNIOBoringSSL/ssl/handshake.cc:393]))"
}

相同的证书和连接参数在MySQL Workbench中可正常使用,求正确的Vapor+MySQLKit TLS配置方法。

解决方案

你的核心问题是把CA证书放错了配置项,同时证书文件的处理方式也可以优化:

1. 证书文件的放置位置

将ca_cert.crt文件放到Vapor项目的Resources文件夹下(没有则新建),然后在Xcode中把该文件添加到项目目标,确保编译时会被复制到应用包内。

2. 正确的TLS配置

CA证书用于验证服务器证书的合法性,应该配置到TLS的trustRoots字段,而非certificateChain(后者是客户端证书,仅当服务器要求客户端身份验证时才需要)。

修改后的配置代码如下:

static let prod: MySQLConfiguration = {
    var tls = TLSConfiguration.makeClientConfiguration()
    
    do {
        // 读取Resources目录下的CA证书文件
        guard let certPath = Bundle.module.path(forResource: "ca_cert", ofType: "crt") else {
            fatalError("CA certificate file not found")
        }
        let certData = try Data(contentsOf: URL(fileURLWithPath: certPath))
        let cert = try NIOSSLCertificate(bytes: [UInt8](certData), format: .pem)
        
        // 将CA证书添加到信任根集合
        tls.trustRoots = .certificates([cert])
        // 无需客户端证书时,certificateChain和privateKey保持默认nil即可
        
        let config = MySQLConfiguration(
            hostname: "192.65.85.577",
            port: 3658,
            username: "testadmin",
            password: "dd#246$@erjt!df^67",
            database: "Elevate",
            tlsConfiguration: tls
        )
        return config
    } catch {
        fatalError("DB SSL CA Error: \(error.localizedDescription)")
    }
}()

3. 额外注意事项

  • 如果远程MySQL服务器的hostname与证书中的Common Name(CN)不匹配,可临时添加tls.verifyHostname = false跳过主机名验证,但这会降低安全性,仅在测试场景使用。
  • 直接读取证书文件比硬编码内容更可靠,也方便后续证书更新。

内容的提问来源于stack exchange,提问作者AppNameExMin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:57:36