【问题标题】:WCF with certificates on both Client and Server (Message security and wsHttpBinding)WCF 在客户端和服务器上都有证书(消息安全和 wsHttpBinding)
【发布时间】:2012-08-19 02:46:24
【问题描述】:

我正在尝试在客户端和服务器上设置具有证书身份验证的 WCF 服务。我正在经历地狱,遍历所有可能的错误消息。

这里的最终目标是使用证书对双方进行身份验证。我将为每个客户颁发一个特定的证书(希望)让我能够将他们区分开来。

到目前为止,我有以下配置文件:

服务器配置文件

<configuration>
    <system.serviceModel>
        <services>
            <service name="ServiceApiImplementation" behaviorConfiguration="myBehaviour">
                <host>
                    <baseAddresses><add baseAddress="http://localhost:9110/MyService"/></baseAddresses>
                </host>
                <endpoint address="" binding="wsHttpBinding" contract="IServiceAPI" bindingName="SOAP12Binding">
                    <identity>
                        <certificateReference findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName"/>
                    </identity>
                </endpoint>
            </service>
        </services>
        <bindings>
            <wsHttpBinding>
                <binding name="SOAP12Binding" receiveTimeout="00:02:00" closeTimeout="00:01:00" openTimeout="00:01:00" sendTimeout="00:01:00">
                    <security mode="Message">
                        <message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <behaviors>
            <serviceBehaviors>
                <behavior name="myBehaviour">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceCredentials>
                        <serviceCertificate findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
                        <clientCertificate>
                            <authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck"/>
                        </clientCertificate>
                    </serviceCredentials>
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

客户端配置文件

<system.serviceModel>
    <client>
        <endpoint address="http://localhost:9110/MyService" binding="wsHttpBinding" 
                  bindingConfiguration="SOAP12Binding_IServiceAPI" contract="IServiceAPI" 
                  behaviorConfiguration="behaviour1" name="SOAP12Binding_IServiceAPI">
            <identity>
                <!-- Value obtained when "Adding a Service Reference in visual studio" -->
                <certificate encodedValue="xxxxxxxxxxxxx" />
            </identity>
        </endpoint>
    </client>
    <behaviors>
        <endpointBehaviors>
            <behavior name="behaviour1">
                <clientCredentials>
                    <clientCertificate findValue="ClientCertificate" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName"/>
                    <serviceCertificate>
                        <defaultCertificate findValue="ServerCertificate" storeName="My" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
                        <authentication certificateValidationMode="ChainTrust" trustedStoreLocation="LocalMachine" revocationMode="NoCheck" />
                    </serviceCertificate>
                </clientCredentials>
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <bindings>
        <wsHttpBinding>
            <binding name="SOAP12Binding_IServiceAPI">
                <security mode="Message">
                    <message clientCredentialType="Certificate"  negotiateServiceCredential="false" establishSecurityContext="false" />
                </security>
            </binding>
        </wsHttpBinding>
    </bindings>
</system.serviceModel>

我已经为客户端和服务器生成了一个 rootCA 和几个证书,获得了适当的权限并将它们放入存储中(LocalMachine 和 CurrentUSer 都出于绝望)。据我所知,这一点很有效。

调用服务时会出现问题。最新的错误是:

从对方收到不安全或不正确安全的故障 派对。故障代码和细节见内部FaultException。

无法处理该消息。这很可能是因为 操作“http://tempuri.org/IServiceAPI/MyMethod”是 不正确或因为消息包含无效或过期 安全上下文令牌或因为之间存在 m 不匹配 绑定。如果服务,安全上下文令牌将无效 由于不活动而中止了通道。为了防止服务 过早中止空闲会话会增加接收超时 服务端点的绑定。

甚至(上一个错误)

外发消息的身份检查失败。预期的 身份是 '身份(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn)' 为 'http://localhost:9110/MyService' 目标端点。

错误消息根据我在配置文件中的实验而有所不同。现在客户端和服务器都在同一台机器上运行,所以,至少,我希望每个应用程序都会通过 rootCA 对另一个应用程序进行身份验证。

请注意,我正在使用 Message Security 和 wsHttpBinding,因为它们似乎是正确的选择。除了发布可以被标准 JAVA 框架使用的服务之外,我没有任何大的限制。

谁能帮我解决这个烂摊子?

任何帮助将不胜感激

问候,

【问题讨论】:

    标签: wcf certificate wshttpbinding


    【解决方案1】:

    无法处理该消息。这很可能是因为“http://tempuri.org/IServiceAPI/MyMethod”操作不正确,或者因为消息包含无效或过期的安全上下文令牌,或者因为绑定之间存在不匹配。如果服务因不活动而中止通道,则安全上下文令牌将无效。为防止服务过早中止空闲会话,请增加服务端点绑定的接收超时。

    这表示服务请求正在超时。请参阅 Windows 事件查看器或在您的服务上启用日志记录。见:http://msdn.microsoft.com/en-us/library/ms732023.aspx

    外发消息的身份检查失败。对于“http://localhost:9110/MyService”目标端点,预期的身份是“identity(http://schemas.xmlsoap.org/ws/2005/05/identity/right/possessproperty:http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn)”。

    这表明您的indentity 节点错误地指向了错误的位置。自生成证书后,您是否更改了服务的位置?事后搬家无效。

    【讨论】:

    • 嗨贾斯汀。关于第一个消息,跟踪是不确定的。另外,这两个服务都在本地主机上运行并且只返回虚拟数据。我没有更改服务位置。不过,您觉得配置正确吗?
    【解决方案2】:

    我设法解决了我最初的问题。

    关于双向证书认证,我发现下面的codeproject文章提供了一个工作演示:http://www.codeproject.com/Articles/36683/9-simple-steps-to-enable-X-509-certificates-on-WCF#Step%201:-%20Create%20client%20and%20server%20certificates

    尽管这个示例使用了对等信任,但到目前为止,无论如何我都无法让一个工作原型正常工作。从这一点开始,我预见到的唯一陷阱是将证书链存储在适当的位置,并为您的项目正在运行的用户提供对私钥的访问权限。有关如何授予证书私钥权限的说明,请参阅本文:http://msdn.microsoft.com/en-us/library/ff647171.aspx#Step6

    对于问题的第二部分:如何在 WCF 服务中区分客户端证书?,您可以使用以下代码获取客户端的证书指纹:

    X509Certificate2 certificate = null;
    
    if(ServiceSecurityContext.Current.AuthorizationContext.ClaimSets == null)
        throw new Exception("No claim set");
    
    foreach(var claim in ServiceSecurityContext.Current.AuthorizationContext.ClaimSets)
        if(claim is X509CertificateClaimSet)
        {
            X509CertificateClaimSet xcset = claim as X509CertificateClaimSet;
            certificate = xcset.X509Certificate;
            break;
        }
    
    if(certificate == null)
        throw new Exception("No X509 certificate found");
    
    string clientCertificateThumbprint = certificate.Thumbprint;
    

    这将获得客户端的指纹,该指纹对于您向其颁发证书的每个客户端都不同。当然,所有其他证书数据都是可用的。

    【讨论】:

      猜你喜欢
      • 2011-10-25
      • 1970-01-01
      • 2014-06-19
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-28
      • 2017-02-03
      相关资源
      最近更新 更多