IIS 7.5 上托管的 ASP.NET 应用程序中的 WCF 客户端证书存在问题
我有一个 WCF 服务,需要在 IIS 7.5 上托管的 ASP.NET Web 应用程序中调用该服务。此 WCF 服务使用客户端证书的传输安全性。我获得了一个客户端证书,该证书是我使用 mmc 在“本地计算机/个人”存储位置安装的。 .pfx 安装了另外 2 个证书(无私钥),它们是我的带有私钥的客户端证书的 CA。我在运行时分配证书,因为将来我可能会在同一 Web 服务中使用其他证书。
wcfClient.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySerialNumber, "XXXXXXXXXXXXXXXXXXXXXX");
// debugging shows that client certificate was found
var result = wcfClient.CallMyMethod();
对于在 ApplicationPoolIdentity 下运行的 Web 应用程序,调用 Web 服务会抛出 MessageSecurityException 和内部 WebException (403 Forbidden),就好像我根本没有传递客户端证书一样。实际上,如果配置需要的话,不设置有效的证书将会引发 InvalidOperationException。如果我在管理员帐户下运行,则不会引发异常。我需要能够调用 ApplicationPoolIdentity 下的 Web 服务。
编辑:我认为证书链可能是这里的问题...
到目前为止我已经尝试过:
- 在 MMC 中:MyCertificate ->所有任务 ->管理私钥...我向 IIS_IUSRS 授予了管理私钥的权限
- 为 C:\ProgramData\Microsoft\Crypto\RSA 添加了对 IIS_IUSRS 的读取访问权限
- 我使用了 System.Net 跟踪,并且比较了 ApplicationPoolIdentity 和我的日志管理员帐户。一切看起来都一样,直到下面的某个点,在“我们有用户提供的证书。服务器已指定 24 个颁发者。正在查找与任何颁发者匹配的证书。”行
ApplicationPoolIdentity Log 之后:
System.Net Information: 0 : [5436] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CredentialsNeeded).
System.Net Information: 0 : [5436] SecureChannel#20350898 - We have user-provided certificates. The server has specified 24 issuer(s). Looking for certificates that match any of the issuers.
System.Net Information: 0 : [5436] SecureChannel#20350898 - Left with 0 client certificates to choose from.
System.Net Information: 0 : [5436] Using the cached credential handle.
System.Net Information: 0 : [5436] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = fc5d070:1ffd1d0, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5436] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=349, returned code=ContinueNeeded).
System.Net Information: 0 : [5436] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = fc5d070:1ffd1d0, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5436] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [5436] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = fc5d070:1ffd1d0, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5436] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=OK).
System.Net Information: 0 : [5436] Remote certificate: [bla bla remote certificate]
System.Net Information: 0 : [5436] SecureChannel#20350898 - Remote certificate was verified as valid by the user.
管理员帐户日志:
System.Net Information: 0 : [5952] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CredentialsNeeded).
System.Net Information: 0 : [5952] SecureChannel#60080036 - We have user-provided certificates. The server has specified 24 issuer(s). Looking for certificates that match any of the issuers.
System.Net Information: 0 : [5952] SecureChannel#60080036 - Selected certificate: [Bla bla bla client cert info]
System.Net Information: 0 : [5952] SecureChannel#60080036 - Left with 1 client certificates to choose from.
System.Net Information: 0 : [5952] SecureChannel#60080036 - Trying to find a matching certificate in the certificate store.
System.Net Information: 0 : [5952] SecureChannel#60080036 - Locating the private key for the certificate: [Bla bla bla client cert info]
System.Net Information: 0 : [5952] SecureChannel#60080036 - Certificate is of type X509Certificate2 and contains the private key.
System.Net Information: 0 : [5952] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent = Outbound, scc = System.Net.SecureCredential)
System.Net Information: 0 : [5952] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4e5bb48:1fff710, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5952] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=5718, returned code=ContinueNeeded).
System.Net Information: 0 : [5952] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4e5bb48:1fff710, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5952] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [5952] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4e5bb48:1fff710, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5952] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=OK).
System.Net Information: 0 : [5952] Remote certificate: [bla bla bla remote certificate]
I have a WCF service that I need to call in a ASP.NET web application hosted on IIS 7.5. This WCF service uses transport security with client certificates. I am provided with a client certificate which I installed using mmc in "Local Computer/Personal" store location. The .pfx installed 2 other certificates (no private key) which are CA for my client certificate with private key. I am assigning the certificate at runtime, because I might have other certificates used with the same web service in the future.
wcfClient.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySerialNumber, "XXXXXXXXXXXXXXXXXXXXXX");
// debugging shows that client certificate was found
var result = wcfClient.CallMyMethod();
For my web application running under ApplicationPoolIdentity calling the webservice throws MessageSecurityException with a inner WebException (403 Forbidden) as if I wasn't passing the client certificate at all. Actually not setting a valid certificate will through an InvalidOperationException if the configuration demands it. If I run under an administrator account, then no exception is thrown. I need to be able to call the webservice under ApplicationPoolIdentity.
Edit: I think the certificate chain might be the issue here...
What I have tried so far:
- In MMC: MyCertificate -> All Tasks -> Manage Private Keys... I gave permission for managing private keys to IIS_IUSRS
- Added read access to IIS_IUSRS for C:\ProgramData\Microsoft\Crypto\RSA
- I've used System.Net tracing and I've compared the logs for ApplicationPoolIdentity and my administrator account. Everything look the same until a certain point below, after "We have user-provided certificates. The server has specified 24 issuer(s). Looking for certificates that match any of the issuers." line
ApplicationPoolIdentity Log:
System.Net Information: 0 : [5436] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CredentialsNeeded).
System.Net Information: 0 : [5436] SecureChannel#20350898 - We have user-provided certificates. The server has specified 24 issuer(s). Looking for certificates that match any of the issuers.
System.Net Information: 0 : [5436] SecureChannel#20350898 - Left with 0 client certificates to choose from.
System.Net Information: 0 : [5436] Using the cached credential handle.
System.Net Information: 0 : [5436] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = fc5d070:1ffd1d0, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5436] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=349, returned code=ContinueNeeded).
System.Net Information: 0 : [5436] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = fc5d070:1ffd1d0, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5436] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [5436] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = fc5d070:1ffd1d0, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5436] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=OK).
System.Net Information: 0 : [5436] Remote certificate: [bla bla remote certificate]
System.Net Information: 0 : [5436] SecureChannel#20350898 - Remote certificate was verified as valid by the user.
Admin account log:
System.Net Information: 0 : [5952] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=CredentialsNeeded).
System.Net Information: 0 : [5952] SecureChannel#60080036 - We have user-provided certificates. The server has specified 24 issuer(s). Looking for certificates that match any of the issuers.
System.Net Information: 0 : [5952] SecureChannel#60080036 - Selected certificate: [Bla bla bla client cert info]
System.Net Information: 0 : [5952] SecureChannel#60080036 - Left with 1 client certificates to choose from.
System.Net Information: 0 : [5952] SecureChannel#60080036 - Trying to find a matching certificate in the certificate store.
System.Net Information: 0 : [5952] SecureChannel#60080036 - Locating the private key for the certificate: [Bla bla bla client cert info]
System.Net Information: 0 : [5952] SecureChannel#60080036 - Certificate is of type X509Certificate2 and contains the private key.
System.Net Information: 0 : [5952] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent = Outbound, scc = System.Net.SecureCredential)
System.Net Information: 0 : [5952] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4e5bb48:1fff710, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5952] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=5718, returned code=ContinueNeeded).
System.Net Information: 0 : [5952] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4e5bb48:1fff710, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5952] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded).
System.Net Information: 0 : [5952] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4e5bb48:1fff710, targetName = ws.allianztiriac.ro, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [5952] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=OK).
System.Net Information: 0 : [5952] Remote certificate: [bla bla bla remote certificate]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我们在这里遇到了同样的问题。通过确保链中的证书放置在适当的位置来解决这个问题。使用管理帐户,将证书安装到本地计算机存储的个人文件夹中时,会将中间证书放置在同一文件夹中。将它们移动到中级证书颁发机构文件夹中,为 ApplicationPoolIdentity 提供了对完整链的访问权限。
We had the same issue here. It was solved by ensuring the certificates in the chain were placed in the appropriate locations. Using an administrative account, when installing the certificate into the Personal folder of Local Machine store, it placed the intermediate certs in the same folder. Moving them to the Intermediate Certification Authorities folder provided the ApplicationPoolIdentity access to the complete chain.
作为一个想法 - 为什么不在您的网络应用程序的配置中指定要发送的证书?如果证书要求发生变化,只需添加到您的 Web 应用程序的 web.config 中即可。
例如,查看客户端的设置方式:
http://www.codeproject.com/KB/WCF/Senthil.aspx
As an idea - why not just specify in your web app's config the certificates to send over? If the cert requirements change, simply add to the web.config of your web app.
See how the client is setup here for example:
http://www.codeproject.com/KB/WCF/Senthil.aspx