none
WCF自定义用户名密码认证部署到IIS上的问题,请大伙帮忙看看。 RRS feed

  • 问题

  • 我在IIS上托管 调试一个星期了 没成功过一次。郁闷+崩溃。。。。
    有2个错误
    如果 证书放在CurrentUser 就会报
    无法使用以下搜索标准找到 X.509 证书: StoreName“My”、StoreLocation“CurrentUser”、
    FindType“FindBySubjectName”、FindValue“WCFServerCertificate”。

    如果证书放在 localmachine 中
    就会报
    [CryptographicException: 句柄无效。
    ]
       System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) +1520238
       System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) +55
       System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() +79
       System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) +309
       System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters) +9
       System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() +199
       System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) +63
    
    [ArgumentException: 证书“CN=MyServer”必须具有能够进行密钥交换的私钥。该进程必须具有访问私钥的权限。]
       System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) +2447612
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateServerX509TokenProvider() +34
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateLocalSecurityTokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement) +56
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement requirement) +47
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoServerX509TokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement) +169
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoSecurityTokenAuthenticator(RecipientServiceModelSecurityTokenRequirement recipientRequirement, Boolean requireClientCertificate, SecurityTokenResolver& sctResolver) +659
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, SecurityTokenResolver& outOfBandTokenResolver) +510
       System.ServiceModel.Security.SessionRenewSecurityTokenManager.CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, SecurityTokenResolver& outOfBandTokenResolver) +88
       System.ServiceModel.Security.SymmetricSecurityProtocolFactory.OnOpen(TimeSpan timeout) +2829870
       System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +19
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Security.SecurityProtocolFactory.Open(Boolean actAsInitiator, TimeSpan timeout) +23
       System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +80
       System.ServiceModel.Channels.SecurityChannelListener`1.OnOpen(TimeSpan timeout) +204
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +61
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +123
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Security.SecuritySessionSecurityTokenAuthenticator.OnOpen(TimeSpan timeout) +129
       System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +19
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Security.CommunicationObjectSecurityTokenAuthenticator.Open(TimeSpan timeout) +20
       System.ServiceModel.Security.SecurityUtils.OpenCommunicationObject(ICommunicationObject obj, TimeSpan timeout) +18
       System.ServiceModel.Security.SecurityUtils.OpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout) +27
       System.ServiceModel.Security.SecuritySessionServerSettings.OnOpen(TimeSpan timeout) +735
       System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +19
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Security.SecuritySessionServerSettings.Open(TimeSpan timeout) +20
       System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +123
       System.ServiceModel.Channels.SecurityChannelListener`1.OnOpen(TimeSpan timeout) +204
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +61
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +123
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Channels.CommunicationObject.Open() +30
       System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +104
       System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +498
    
    [ServiceActivationException: 由于编译过程中出现异常,无法激活服务“/wcftest3/WcfServiceLibrary7.Service1.svc”。异常消息为: 证书“CN=MyServer”必须具有能够进行密钥交换的私钥。该进程必须具有访问私钥的权限。。]
       System.ServiceModel.AsyncResult.End(IAsyncResult result) +4413209
       System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +183
       System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, Boolean flowContext) +205
       System.ServiceModel.Activation.HttpModule.ProcessRequest(Object sender, EventArgs e) +322
       System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +92
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +64
    


    2009年9月18日 3:44

答案

  • 找到错误了 服务器上的 NETWORK SERVICE账户权限不够
    使用 cacls.exe 等工具向 WCF 运行时所使用的帐户授予对包含私钥的文件的读访问权限。
    下面的代码示例编辑 (/E) 指定文件的访问控制列表 (ACL),以向“NETWORK SERVICE”帐户授予 (/G) 对此文件的读 (:R) 访问权限。
    cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\8aeda5eb81555f14f8f9960745b5a40d_38f7de48-5ee9-452d-8a5a-92789d7110b1" /E /G "NETWORK SERVICE":R
    谢谢 老许了
    2009年9月23日 1:36

全部回复

  • 1.
       你证书的制作语句是什么?
      如果在该存储区找不到证书,检查一下你的证书配置。还有配置文件的设置查找信息是否有误。
    2.你的证书没有可交换的密钥。
    请使用以下语句制作证书,
    (1)使用makecert 工具:Microsoft Visual Studio 2008-->Visual Studio Tools-->Visual Studio 2008 命令提示行。
    输入:makecert -sr localmachine -ss My -n CN=WCFServerPK -sky exchange -pe -r
    输入:makecert -sr localmachine -ss My -n CN=WCFClientPK -sky exchange -pe -r。
    -这里制作了连个证书,主要只使用一个WCFServerPK,可以到出密钥文件pfx,后续我们要导入到其他存储区,设置为信任的证书。WCFClientPK -是为以后文章准备的,也是可以设置为信任的证书。


    http://www.cnblogs.com/frank_xl/archive/2009/08/13/1543848.html


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年9月18日 4:35
    版主
  • 我用来制作证书的 语句就是 makecert -sr localmachine -ss My -n CN=WCFServerPK -sky exchange -pe -r

    但是在IIS上一发布 就会报 句柄无效的错误。
    应该不是证书制作的问题。因为 我如果不用IIS托管的话。
    在客户端跟服务器端 分别田间证书为信任 就可以成功运行。
    但是只要托管到IIS上就会报这个错。

    也在老徐的博客上留言,一直想找到不用再客户端安装证书就可以的方法 但是老徐给的回答一直很模糊。
    现在只有消息认证 在客户端跟服务器端都安装了证书 wcf不通过IIS托管才能成功。

    如果按照老徐博客上传输安全模式的写法来做,当客户端引用wcf服务时间。报错

    下载“https://localhost:9001/”时出错。
    基础连接已经关闭: 发送时发生错误。
    由于远程方已关闭传输流,身份验证失败。
    元数据包含无法解析的引用:“https://localhost:9001/”。
    https://localhost:9001/ 执行 HTTP 请求时发生错误。这可能是由于在使用 HTTPS 的情况下未使用 HTTP.SYS 正确配置服务器证书造成的。这还可能是由于客户端和服务器之间的安全绑定不匹配所致。
    基础连接已经关闭: 发送时发生错误。
    由于远程方已关闭传输流,身份验证失败。
    如果该服务已在当前解决方案中定义,请尝试生成该解决方案,然后再次添加服务引用。

    很想同时在线请教下 徐老师。 谢谢
    2009年9月21日 10:11
  • Hi,
      不要这么客气,我尽量给你提供参考意见。有的知识我也不一定知道~可以一起交流
     1.安全模式:首先来看你的错误信息,从这里能看出你使用的是传输安全模式,https.
    2.错误原因:身份验证失败,基本也就是你的客户端没有提供正确的凭据,我现在不知道你使用的是什么客户端验证方式。
    3.你需要配置SSL证书,错误信息里已经提示HTTP.SYS 正确配置。传输安全模式需要服务器提供证书,用于建立SSL链接,具体配置你可以参考,安全开发实践系列你的传输安全文章。


     WCF分布式安全开发实践(6):传输安全模式之自定义X509证书验证:Transport_X509Certificate_WSHttpBinding
    WCF分布式安全开发实践(5):传输安全模式之Certificate身份验证:Transport_Certificate_WSHttpBinding
    WCF分布式安全开发实践(4):传输安全模式之Windows身份验证:Transport_Windows_NetTcpBinding
    WCF分布式安全开发实践(3):传输安全模式之自定义用户名密码身份验证:Transport_UserNamePassword_WSHttpBinding
    WCF分布式安全开发实践(2):传输安全模式之基本身份验证(Windows账户密码):Transport_Basic_WSHttpBinding
    WCF分布式安全开发实践(1):传输安全模式之匿名客户端:Transport_None_WSHttpBinding


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年9月21日 12:00
    版主
  • 开始是用消息安全模式的。
    制作证书也是正确的
    (1)使用makecert 工具:Microsoft Visual Studio 2008-->Visual Studio Tools-->Visual Studio 2008 命令提示行。
    输入:makecert -sr localmachine -ss My -n CN=WCFServerPK -sky exchange -pe -r
    输入:makecert -sr localmachine -ss My -n CN=WCFClientPK -sky exchange -pe -r。
    -这里制作了连个证书,主要只使用一个WCFServerPK,可以到出密钥文件pfx,后续我们要导入到其他存储区,设置为信任的证书。WCFClientPK -是为以后文章准备的,也是可以设置为信任的证书。

    但是IIS发布以后 浏览报错
    [CryptographicException: 句柄无效。
    ]
       System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) +1520238
       System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) +55
       System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() +79
       System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) +309
       System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters) +9
       System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() +199
       System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) +63
    
    [ArgumentException: 证书“CN=MyServer”必须具有能够进行密钥交换的私钥。该进程必须具有访问私钥的权限。]
       System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) +2447612
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateServerX509TokenProvider() +34
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateLocalSecurityTokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement) +56
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement requirement) +47
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoServerX509TokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement) +169
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateTlsnegoSecurityTokenAuthenticator(RecipientServiceModelSecurityTokenRequirement recipientRequirement, Boolean requireClientCertificate, SecurityTokenResolver& sctResolver) +659
       System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, SecurityTokenResolver& outOfBandTokenResolver) +510
       System.ServiceModel.Security.SessionRenewSecurityTokenManager.CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, SecurityTokenResolver& outOfBandTokenResolver) +88
       System.ServiceModel.Security.SymmetricSecurityProtocolFactory.OnOpen(TimeSpan timeout) +2829870
       System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +19
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Security.SecurityProtocolFactory.Open(Boolean actAsInitiator, TimeSpan timeout) +23
       System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +80
       System.ServiceModel.Channels.SecurityChannelListener`1.OnOpen(TimeSpan timeout) +204
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +61
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +123
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Security.SecuritySessionSecurityTokenAuthenticator.OnOpen(TimeSpan timeout) +129
       System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +19
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Security.CommunicationObjectSecurityTokenAuthenticator.Open(TimeSpan timeout) +20
       System.ServiceModel.Security.SecurityUtils.OpenCommunicationObject(ICommunicationObject obj, TimeSpan timeout) +18
       System.ServiceModel.Security.SecurityUtils.OpenTokenAuthenticatorIfRequired(SecurityTokenAuthenticator tokenAuthenticator, TimeSpan timeout) +27
       System.ServiceModel.Security.SecuritySessionServerSettings.OnOpen(TimeSpan timeout) +735
       System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout) +19
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Security.SecuritySessionServerSettings.Open(TimeSpan timeout) +20
       System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +123
       System.ServiceModel.Channels.SecurityChannelListener`1.OnOpen(TimeSpan timeout) +204
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +61
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +123
       System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +268
       System.ServiceModel.Channels.CommunicationObject.Open() +30
       System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +104
       System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +498
    
    [ServiceActivationException: 由于编译过程中出现异常,无法激活服务“/wcftest3/WcfServiceLibrary7.Service1.svc”。异常消息为: 证书“CN=MyServer”必须具有能够进行密钥交换的私钥。该进程必须具有访问私钥的权限。。]
       System.ServiceModel.AsyncResult.End(IAsyncResult result) +4413209
       System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +183
       System.ServiceModel.Activation.HostedHttpRequestAsyncResult.ExecuteSynchronous(HttpApplication context, Boolean flowContext) +205
       System.ServiceModel.Activation.HttpModule.ProcessRequest(Object sender, EventArgs e) +322
       System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +92
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +64
    
    
    2009年9月22日 3:10
  • 还不行是吧?我有必要做一些IIS托管WCF安全的测试了。
    这个问题在自定义托管的时候很容易就解决了。
    我在看看
    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年9月22日 10:30
    版主
  • 找到错误了 服务器上的 NETWORK SERVICE账户权限不够
    使用 cacls.exe 等工具向 WCF 运行时所使用的帐户授予对包含私钥的文件的读访问权限。
    下面的代码示例编辑 (/E) 指定文件的访问控制列表 (ACL),以向“NETWORK SERVICE”帐户授予 (/G) 对此文件的读 (:R) 访问权限。
    cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\8aeda5eb81555f14f8f9960745b5a40d_38f7de48-5ee9-452d-8a5a-92789d7110b1" /E /G "NETWORK SERVICE":R
    谢谢 老许了
    2009年9月23日 1:36
  • Hi,
      不好意思,我也没能给出正确的解答,只是提了些建议。呵呵。
      谢谢你能把问题答案和大家分享。
      以后常来交流~


    Frank Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    欢迎访问老徐的中文技术博客:Welcome to My Chinese Technical Blog
    欢迎访问微软WCF中文技术论坛:Welcome to Microsoft Chinese WCF Forum
    欢迎访问微软WCF英文技术论坛:Welcome to Microsoft English WCF Forum
    2009年9月23日 13:16
    版主