IIS7 共享主机上的 WCF 身份验证 [英] WCF authentication on IIS7 shared hosting

查看:53
本文介绍了IIS7 共享主机上的 WCF 身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过几天的测试,我发现创建带有身份验证的 WCF Web 服务的唯一方法是将证书放在 localmachine/trustedpeople 证书存储中.主人不会为我做这件事.您知道有什么方法可以在不将证书放入该商店的情况下启用 WCF 身份验证吗?有没有其他方法可以让 WCF 安全在共享主机上工作?

我在 codeproject 上使用了一个示例,该示例将证书放入 app_data,但我无法让它发挥作用.

解决方案

我在本地 IIS 上做了一些非常简单的测试.我使用单一方法提供非常简单的服务.为了公开服务,我使用此配置:

<预><代码><配置><应用设置><add key="CertificatePath" value="D:\Applications\CertificateFromFile\App_Data\ServerCert.pfx"/><add key="CertificatePassword" value="密码"/></appSettings><system.web><编译调试="true" targetFramework="4.0"/></system.web><system.serviceModel><行为><服务行为><行为><serviceMetadata httpGetEnabled="true"/><serviceDebug includeExceptionDetailInFaults="true"/><serviceCredentials><userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CertificateFromFile.MyPasswordValidator, CertificateFromFile"/></serviceCredentials></行为></serviceBehaviors></行为><协议映射><清除/><add scheme="http" binding="wsHttpBinding"/></protocolMapping><绑定><wsHttpBinding><绑定><安全模式=消息"><message clientCredentialType="UserName"establishSecurityContext="false"negotiationServiceCredential="false"/></安全></binding></wsHttpBinding></绑定><serviceHostingEnvironment multipleSiteBindingsEnabled="true"><服务激活><add service="CertificateFromFile.MyService" factory="CertificateFromFile.MyServiceHostFactory" relativeAddress="Service.svc"/></serviceActivations></serviceHostingEnvironment></system.serviceModel><system.webServer><modules runAllManagedModulesForAllRequests="true"/></system.webServer></配置>

配置定义:

  • 描述证书和密码路径的两个自定义 appSettings.
  • 具有基于配置的激活的单个服务 - 它将具有需要消息级身份验证的 wsHttpBinding(通过 protocolMapping 定义)的默认端点.
  • 定义自定义密码验证器但没有服务证书的默认行为!
  • 使用自定义 ServiceHostFactory 在自定义服务主机上激活服务.

加载证书的全部魔法是在自定义服务主机和服务主机工厂中完成的:

命名空间 CertificateFromFile{公共类 MyServiceHostFactory : ServiceHostFactory{protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses){字符串路径 = ConfigurationManager.AppSettings["CertificatePath"];字符串密码 = ConfigurationManager.AppSettings["CertificatePassword"];返回新的 MyServiceHost(serviceType, path, password, baseAddresses);}}公共类 MyServiceHost : ServiceHost{私有只读字符串_certificatePath;私有只读字符串_certificatePassword;public MyServiceHost(Type serviceType, string certificatePath, string certificatePassword, params Uri[] baseAddresses):基地(服务类型,基地地址){_certificatePath = 证书路径;_certificatePassword = 证书密码;}受保护的覆盖 void OnOpening(){base.OnOpening();var certificate = new X509Certificate2(_certificatePath, _certificatePassword);var凭据 = Description.Behaviors.Find();凭据.ServiceCertificate.Certificate = 证书;}}}

After several days of tests I find the only way I can create a WCF web service with authentication is to put a certificate in localmachine/trustedpeople cert store. The host will not do this for me. Do you know any way to enable WCF authentication without putting a cert in that store? Is there any other way to get WCF security working on shared hosting?

I have worked with a sample on codeproject that puts certs in app_data, but I haven't been able to get that to work.

解决方案

I did some very simple test on my local IIS. I have very simple service with single method. To expose the service I use this configuration:

<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>

The configuration defines:

  • Two custom appSettings describing path to the certificate and password.
  • Single service with configuration based activation - it will have default endpoint with wsHttpBinding (defined via protocolMapping) requiring message level authentication.
  • Default behaviour defining custom password validator but no service certificate!
  • Service is activated on custom service host with custom ServiceHostFactory.

The whole magic of loading certificate is done in custom service host and service host factory:

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;
        }
    }
}

这篇关于IIS7 共享主机上的 WCF 身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆