使用Rust的async_nats连接NATS时遇MissingOrMalformedExtensions错误
解决async_nats连接NATS服务器时的证书读取错误
问题场景
使用Rust的async_nats crate连接本地NATS服务器,代码如下:
use futures::StreamExt; #[tokio::main] async fn main() -> Result<(), async_nats::Error> { let client = async_nats::connect("nats://127.0.0.1:4222").await?; // let client = async_nats::connect("127.0.0.1:4222").await?; // let client = async_nats::connect("127.0.0.1").await?; let mut subscriber = client.subscribe("messages".into()).await?.take(10); for _ in 0..10 { client.publish("messages".into(), "data".into()).await?; } while let Some(message) = subscriber.next().await { println!("Received message {:?}", message); } Ok(()) }
运行时触发panic,错误信息:
Error: Custom { kind: Other, error: "failed to read root certificates: MissingOrMalformedExtensions" } error: process didn't exit successfully: `target\debug\program.exe` (exit code: 1)
解决方案
这个错误的核心原因是客户端尝试读取系统根证书以建立TLS连接,但读取失败,或者本地NATS服务器未配置TLS但客户端自动启用了TLS验证。
1. 显式禁用TLS连接(推荐本地开发使用)
使用ClientOptions创建客户端,明确不启用TLS,避免自动触发证书验证逻辑:
use futures::StreamExt; use async_nats::ClientOptions; #[tokio::main] async fn main() -> Result<(), async_nats::Error> { // 显式配置无TLS的客户端 let client = ClientOptions::new() .connect("127.0.0.1:4222") .await?; let mut subscriber = client.subscribe("messages".into()).await?.take(10); for _ in 0..10 { client.publish("messages".into(), "data".into()).await?; } while let Some(message) = subscriber.next().await { println!("Received message {:?}", message); } Ok(()) }
2. 手动指定CA证书(若服务器启用了TLS)
如果你的NATS服务器确实配置了TLS,需要手动指定CA证书路径来修复证书读取问题:
use futures::StreamExt; use async_nats::ClientOptions; use rustls_pemfile::certs; use std::fs::File; use std::io::BufReader; #[tokio::main] async fn main() -> Result<(), async_nats::Error> { // 读取自定义CA证书文件 let cert_file = File::open("path/to/your/ca.crt")?; let mut reader = BufReader::new(cert_file); let certs = certs(&mut reader)? .into_iter() .map(|cert| rustls::Certificate(cert)) .collect(); // 构建自定义TLS配置 let tls_config = rustls::ClientConfig::builder() .with_safe_defaults() .with_root_certificates(certs) .with_no_client_auth(); let client = ClientOptions::new() .tls(tls_config.into()) .connect("tls://127.0.0.1:4222") .await?; let mut subscriber = client.subscribe("messages".into()).await?.take(10); for _ in 0..10 { client.publish("messages".into(), "data".into()).await?; } while let Some(message) = subscriber.next().await { println!("Received message {:?}", message); } Ok(()) }
内容的提问来源于stack exchange,提问作者Yoskutik
相关产品推荐
相关产品推荐

