大家好,我是Edison。

最近,在使用CAP事件总线时,碰到了这样一个需求:微服务采用的是MongoDB,而且还是带身份验证 和 SSL根证书验证的。由于目前网上能找到的资料,都是不带身份验证的MongoDB,现在网络信息安全越来越被重视,那么就需要自己研究一番了。

CAP.MongoDB组件

CAP是一个开源的事件总线项目,在.NET社区已经十分流行了,它提供了多种存储方式:MSSQL, MySQL, PgSQL,MongoDB等,这里我们主要关注MongoDB。快速安装CAP.MongoDB组件:

PM> Install-Package DotNetCore.CAP.MongoDB

快速集成CAP.MongoDB组件(StartUp.cs):

​public void ConfigureServices(IServiceCollection services)
{
// ...

services.AddCap(x =>
{
x.UseMongoDB(opt=>{
//MongoDBOptions
});
// x.UseXXX ...
});
}

目前CAP提供的Options如下:

也就是说,CAP的Option只提供了一个DatabaseConnection选项,让我们自己构造Mongo链接字符串供CAP使用。

那么,我们就需要准确地构造这个Mongo连接字符串了。

这里,我们以之前分享的一篇文章《在ASP.NET 6中使用工作单元操作MongoDB》为基础,不熟悉的朋友可以先看看这篇文章。

前提条件/准备工作

这里我们假设在appsettings中我们针对MongoDB的配置项如下格式:

"MongoDatabaseConfigs": {
"Servers": "xxx01.server.net,xxx02.server.net,xxx03.server.net",
"Port": 27017, // optional, default : 27017
"ReplicaSetName": "myrs",
"DatabaseName": "TEST_DB",
"AuthDatabaseName": "admin", // optional, default: admin
"ApplicationName": "Todo",
"UserName": "test_dev_user",
"Password": "test_dev_password",
"UseTLS": true, // optional, default : false
"AllowInsecureTLS": true, // optional, default : true
"SslCertificatePath": "/etc/pki/tls/certs/MyCustomCA.cer"
}

配置项中给出了UserName、Password 还有 SSL证书的路径,这些都是需要构造到连接字符串中的。当然,在Kubernetes中,都建议放到Secret中去。

核心工作:封装构造连接字符串的方法

这里我们封装一个生成MongoDB连接字符串的静态方法,用于读取appsettings中的配置项,并帮我们生成CAP可以用的MongoDB连接字符串:

public static class DbConnUtil
{
// Const Settings for Mongo
private const int DEFAULT_CONNECT_TIMEOUT_MS = 10000; // 10s
private const int DEFAULT_SERVER_SELECTION_TIMEOUT_MS = 5000; // 5s
private const string DEFAULT_AUTH_MECHANISM = "SCRAM-SHA-256"; // SCRAM-SHA-256
private const string DEFAULT_READ_PREFERENCE = "primaryPreferred"; // Primary Preferred
private const string DEFAULT_SSL_INVALID_HOSTNAME_ALLOWED = "true"; // Allow Invalid HostName for SSL /// <summary>
/// 获取MongoDB数据库连接字符串
/// 需要在配置文件中提前根据指定Key进行设置
/// </summary>
public static string GetMongoDbConnectionString(IConfiguration config)
{
var servers = config["MongoDatabaseConfigs:Servers"];
var port = config["MongoDatabaseConfigs:Port"] ?? "27017";
if (string.IsNullOrWhiteSpace(servers))
throw new ArgumentNullException("Mongo Servers Configuration is Missing!");
var mongoServers = servers.Split(','); // Basic Auth
var userName = config["MongoDatabaseConfigs:UserName"];
var password = config["MongoDatabaseConfigs:Password"];
if (string.IsNullOrWhiteSpace(userName) || string.IsNullOrWhiteSpace(password))
throw new ArgumentNullException("Mongo Account Configuration is Missing!"); // Uri
var replicaName = config["MongoDatabaseConfigs:ReplicaSetName"];
var authDatabaseName = config["MongoDatabaseConfigs:AuthDatabaseName"] ?? "admin";
var mongoUriBuilder = new StringBuilder();
mongoUriBuilder.Append($"mongodb://{userName}:{password}@");
for (int i = 0; i < mongoServers.Length; i++)
{
if (i < mongoServers.Length - 1)
{
mongoUriBuilder.Append($"{mongoServers[i]}:{port},");
}
else
{
mongoUriBuilder.Append($"{mongoServers[i]}:{port}/?");
}
} // Settings
var applicationName = config["MongoDatabaseConfigs:ApplicationName"];
mongoUriBuilder.Append($"replicaSet={replicaName}");
mongoUriBuilder.Append($"&appName={applicationName}");
mongoUriBuilder.Append($"&authSource={authDatabaseName}");
mongoUriBuilder.Append($"&authMechanism={DEFAULT_AUTH_MECHANISM}");
mongoUriBuilder.Append($"&connectTimeoutMS={DEFAULT_CONNECT_TIMEOUT_MS}");
mongoUriBuilder.Append($"&serverSelectionTimeoutMS={DEFAULT_SERVER_SELECTION_TIMEOUT_MS}");
mongoUriBuilder.Append($"&readPreference={DEFAULT_READ_PREFERENCE}"); // TLS/SSL Auth
var useTLS = Convert.ToBoolean(config["MongoDatabaseConfigs:UseTLS"] ?? "false");
if (useTLS)
{
var allowInsecureTls = Convert.ToBoolean(config["MongoDatabaseConfigs:AllowInsecureTLS"] ?? "true");
var sslCertificatePath = config["MongoDatabaseConfigs:SslCertificatePath"]; mongoUriBuilder.Append($"&ssl={useTLS}");
mongoUriBuilder.Append($"&net.ssl.CAFile={sslCertificatePath}");
mongoUriBuilder.Append($"&net.ssl.allowInvalidCertificates={DEFAULT_SSL_INVALID_HOSTNAME_ALLOWED}");
} return mongoUriBuilder.ToString();
}
}

最终可以生成的连接字符串为:

mongodb://test_dev_user:test_dev_password@xxx01:27017.server.net,xxx02.server.net:27017,xxx03.server.net:27017/?replicaSet=myrs&appName=Todo&authSource=admin&authMechanism=SCRAM-SHA-256&connectTimeoutMS=10000&serverSelectionTimeoutMS=5000&readPreference=primaryPreferred&ssl=True&net.ssl.CAFile=/etc/pki/tls/certs/MyCustomCA.cer&net.ssl.allowInvalidCertificates=true

ASP.NET Core集成CAP

这里我们使用刚刚封装的方法来生成Mongo连接字符串,来快速集成CAP:

public static IServiceCollection AddApplicationEventBus(this IServiceCollection services, IConfiguration config)
{
......
// CAP EventBus
services.AddCap(option =>
{
// Transport
option.UseKafka(option =>
{
option.Servers = config["EventBusConfigs:KafkaServers"]
?? throw new ArgumentException("EventBusConfigs:KafkaServers must be set!");
option.ConnectionPoolSize = int.Parse(config["EventBusConfigs:CapConnectionPoolSize"]
?? ApplicationDefaultSettings.Default_ConnectionPool_Size);
option.CustomHeaders = e => new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>(Headers.MessageId, SnowflakeId.Default().NextId().ToString()),
new KeyValuePair<string, string>(Headers.MessageName, e.Topic)
}; if (Convert.ToBoolean(config["EventBusConfigs:EnableAuthorization"] ?? "false"))
{
var userName = config["EventBusConfigs:SaslUserName"];
var passWord = config["EventBusConfigs:SaslPassword"]; if (string.IsNullOrWhiteSpace(userName) || string.IsNullOrWhiteSpace(passWord))
throw new ArgumentNullException("Kafka username or password can't be null!"); option.MainConfig.Add(KafkaMainConfigKey.SECURITY_PROTOCOL, KafkaProtocol.SASL_SSL);
option.MainConfig.Add(KafkaMainConfigKey.SASL_MECHANISM, KafkaAuthMechanism.PLAIN);
option.MainConfig.Add(KafkaMainConfigKey.SASL_USERNAME, userName);
option.MainConfig.Add(KafkaMainConfigKey.SASL_PASSWORD, passWord); if (!string.IsNullOrWhiteSpace(config["EventBusConfigs:SslCertificatePath"]))
option.MainConfig.Add(KafkaMainConfigKey.SSL_CA_LOCATION, config["EventBusConfigs:SslCertificatePath"]);
if (!string.IsNullOrWhiteSpace(config["EventBusConfigs:EnableSslCertificateVerification"]))
option.MainConfig.Add(KafkaMainConfigKey.ENABLE_SSL_CERT_VERIFICATION, config["EventBusConfigs:EnableSslCertificateVerification"]);
}
});
option.SucceedMessageExpiredAfter = 3600 * 24 * int.Parse(config["EventBusConfigs:CapSuccessMsgExpireDays"];
// Storage
option.UseMongoDB(option =>
{
option.DatabaseConnection = DbConnUtil.GetMongoDbConnectionString(config);
option.DatabaseName = config["MongoDatabaseConfigs:DatabaseName"]
?? throw new ArgumentException("MongoDatabaseConfigs:DatabaseName must be set!");
option.PublishedCollection = "msg.published";
option.ReceivedCollection = "msg.received";
});
}); ...... return services;
}

小结

本文我们了解了如何在CAP中集成带基础身份验证(用户名/密码)+SSL根证书验证的MongoDB,方便CAP能够正常连接MongoDB并生成本地消息表,在网络信息安全越来越重视的现在,相信会对你使用CAP+MongoDB有一定帮助!

参考资料

CAP官方文档:https://cap.dotnetcore.xyz/user-guide/en/storage/mongodb/
MongoDB官方文档:https://www.mongodb.com/docs/v5.0/security/

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

CAP项目集成带身份和证书验证的MongoDB的更多相关文章

  1. 无法在web服务器上启动调试。调试失败,因为没有启用集成windows身份验证

    ----注意:以管理员身份运行VS C#中ASP.NET Web应用程序编译时的错误:无法在web服务器上启动调试.调试失败,因为没有启用集成windows身份验证. 解决:打开IIS,在IIS里查看 ...

  2. Spring Cloud系列-Zuul网关集成JWT身份验证

    前言 这两三年项目中一直在使用比较流行的spring cloud框架,也算有一定积累,打算有时间就整理一些干货与大家分享. 本次分享zuul网关集成jwt身份验证 业务背景 项目开发少不了身份认证,j ...

  3. HttpHelpers类普通GET和POST方式,带Cookie和带证书验证模式

    HttpHelpers类普通GET和POST方式,带Cookie和带证书验证模式 参考路径:https://www.cnblogs.com/splendidme/archive/2011/09/14/ ...

  4. Android证书验证存漏洞 开发者身份信息可被篡改(转)

    原帖地址:http://bbs.pediy.com/showthread.php?p=1335278#post1335278 近期在国内网易,雷锋网等网站爆出谷歌市场上的索尼官方的备份与恢复应用&qu ...

  5. 微信支付HTTPS服务器证书验证指引

    1. 背景介绍 2. 常见问题 3. 验证证书 4. 安装证书 背景介绍 微信支付使用HTTPS来保证通信安全, 在HTTPS服务器上部署了由权威机构签发的证书, 用于证明微信支付平台的真实身份. 商 ...

  6. iOS-Cordova集成开发,已有项目集成cordova

    iOS-Cordova集成开发,已有项目集成cordova 项目组准备开发一个APP,要求Android和iOS端页面完全一致,除了一个页面跟业务相关的不同,其他界面基本一致,因此,萌生一个想法,关于 ...

  7. iOS 绕过https证书验证 请求数据

    HTTPS和HTTP: 1.https协议需要到ca申请证书,一般免费证书很少,需要交费. 2.http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议. 3.http ...

  8. Taurus.MVC 微服务框架 入门开发教程:项目集成:4、默认安全认证与自定义安全认证。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...

  9. 重温WCF之WCF传输安全(十三)(4)基于SSL的WCF对客户端采用证书验证(转)

    转载地址:http://www.cnblogs.com/lxblog/archive/2012/09/20/2695397.html 前一篇我们演示了基于SSL的WCF 对客户端进行用户名和密码方式的 ...

  10. 【腾讯Bugly干货分享】iOS 中 HTTPS 证书验证浅析

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/-fLLTtip509K6pNOTkflPQ 导语 本 ...

随机推荐

  1. Volo.Abp升级小记(二)创建全新微服务模块

    @ 目录 创建模块 领域层 应用层 数据库和仓储 控制器 配置微服务 测试微服务 微服务注册 添加资源配置 配置网关 运行项目 假设有一个按照官方sample搭建的微服务项目,并安装好了abp-cli ...

  2. 聊聊Zookeeper的Session会话超时重连

    概述 简单地说,ZooKeeper的连接与会话就是客户端通过实例化ZooKeeper对象来实现客户端与服务器创建并保持TCP连接的过程.本质上,Session就是一个TCP 长连接. 会话 Sessi ...

  3. 1. Mybatis 简介

    1. Mybatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code.随着 ...

  4. 基于生成式预训练Transformer的跨语言文本摘要与情感分析

    目录 1. 引言 2. 技术原理及概念 2.1 基本概念解释 2.2 技术原理介绍 2.3 相关技术比较 3. 实现步骤与流程 3.1 准备工作:环境配置与依赖安装 3.2 核心模块实现 3.3 集成 ...

  5. 如何使用libavcodec将.h264码流文件解码为.yuv图像序列?

    一.打开和关闭输入文件和输出文件 //io_data.cpp static FILE* input_file= nullptr; static FILE* output_file= nullptr; ...

  6. influxdb常用sql总结

    本文为博主原创,转载请注明出处: 1.登录influxdb influx -username admin -password "password" 2.查看数据库 ##查看有哪些数 ...

  7. 【Mybatis】学习

    Mybatis 学习 环境搭建 pom.xml <!--log4j--> <dependency> <groupId>org.slf4j</groupId&g ...

  8. 消灭非稳态噪音的利器 - AI 降噪

    摘要:轻量级神经网络降噪方法,解析 ZegoAIDenoise 的算法实现! 文|即构引擎开发团队 一.轻量级神经网络降噪--ZegoAIDenoise 当下,用户在进行音频通话时常常置身于各种不同的 ...

  9. Python单元测试之道:从入门到精通的全面指南

    在这篇文章中,我们会深入探讨Python单元测试的各个方面,包括它的基本概念.基础知识.实践方法.高级话题,如何在实际项目中进行单元测试,单元测试的最佳实践,以及一些有用的工具和资源 一.单元测试重要 ...

  10. Java 中怎样将 bytes 转换为 long 类型?

    将bytes 转换为long类型: 第一种方式: String 接收 bytes 的构造器转成 String,再 Long.parseLong: 但此种情况需要注意:字节数组中的每个字节都必须是有效的 ...