WCF с сертификатами на клиенте и сервере (безопасность сообщений и 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>

Файл Конфигурации Клиента

<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 из отчаяния). Насколько мне известно, эта часть работает.

проблемы возникают при вызове службы. Последняя ошибка:

незащищенное или неправильно защищенное сообщение об ошибке от другого вечеринка. См для код ошибки и описание.

сообщение не удалось обработать. Это скорее всего потому, что действие "http://tempuri.org/IServiceAPI/MyMethod' is неверно или потому, что сообщение содержит недопустимый или истекший срок действия маркер контекста безопасности, или потому что там выполняется м между фурнитура. Маркер контекста безопасности будет недопустимым, если служба прерван канал из-за бездействия. Чтобы предотвратить обслуживание от преждевременное прерывание сеансов ожидания увеличивает время ожидания приема на привязка конечной точки службы.

или даже (предыдущая ошибка)

ошибка проверки подлинности исходящего сообщения. Ожидаемое тож идентичность(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.

обратите внимание, я использую безопасность сообщений и wsHttpBinding, потому что они оказались правильными chouices. У меня нет никаких больших ограничений, кроме публикации службы, которая может быть использована standard Платформу Java.

может кто-нибудь помочь мне разобраться в этом беспорядке?

любая помощь будет оценена grealty

С уважением,

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;

Это получит отпечаток большого пальца клиента, который будет отличаться для каждого клиента, которому вы выдаете сертификат. Конечно, все остальные данные сертификата доступны.


сообщение не удалось обработать. Это, скорее всего, потому, что действие "http://tempuri.org/IServiceAPI/MyMethod" неверно или потому, что сообщение содержит недопустимый или истекший токен контекста безопасности, или потому, что существует M ismatch между привязками. Маркер контекста безопасности будет недействительным, если служба прервала канал из-за бездействия. Чтобы предотвратить преждевременное прерывание сеансов простоя службой, увеличьте время ожидания получения на конечной точке службы обязательный.

Это означает, что запрос по тайм-ауту. Обратитесь к средству просмотра событий 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 узел неправильно указывает на неправильное место. Вы изменили расположение службы с момента создания сертификатов? Это недействительно, если вы переехали после этого.