Проверка подлинности WCF на виртуальном хостинге IIS7 - PullRequest
2 голосов
/ 02 июня 2011

После нескольких дней тестов я обнаружил, что единственный способ создать веб-сервис WCF с аутентификацией - это поместить сертификат в хранилище сертификатов localmachine /rustpeople. Хозяин не сделает это для меня. Знаете ли вы какой-либо способ включить аутентификацию WCF без помещения сертификата в этот магазин? Есть ли другой способ заставить работать безопасность WCF на виртуальном хостинге?

Я работал с примером кода проекта, который помещает сертификаты в app_data, но я не смог заставить его работать.

1 Ответ

3 голосов
/ 03 июня 2011

Я провел очень простой тест на своем локальном IIS.У меня очень простой сервис с одним методом.Для предоставления сервиса я использую эту конфигурацию:

<configuration>
  <appSettings>
    <add key="CertificatePath" value="D:\Applications\CertificateFromFile\App_Data\ServerCert.pfx" />
    <add key="CertificatePassword" value="password" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CertificateFromFile.MyPasswordValidator, CertificateFromFile" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <clear />
      <add scheme="http" binding="wsHttpBinding" />
    </protocolMapping>
    <bindings>
      <wsHttpBinding>
        <binding>
          <security mode="Message">
            <message clientCredentialType="UserName" establishSecurityContext="false" negotiateServiceCredential="false" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true">
      <serviceActivations>
        <add service="CertificateFromFile.MyService" factory="CertificateFromFile.MyServiceHostFactory" relativeAddress="Service.svc" />
      </serviceActivations>
    </serviceHostingEnvironment>
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>
</configuration>

Конфигурация определяет:

  • Два пользовательских набора настроек, описывающих путь к сертификату и паролю.
  • Один сервисс активацией на основе конфигурации - у нее будет конечная точка по умолчанию с wsHttpBinding (определяется с помощью protocolMapping), требующей аутентификации на уровне сообщений.
  • Поведение по умолчанию, определяющее пользовательский валидатор паролей, но без сертификата сервиса!
  • Сервис активируется в пользовательскомсервисный хост с пользовательским ServiceHostFactory.

Вся магия загрузки сертификата выполняется на фабрике пользовательских сервисных хостов и сервисных хостов:

namespace CertificateFromFile
{
    public class MyServiceHostFactory : ServiceHostFactory
    {
        protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            string path = ConfigurationManager.AppSettings["CertificatePath"];
            string password = ConfigurationManager.AppSettings["CertificatePassword"];
            return new MyServiceHost(serviceType, path, password, baseAddresses);
        }
    }

    public class MyServiceHost : ServiceHost
    {
        private readonly string _certificatePath;
        private readonly string _certificatePassword;

        public MyServiceHost(Type serviceType, string certificatePath, string certificatePassword, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            _certificatePath = certificatePath;
            _certificatePassword = certificatePassword;
        }

        protected override void OnOpening()
        {
            base.OnOpening();

            var certificate = new X509Certificate2(_certificatePath, _certificatePassword);
            var credentials = Description.Behaviors.Find<ServiceCredentials>();
            credentials.ServiceCertificate.Certificate = certificate;
        }
    }
}
...