- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
好的,这是我需要做的:
我的应用程序是用 C# (.NET Framework 4.5) 编写的,需要通过 HTTPS 与我们的服务器通信。我们的服务器使用我们自己的 Root-CA 颁发的 TLS/SSL 证书。该 Root-CA 虽然完全受我的应用程序信任,但未安装在系统的“受信任的根”证书库中。因此,如果没有进一步的工作,C# 将拒绝联系服务器,因为无法验证服务器的证书 - 正如预期的那样。注意:我们不能使用系统中已经安装的 Root-CA。
我该怎么做才能让我的应用程序(安全地)联系我们的服务器?我知道 C# 提供了将我们的 Root-CA 证书作为“受信任的根”安装到系统证书库中的类。这不是我们想要做的!那是因为 (a) 它向用户显示了一个令人震惊的(并且技术性太强的)警告,并且因为 (b) 它也会影响其他应用程序 - 我们不会这样做不想也不需要。
所以我需要的是告诉 C#/.NET 使用“自定义”(即 特定于应用程序)的证书集 - 而不是系统范围的证书存储 - 来验证服务器证书链。整个证书链仍然需要正确验证(包括吊销列表!)。只有我们的根 CA 需要被接受为我的应用程序的“可信”根。
执行此操作的最佳方法是什么?
任何帮助将不胜感激。提前致谢!
顺便说一句:我发现我可以使用 ServicePointManager.ServerCertificateValidationCallback
来安装我自己的证书验证功能。这确实有效。但这种方法并不好,因为现在我需要在我自己的代码中手动整个证书验证。但是,我不想要重新实现整个证书验证过程(例如下载和检查 CRL 等),该过程已经在 .NET Framework 中实现(和测试)。这就像重新发明轮子,永远无法像已经存在的 .NET 实现那样进行彻底的测试。
最佳答案
RemoteCertificateValidationCallback
委托(delegate)是解决问题的正确方法。但是,我会在委托(delegate)中使用不同于 Olivier 建议的行为。这就是为什么:执行了太多不相关的检查而没有执行相关的检查。
那么,详细看问题:
首先,我们将考虑当您的服务使用从商业 CA 购买的合法证书时的场景(现在可能不是这种情况,但将来可能是这种情况)。这意味着如果 sslPolicyErrors
参数有 None
标志,立即返回 True
,证书有效并且没有明显的理由拒绝它。仅当以下声明不严格时才需要此步骤:
Only our Root-CA needs to be accepted as a "trusted" root for my application.
否则,忽略第一步。
让我们假设,该服务仍然使用来自私有(private)和不受信任的 CA 的证书。在这种情况下,我们必须处理与证书链无关且仅特定于 SSL session 的错误。因此,当调用 RemoteCertificateValidationCallback
委托(delegate)时,我们应确保 RemoteCertificateNameMismatch
和 RemoteCertificateNotAvailable
标志不会出现在 sslPolicyErrors
参数。如果出现其中任何一个,我们将拒绝连接而不进行额外检查。
让我们假设没有出现这些标志。此时我们正确地处理了特定于 SSL 的错误,只有证书链可能有问题。
如果我们做到这一点,我们可以声明 sslPolicyErrors
参数包含 RemoteCertificateChainErrors
标志。这可能意味着一切,我们必须进行额外的检查。您的根 CA 证书是一个常量。这意味着我们可以检查 chain
参数中的根证书并将其与我们的常量(例如根 CA 证书的指纹)进行比较。如果比较失败,我们会立即拒绝该证书,因为它不是您的并且没有明显的理由信任由未知 CA 颁发的证书并且可能存在其他链问题。
如果比较成功,那么我们就到了必须谨慎妥善处理的情况。我们必须执行证书链引擎的另一个实例并指示它收集任何链问题,仅 UntrustedRoot
错误除外。这意味着如果 SSL 证书有其他问题(例如 RevocationOffline、有效性、策略错误),我们将知道并拒绝该证书。
下面的代码是上面许多词的编程实现:
using System;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace MyNamespace {
class MyClass {
Boolean ServerCertificateValidationCallback(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
String rootCAThumbprint = ""; // write your code to get your CA's thumbprint
// remove this line if commercial CAs are not allowed to issue certificate for your service.
if ((sslPolicyErrors & (SslPolicyErrors.None)) > 0) { return true; }
if (
(sslPolicyErrors & (SslPolicyErrors.RemoteCertificateNameMismatch)) > 0 ||
(sslPolicyErrors & (SslPolicyErrors.RemoteCertificateNotAvailable)) > 0
) { return false; }
// get last chain element that should contain root CA certificate
// but this may not be the case in partial chains
X509Certificate2 projectedRootCert = chain.ChainElements[chain.ChainElements.Count - 1].Certificate;
if (projectedRootCert.Thumbprint != rootCAThumbprint) {
return false;
}
// execute certificate chaining engine and ignore only "UntrustedRoot" error
X509Chain customChain = new X509Chain {
ChainPolicy = {
VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority
}
};
Boolean retValue = customChain.Build(chain.ChainElements[0].Certificate);
// RELEASE unmanaged resources behind X509Chain class.
customChain.Reset();
return retValue;
}
}
}
此方法(命名委托(delegate))可以附加到 ServicePointManager.ServerCertificateValidationCallback
。代码可能会被压缩(例如,在一个 IF 语句中组合多个 IF),我使用冗长的版本来反射(reflect)文本逻辑。
关于C#/.NET - 如何在我的应用程序中允许 HTTPS 的 "custom"Root-CA(仅)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33627593/
我在大学学习C++时学习了这段代码..后来我在C#中使用了同样的东西...但现在我想在Java中使用它...我在互联网上寻找类似的东西,但我什至不知道如何表达它,以便我得到正确的结果。 所以嗯,请让我
我正在我的 Ruby on Rails Controller 上运行 RSPEC 测试,这是我正在测试的 Controller 操作: Controller 代码: class Customers::
想为我选择的选项卡设置自定义背景,到目前为止,子类化是我自定义 UITAbBar/UITabBarItem 的方式。 问题是:有谁知道(或知道我在哪里可以找到)设置背景的属性是什么? 所选选项卡周围有
您好,我在 commerefacades-beans.xml 中创建了 eProductForm bean,我添加了 ProductData 的自定义属性。 然后在commercewebs
我有两个表:1. 客户2. customer_order 客户表包含客户数据(duh),customer_order 包含所有订单。我可以在 customer.id=customer_order.id
在我的 TableView 中,我有一个 NSMutableArray *currList 的数据源 - 它包含对象 Agent 的对象。我创建了自定义的 TableCell 并正确设置了所有内容。我
是否建议使用自引用泛型继承? public abstract class Entity { public Guid Id {get; set;} public int Version
我正在尝试为我的 Grafana 安装使用自定义文件 ( custom.ini )。不幸的是,这不起作用。 我做了什么: 安装了一台装有 CentOS 7 的虚拟机 添加了 Grafana Yum R
我被分配了两个给定类的作业,一个是抽象父类 Lot.java,另一个是测试类 TestLots.java。我不应该编辑其中任何一个。任务是创建Lot的两个子类,使TestLots中的错误不再是错误。
我是 Botpress 的新手。 我刚刚安装了 Botpress 的最新版本“botpress-ce-v11_0_1-win-x64”。 我浏览了文档,发现了一些关于内容类型、内容元素和内容渲染的解释
我一直在四处寻找,但我还没有找到任何东西,除了 Qt3 的旧文档和 qt 设计器的 3.x 版。 我会举个例子,并不是因为我的项目是 GPL 而不能提供代码,而是为了简单起见。 示例:您正在为您的应用
场景 我有一个自定义规则来验证订单的运费: public class OrderValidator : BaseValidator { private string CustomInfo {
我有用于身份验证的自定义拦截器: @Named("authInterceptor") @Provides @Singleton fun providesAuthIntercep
如果有人没有添加照片,我想显示默认头像图像。我假设我需要在模型或助手中执行自定义 getter。 如果我做 getter,它会看起来像这样吗: def avatar_url "default_ur
我正在使用 Google Search API,但遇到了一些麻烦。这个请求(在 Python 中,使用 requests 库)工作正常 res = requests.get("https://www.
我使用 MSKLC 制作了自定义键盘布局。 我以为我仔细按照说明操作了chose appropriate values对于LOCALENAME和 LOCALID参数。 但是,在通过按 Win+Spac
我正在使用 simpleframework解析 XML 字符串并将其转换为对象。 Serializer serializer = new Persister(); try { Customer
我正在使用 C# 控制台应用程序从 MySql 数据库获取一些数据,但在正确查询时遇到一些问题 现在的情况: SELECT * FROM Customer WHERE EXISTS ( SELECT
我在我的 iPhone 4S 上运行我的应用程序,我正在使用自定义表格 View Controller 和自定义表格 View 单元格,当我将表格 View 向上滑动到空白区域并同样向下滑动到空白区域
我有一个自定义的 JavaScript 变量,它正在检查 eventAction 是什么,这样我就可以知道是否触发一些转换像素。自定义 Javascript 称为“FacebookConversion
我是一名优秀的程序员,十分优秀!