如何将SSL添加到使用httplistener的.net应用程序-它不会在IIS上运行
最新编辑以粗体显示
我正在使用.netHttpListener
类,但是不会在IIS上运行,也不在使用ASP.net。该网站描述了使用asp.net实施SSL实际使用的代码,并且该网站描述了如何设置证书(尽管我不确定它是否仅适用于IIS)。
类文档描述了各种身份验证类型(基本身份验证,摘要身份验证,Windows身份验证等),其中没有一个涉及SSL。它确实说如果使用HTTPS,则需要设置服务器证书。这将是一个单行属性设置,而HttpListener
会找出其余的属性吗?
简而言之,我需要知道如何设置证书以及如何修改代码以实现SSL。
尽管在尝试访问HTTPS时没有发生此错误,但是我的确在系统事件日志中发现了一个错误,该错误的来源是" Schannel",消息的内容是:
A fatal error occurred when attempting to access the SSL server credential private key. The error code returned from the cryptographic module is 0x80090016.
编辑:
到目前为止已采取的步骤
- 在C#中创建了可用于HTTP连接的有效HTTPListener(例如" http:// localhost:8089 / foldername /"
- 使用makecert.exe创建了一个证书
- 使用certmgr.exe添加了受信任的证书
- 使用Httpcfg.exe侦听测试端口上的SSL连接(例如8090)
- 通过侦听器将端口8080添加到HTTPListener。Prefixes.Add(https:// localhost:8090 / foldername /");
- 测试了HTTP客户端连接,例如(http:// localhost:8089 / foldername /")在浏览器中并收到正确的返回
- 测试了HTTPS客户端连接,例如(http:// localhost:8090 / foldername /")在浏览器中并收到"数据传输中断"(在Firefox中)
- 在Visual Studio中进行调试表明,HTTPS连接启动时,接收到请求的侦听器回调永远不会被击中-我看不到可以设置断点以更早捕获其他任何内容的地方。
- netstat显示HTTPS和HTTP的侦听端口均已打开。尝试连接后,HTTPS端口确实转到TIME_WAIT。
- Fiddler和HTTPAnalyzer不会捕获任何流量,我想它在此过程中还不足以显示在那些HTTP分析工具中
问题
- 可能是什么问题?
- 我是否缺少一部分.Net代码(这意味着我必须在C#中做更多的工作,而不仅仅是在侦听器中添加指向HTTPS的前缀,这就是我所做的)
- 在某处错过了配置步骤吗?
- 我还可以做些什么来分析问题?
- 系统事件日志中的错误消息是问题的征兆吗?如果是这样,如何解决?
解决方案
回答
我还没有完全实现它,但是该网站似乎为设置证书和代码提供了很好的演练。
回答
类文档
有这个注意事项:
If you create an HttpListener using https, you must select a Server Certificate for that listener. Otherwise, an HttpWebRequest query of this HttpListener will fail with an unexpected close of the connection.
还有这个:
You can configure Server Certificates and other listener options by using HttpCfg.exe. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/http/http/httpcfg_exe.asp for more details. The executable is shipped with Windows Server 2003, or can be built from source code available in the Platform SDK.
第一个音符由第二个音符解释吗?如问题所述,我使用httpcfg.exe将证书绑定到特定端口。如果他们打算除此以外的其他用途,则说明不明确。
回答
我遇到了与我们相同的问题。幸运的是,在搜索了本页上的所有困难步骤之后,使SSL与我的HttpListener一起使用。
回答
我有一个类似的问题,看来证书本身可能有问题。
这是对我有用的路径:
makecert.exe -r -a sha1 -n CN=localhost -sky exchange -pe -b 01/01/2000 -e 01/01/2050 -ss my -sr localmachine
然后查找证书指纹,将其复制到剪贴板并删除空格。在下一个命令中,该参数将是-h之后的参数:
HttpCfg.exe set ssl -i 0.0.0.0:801 -h 35c65fd4853f49552471d2226e03dd10b7a11755
然后在https:// localhost:801 /上运行服务主机,即可正常运行。
我无法进行的工作是让https在自行生成的证书上运行。这是我运行生成的代码(为清楚起见,删除了错误处理):
LPCTSTR pszX500 = subject; DWORD cbEncoded = 0; CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL); pbEncoded = (BYTE *)malloc(cbEncoded); CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL); // Prepare certificate Subject for self-signed certificate CERT_NAME_BLOB SubjectIssuerBlob; memset(&SubjectIssuerBlob, 0, sizeof(SubjectIssuerBlob)); SubjectIssuerBlob.cbData = cbEncoded; SubjectIssuerBlob.pbData = pbEncoded; // Prepare key provider structure for self-signed certificate CRYPT_KEY_PROV_INFO KeyProvInfo; memset(&KeyProvInfo, 0, sizeof(KeyProvInfo)); KeyProvInfo.pwszContainerName = _T("my-container"); KeyProvInfo.pwszProvName = NULL; KeyProvInfo.dwProvType = PROV_RSA_FULL; KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET; KeyProvInfo.cProvParam = 0; KeyProvInfo.rgProvParam = NULL; KeyProvInfo.dwKeySpec = AT_SIGNATURE; // Prepare algorithm structure for self-signed certificate CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm)); SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA; // Prepare Expiration date for self-signed certificate SYSTEMTIME EndTime; GetSystemTime(&EndTime); EndTime.wYear += 5; // Create self-signed certificate pCertContext = CertCreateSelfSignCertificate(NULL, &SubjectIssuerBlob, 0, &KeyProvInfo, &SignatureAlgorithm, 0, &EndTime, 0); hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"MY"); CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, 0);
证书显示正常,并且具有有效的私钥,但是https会超时,就像从未注册指纹一样。如果有人知道为什么请PLZ发表评论
EDIT1:经过一番摸索,我发现CertCreateSelfSignCertificate的初始化会生成正确的证书:
CRYPT_KEY_PROV_INFO KeyProvInfo; memset(&KeyProvInfo, 0, sizeof(KeyProvInfo)); KeyProvInfo.pwszContainerName = _T("my-container"); KeyProvInfo.pwszProvName = _T("Microsoft RSA SChannel Cryptographic Provider"); KeyProvInfo.dwProvType = PROV_RSA_SCHANNEL; KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET; KeyProvInfo.cProvParam = 0; KeyProvInfo.rgProvParam = NULL; KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;