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

如何在Rust中用rustls结合Windows证书存储认证PostgreSQL连接?

在Rust中使用rustls结合PostgreSQL/Diesel(Windows证书存储)实现TLS认证

核心依赖

先把需要的依赖加到Cargo.toml里,根据场景选择同步/异步、是否用Diesel:

# 基础同步版依赖
[dependencies]
postgres = "0.19"
postgres-rustls = "0.23"
rustls = "0.21"
rustls-native-certs = "0.6"

# 异步版(需添加tokio)
postgres = { version = "0.19", features = ["tokio"] }
tokio = { version = "1.0", features = ["full"] }

# Diesel适配版
diesel = { version = "2.0", features = ["postgres", "r2d2"] }

一、postgres crate + rustls 同步连接示例

直接上代码,关键步骤附注释:

use postgres::Config;
use postgres_rustls::MakeRustlsConnect;
use rustls::RootCertStore;
use rustls_native_certs::load;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 加载Windows系统证书存储中的受信任根CA
    let system_certs = load()?;
    let mut root_store = RootCertStore::empty();
    for cert in system_certs {
        // 转换为rustls兼容格式并添加到根存储
        root_store.add(&rustls::Certificate(cert.0))?;
    }

    // 2. 构建rustls客户端配置
    let tls_config = rustls::ClientConfig::builder()
        .with_safe_defaults() // 使用rustls默认安全套件
        .with_root_certificates(root_store) // 绑定系统根CA
        .with_no_client_auth(); // 单向TLS(仅验证服务器证书)

    // 3. 把rustls配置包装成postgres客户端能识别的TLS连接器
    let tls_connector = MakeRustlsConnect::new(tls_config);

    // 4. 配置PostgreSQL连接参数
    let mut db_config = Config::new();
    db_config
        .host("your-db-host")
        .port(5432)
        .user("your-db-user")
        .password("your-db-password")
        .dbname("your-db-name");

    // 5. 建立带TLS的数据库连接
    let client = db_config.connect(tls_connector)?;

    // 测试连接:查询PostgreSQL版本
    let rows = client.query("SELECT version();", &[])?;
    let version: String = rows[0].get(0);
    println!("Connected to PostgreSQL: {}", version);

    Ok(())
}

二、异步版postgres连接

异步场景只需调整连接逻辑为异步调用:

use postgres::Config;
use postgres_rustls::MakeRustlsConnect;
use rustls::RootCertStore;
use rustls_native_certs::load;
use tokio;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let system_certs = load()?;
    let mut root_store = RootCertStore::empty();
    for cert in system_certs {
        root_store.add(&rustls::Certificate(cert.0))?;
    }

    let tls_config = rustls::ClientConfig::builder()
        .with_safe_defaults()
        .with_root_certificates(root_store)
        .with_no_client_auth();

    let tls_connector = MakeRustlsConnect::new(tls_config);

    let mut db_config = Config::new();
    db_config
        .host("your-db-host")
        .port(5432)
        .user("your-db-user")
        .password("your-db-password")
        .dbname("your-db-name");

    // 异步建立连接
    let client = db_config.connect(tls_connector).await?;

    // 异步查询
    let rows = client.query("SELECT version();", &[]).await?;
    let version: String = rows[0].get(0);
    println!("Connected to PostgreSQL: {}", version);

    Ok(())
}

三、适配Diesel ORM

Diesel底层依赖postgres crate,只需把TLS连接器传入Diesel的连接管理器:

use diesel::pg::PgConnection;
use diesel::r2d2::{ConnectionManager, Pool};
use postgres_rustls::MakeRustlsConnect;
use rustls::RootCertStore;
use rustls_native_certs::load;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 加载系统根CA并构建TLS配置,步骤和之前一致
    let system_certs = load()?;
    let mut root_store = RootCertStore::empty();
    for cert in system_certs {
        root_store.add(&rustls::Certificate(cert.0))?;
    }

    let tls_config = rustls::ClientConfig::builder()
        .with_safe_defaults()
        .with_root_certificates(root_store)
        .with_no_client_auth();

    let tls_connector = MakeRustlsConnect::new(tls_config);

    // 用`new_with_tls`方法创建带TLS的Diesel连接管理器
    let db_url = "postgres://your-db-user:your-db-password@your-db-host:5432/your-db-name";
    let manager = ConnectionManager::<PgConnection>::new_with_tls(db_url, tls_connector);

    // 创建连接池(Diesel常用连接池模式)
    let pool = Pool::builder().build(manager)?;

    // 从连接池获取连接并测试
    let conn = pool.get()?;
    let version: String = diesel::sql_query("SELECT version()")
        .get_result(&conn)?;
    println!("Connected to PostgreSQL via Diesel: {}", version);

    Ok(())
}

四、双向TLS(客户端证书认证)

如果PostgreSQL服务器要求客户端提供证书,用win-cert-store读取Windows证书存储中的客户端证书:

先添加依赖:

win-cert-store = "0.3"

修改TLS配置部分:

use win_cert_store::Certificate;

// ... 前面加载根CA的代码不变 ...

// 从Windows证书存储加载客户端证书(按主题名称查找,也可用指纹)
let client_cert = Certificate::find()
    .subject_name("Your Client Certificate Subject")
    .find_one()?;

// 提取证书DER编码和私钥
let cert_der = client_cert.encoded()?;
let private_key = client_cert.private_key()?;

// 转换为rustls兼容格式
let rustls_cert = rustls::Certificate(cert_der);
let rustls_key = rustls::PrivateKey(private_key);

// 构建带客户端证书的TLS配置
let tls_config = rustls::ClientConfig::builder()
    .with_safe_defaults()
    .with_root_certificates(root_store)
    .with_client_auth_cert(vec![rustls_cert], rustls_key)?;

注意事项

  • 确保PostgreSQL服务器已开启TLS:检查postgresql.conf中的ssl = on,并配置ssl_cert_file和ssl_key_file
  • rustls-native-certs自动读取Windows"受信任的根证书颁发机构"存储区,无需手动指定CA文件
  • 客户端证书需放在Windows"个人"证书存储区,且当前程序有权限读取(通常需管理员权限或证书设置为可导出)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:34:58