WCF,证书身份验证 - 常见错误和令人困惑的参数
我正在尝试设置 WCF 服务以使用证书对客户端进行身份验证。我已经阅读了大量有关如何创建证书的帖子,并且我(终于)能够做到这一点。
我正在运行 Windows 2008 R2 的服务器上安装证书颁发机构和证书。当我打开 MMC 证书管理单元时,我选择计算机帐户。这是正确的吗?我这样做是因为我的 WCF 服务将在 Windows 服务中运行,即使没有用户登录也会运行。但不可否认的是,我不知道这三个选项之间有什么区别:
- 我的用户帐户
- 服务帐户
- 计算机 。
加载管理单元后,我将权威证书导入到受信任的根证书颁发机构中 然后,我将证书导入到受信任的发布者中。这样做时我没有遇到任何错误。当我导入权威证书和该权威机构签署的证书时,我不会引用 .pvk 文件。据我了解,私钥嵌入在证书或权威证书中。以下是我用来创建每个证书的命令:
MakeCert.exe
-n “CN=InternalCA”
-r
-sv InternalCA.pvk InternalCA.cer
-cy authority
MakeCert.exe
-sk InternalWebService
-iv InternalCA.pvk
-n “CN=InternalWebService”
-ic InternalCA.cer InternalWebService.cer
-sr localmachine
-ss root
-sky exchange
-pe
请注意,我使用了 -ss root。我见过很多使用 -ss My 的帖子。我真的不明白有什么区别或者什么时候适合使用每个值。
我的 WCF 服务在这台计算机上的托管服务(Windows 服务)内运行。当我启动托管 WCF 服务的 Windows 服务时,它立即崩溃,并且事件查看器中报告了一个看似常见的错误:
System.ArgumentException:很可能 该证书“CN=TempCertName”可能 没有可用的私钥 密钥交换或过程可能不会 拥有私钥的访问权限
我发现帖子说我需要向运行该密钥的服务的用户授予权限。
这似乎是 stackoverflow 上的一个流行答案:授予所有任务/管理私钥的访问权限
但我没有所有任务/管理私钥的选项
,但我不清楚如何这样做。而且,该服务在我的域帐户下运行,该帐户是管理员,也是安装证书的同一用户。
请帮忙:)
I am trying to setup a WCF service to use a Certificate for Authenticating the client. I have read tons of posts on how to create the certificate, and I have been able to do so (finally).
I am installing the Cert Authority and the Cert on a server that runs Windows 2008 R2. When I open the MMC Certificates Snap-in, I choose Computer Account. Is this correct? I am doing this because my WCF service will run in a Windows Service, and will be running even when no user's are logged in. But admittedly, I don't know what the difference is between the three options:
- My user account
- Service account
- Computer account
Once the snap-in loads, I import the Authority Cert into Trusted Root Certification Authorities. Then, I import the cert into Trusted Publishers. I don't encounter any errors when doing this. When I do the import, of both the Authority Cert and the Cert signed by that authority, I don't make any reference to the .pvk file. It is my understanding that the private key is embedded in either the cert or the authority cert. Here are the commands I use to create each cert:
MakeCert.exe
-n “CN=InternalCA”
-r
-sv InternalCA.pvk InternalCA.cer
-cy authority
MakeCert.exe
-sk InternalWebService
-iv InternalCA.pvk
-n “CN=InternalWebService”
-ic InternalCA.cer InternalWebService.cer
-sr localmachine
-ss root
-sky exchange
-pe
Notice I used -ss root. I have seen many posts using -ss My. I don't really understand what the difference is or when it is appropriate to use each value.
My WCF service runs on this machine inside a Managed Service (Windows Service). When I start my windows service, which hosts the WCF service, it crashes immediately and a seemingly common error is reported in the event viewer:
System.ArgumentException: It is likely
that certificate 'CN=TempCertName' may
not have a private key that is capable
of key exchange or the process may not
have access rights for the private key
I have found posts that say I need to grant permissions to the user running the service to the key.
This one seems to be a popular answer here on stackoverflow: Grant access with All Tasks/Manage Private Keys
But I don't have the option of All Tasks/Manage Private Keys
But I'm not clear on how to do that. But also, the service is running under my domain account, which is an administrator and is also the same user that installed the cert.
Please Help :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
以下是最佳链接,可帮助您让自托管 SSL WCF 服务与您自己的自定义 CA/证书配合使用:SSL 与自托管 WCF 服务。
按照上面的指南使其正常工作后,您可能需要设置您的服务 在安装期间以编程方式使用正确的证书。
我发现使用 HTTPCfgUI 工具验证我的 HTTP.SYS 配置比通过命令更容易行
httpcfg
/netsh
命令。接下来,如果仍然遇到错误,可以使用 WCF 跟踪。此外,您还应该打开 WCF 消息跟踪。如果 WCF 跟踪,您也可以跟踪 .NET 网络堆栈没有提供足够的信息。
您可以通过在另一台计算机上的浏览器中单击您的服务 URL 来测试该服务上的证书/CA 对是否正常工作。首先应声明该证书无效。然后,将机器上的CA导入受信任的根目录,并再次点击服务URL。这次它应该像往常一样显示服务描述页面,没有警告。
Here's the best link that should help you get your self-hosted SSL WCF service to work with your own custom CA/certificates: SSL with Self-hosted WCF Service.
After you get it working from the guide above, you may want setup your service programatically to use the right certificate during installation-time.
I find that verifying my HTTP.SYS configuration with the HTTPCfgUI tool to be easier than via the command line
httpcfg
/netsh
commands.Next, if you still encounter errors, you can debug further using WCF Tracing. Additionally, you should turn on WCF Message Tracing as well. You can trace the .NET network stack too, if the WCF tracing doesn't provide enough information.
You can test if your certificate/CA pair on the service is working by hitting your service URL in a browser on another machine. It should first state that the certificate is invalid. Then, import the CA on the machine into the trusted root, and hit the service URL again. This time it should display the service description page as usual, with no warnings.
我认为你很接近。以下是一些建议:
确保您在第二步中获得附加到证书的私钥。您必须在提升的进程中运行该命令 - 即使您具有管理员权限,您也必须右键单击并“以管理员身份运行”来启动用于此命令的命令 shell。否则,您将无法将私钥存入 localMachine 存储区。
我将使用
-ss my
并将证书(带有私钥)放入个人存储中。 在这里我看到这个:cc.ClientCredentials.ClientCertificate.SetCertificate(
商店位置.当前用户,
商店名称.My,
X509FindType.FindBySubjectName,
"contoso.com");
因此,无论您在同等内容中指向何处,请将证书放在那里。
您不需要导入 CA 证书(您创建的第一个证书)的私钥。保留这些只是为了使用 MakeCert 签署更多证书。您在连接的客户端上需要该 CA 证书的副本(没有私钥!),否则客户端将无法验证 InternalWebService 证书。
您实际上并不需要服务器计算机本地的 CA 证书,因为只有客户端需要它。但这并没有什么坏处,如果服务器上有任何东西连接到本地服务,那么它就会被需要。此外,它还使 InternalWebService 证书在 MMC 管理单元上看起来不错。您可以在受信任的根存储中尝试使用或不使用 CA,您就会明白我的意思。但无论如何,我不会将 CA 的私钥放入本地计算机存储中。
从 MMC 管理单元检查 InternalWebService 的私钥权限(右键单击证书,然后单击任务、管理私钥...)如果您在与服务运行时不同的用户帐户下导入,那么当然它还没有访问权限,您必须授予它访问权限。否则,服务将获取证书,但会显示证书没有私钥。
总结一下:
以管理员权限运行,以确保 InternalWebService 的私钥确实进入证书存储区。 (您将在 MMC 管理单元中的证书上看到一个小密钥,右键单击证书将有一个选项“管理私钥...”,如果没有附加私钥,则该选项不会出现。)
将InternalWebService 放在Web 服务正在查找它的位置。我猜是“个人”(又名“我的”),但您知道它在服务配置中的位置。无论是当前用户还是本地计算机,请查看您的配置。
授予对InternalWebService 证书私钥的访问权限。
将 CA 证书(不带其私钥)放在受信任的根下,并且您还需要将其放在客户端上(或者让客户端接受“不受信任的证书”) ” 在其末尾。)
I think you are close. Here are some suggestions:
Make sure you are getting a private key attached to your certificate in the second step. You have to run the command in an elevated process -- even if you have Admin privileges, you have to, for example, right-click and "Run as Administrator" to start the command shell you use for this command. Otherwise, you won't get the private key into the localMachine store.
I would use
-ss my
and put the certificate (with private key) into the Personal store. Here I see this:cc.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySubjectName,
"contoso.com");
and so wherever you are pointing to in your equivalent, put the certificate there.
You don't need to import the private key of the CA cert (the first one you created). That's only kept around to sign more certificates with MakeCert. You will need a copy of that CA certificate (without the private key!) on the client that is connecting in, otherwise the client won't be able to validate the InternalWebService certificate.
You don't really need the CA certificate locally on the server machine, because it will only be needed by the client. But it doesn't hurt, and would be needed if anything on the server connects to the service locally. Also, it makes the InternalWebService certificate look good on the MMC snap-in. You can try with and without the CA in the Trusted Root store and you'll see what I mean. But in any case, I would not put the private key of the CA into the local computer store.
Check the private key permissions for InternalWebService from the MMC snap-in (right-click on the certificate, then Tasks, Manage Private Keys...) If you import under a different user account than the service runs under, then certainly it won't have access yet, and you have to go give it access. Otherwise the service will get the certificate, but it will appear that the certificate does not have a private key.
To summarize:
Run with Admin privileges to make sure the private key of InternalWebService is really getting into the certificate store. (You'll see a little key on the certificate in the MMC snap-in, and right-clicking on the certificate will have an option "Manage Private Keys..." which is not present if there is no private key attached.)
Put the InternalWebService in the place where you Web service is looking for it. I would guess "Personal" (a.k.a. "my") but you know where that is in your service config. Whether current user or local machine, look in your config.
Give access to the InternalWebService certificate private key.
Put the CA certificate -- without its private key -- under Trusted Root, and you'll need to put that on the client as well (or otherwise have the client accept an "untrusted certificate" at its end.)