7

我正在尝试在客户端和服务器上设置具有证书身份验证的 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”不正确,或者因为消息包含无效或过期的安全上下文令牌,或者因为绑定之间存在不匹配。如果服务由于不活动而中止通道,则安全上下文令牌将无效。要防止服务过早中止空闲会话,请增加服务端点绑定的接收超时。

甚至(上一个错误)

传出消息的身份检查失败。预期的身份是'身份( 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 框架可以使用的服务外,我没有任何大的限制。

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

任何帮助将不胜感激

问候,

4

2 回答 2

1

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

关于双向证书认证,我发现下面的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;

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

于 2012-09-08T01:45:45.460 回答
0

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

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

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

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

于 2012-08-23T17:21:37.930 回答