Проверка подлинности WCF на виртуальном хостинге IIS7
После нескольких дней тестов я обнаружил, что единственный способ создать веб-сервис WCF с аутентификацией - это поместить сертификат в хранилище сертификатов localmachine/rustpeople. Хозяин не сделает это для меня. Знаете ли вы какой-либо способ включить аутентификацию WCF без помещения сертификата в этот магазин? Есть ли другой способ заставить безопасность WCF работать на виртуальном хостинге?
Я работал с примером кода проекта, который помещает сертификаты в app_data, но я не смог заставить это работать.
1 ответ
Я сделал очень простой тест на моем местном 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>
Конфигурация определяет:
- Два пользовательских appSettings, описывающие путь к сертификату и паролю.
- Единый сервис с активацией на основе конфигурации - он будет иметь конечную точку по умолчанию с 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;
}
}
}