客户端和服务器上都有证书的WCF(消息安全性和wsHttpBinding)

tgg*_*ggm 7 wcf certificate wshttpbinding

我正在尝试在客户端和服务器上使用证书身份验证设置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>
Run Code Online (Sandbox Code Playgroud)

客户端配置文件

<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>
Run Code Online (Sandbox Code Playgroud)

我已经为客户端和服务器生成了一个rootCA和几个证书,给定了相应的权限并将它们放在商店中(LocalPachine和CurrentUSer都绝望了).据我所知,这一点很有效.

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

从另一方收到了无担保或不正确安全的故障.请参阅内部FaultException以获取故障代码和详细信息.

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

甚至(以前的错误)

传出消息的身份检查失败.预期的身份是'身份( 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,因为它们似乎是正确的chouices.除了发布可以由标准JAVA框架使用的服务之外,我没有任何大的限制.

任何人都可以帮助我解决这个烂摊子吗?

任何帮助都会受到赞赏

问候,

tgg*_*ggm 1

我设法解决了我原来的问题。

关于双向证书身份验证,我发现以下codeproject文章提供了工作演示:http://www.codeproject.com/Articles/36683/9-simple-steps-to-enable-X-509-certificates- on-WCF#Step%201:-%20创建%20client%20和%20server%20证书

诚然,这个例子使用了对等信任,但到目前为止,无论如何我都无法让工作原型正常工作。从现在开始,我预见到的唯一陷阱是将证书链存储在正确的位置,并向运行项目的用户提供对私钥的访问权限。有关如何授予证书私钥权限的说明,请参阅本文: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;
Run Code Online (Sandbox Code Playgroud)

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