减少WCF配置中重复的嵌套标识

时间:2013-11-07 07:19:03

标签: wcf wcf-endpoint service-model

我的WCF应用程序的web.config有一系列端点定义如下:

<system.serviceModel>
    <services>
        <service behaviorConfiguration="whatever" name="MyService">
            <endpoint name="Endpoint1" address="" binding="customBinding" bindingConfiguration="HttpIssuedTokenBinding" contract="My.App.Contract1">
                <identity>
                    <certificateReference findValue="cert name storeName="TrustedPeople" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
                </identity>
            </endpoint>
            <endpoint name="Endpoint2" address="" binding="customBinding" bindingConfiguration="HttpIssuedTokenBinding" contract="My.App.Contract2">
                <identity>
                    <certificateReference findValue="cert name storeName="TrustedPeople" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
                </identity>
            </endpoint>
            <endpoint name="Endpoint3" address="" binding="customBinding" bindingConfiguration="HttpIssuedTokenBinding" contract="My.App.Contract3">
                <identity>
                    <certificateReference findValue="cert name storeName="TrustedPeople" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
                </identity>
            </endpoint>
            <endpoint name="Endpoint4" address="" binding="customBinding" bindingConfiguration="HttpIssuedTokenBinding" contract="My.App.Contract4">
                <identity>
                    <certificateReference findValue="cert name storeName="TrustedPeople" storeLocation="LocalMachine" x509FindType="FindBySubjectName" />
                </identity>
            </endpoint>

我想做的是

<system.serviceModel>
    <services>
        <service behaviorConfiguration="whatever" name="MyService">
            <endpoint name="Endpoint1" address="" binding="customBinding" bindingConfiguration="HttpIssuedTokenBinding" contract="My.App.Contract1" />
            <endpoint name="Endpoint2" address="" binding="customBinding" bindingConfiguration="HttpIssuedTokenBinding" contract="My.App.Contract2" />
            <endpoint name="Endpoint3" address="" binding="customBinding" bindingConfiguration="HttpIssuedTokenBinding" contract="My.App.Contract3" />
            <endpoint name="Endpoint4" address="" binding="customBinding" bindingConfiguration="HttpIssuedTokenBinding" contract="My.App.Contract4" />

在另一个地方指定一次默认身份定义(甚至只是system.serviceModel元素中的顶级)。

基本上我想干,因为配置一直都是一致的。我需要SO的帮助是在哪里找到“所有端点的默认标识”配置元素。 MSDN没有给出很多帮助,我不知道在应用程序启动时读取web.configs时,在哪里反映.NET库以了解如何解释这个问题。

2 个答案:

答案 0 :(得分:3)

<强>摘要

使用Standard Endpoints创建具有相应身份信息的自定义端点,可以从配置文件中配置。


<强>详细

谢谢你的提问! WCF服务的统一配置可以减少配置开销,这是我一直想要研究的问题,而你的问题只是给我一个借口。

我使用Standard Endpoints解决了这个问题,这些问题自.NET 4以来就已存在。大部分工作都是通过继承StandardEndpointElement完成的:

namespace WcfEx
{
    public class X509EndpointElement : StandardEndpointElement
    {
        private static string _findValueKey = "findValue";
        private static string _storeNameKey = "storeName";
        private static string _storeLocationKey = "storeLocation";
        private static string _x509FindTypeKey = "x509SearchType";

        public virtual string FindValue
        {
            get { return base[_findValueKey] as string; }
            set { base[_findValueKey] = value; }
        }

        public virtual StoreName StoreName
        {
            get { return this[_storeNameKey] is StoreName ? (StoreName) this[_storeNameKey] : (StoreName) 0; }
            set { this[_storeNameKey] = value; }
        }

        public virtual StoreLocation StoreLocation
        {
            get
            {
                return this[_storeLocationKey] is StoreLocation
                           ? (StoreLocation) this[_storeLocationKey]
                           : (StoreLocation) 0;
            }
            set { this[_storeLocationKey] = value; }
        }

        public virtual X509FindType X509FindType
        {
            get { return this[_x509FindTypeKey] is X509FindType ? (X509FindType) this[_x509FindTypeKey] : (X509FindType) 0; }
            set { this[_x509FindTypeKey] = value; }
        }

        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                ConfigurationPropertyCollection properties = base.Properties;
                properties.Add(new ConfigurationProperty(_findValueKey, typeof (string), null,
                                                         ConfigurationPropertyOptions.None));
                properties.Add(new ConfigurationProperty(_storeNameKey, typeof (StoreName), null,
                                                         ConfigurationPropertyOptions.None));
                properties.Add(new ConfigurationProperty(_storeLocationKey, typeof (StoreLocation), null,
                                                         ConfigurationPropertyOptions.None));
                properties.Add(new ConfigurationProperty(_x509FindTypeKey, typeof (X509FindType), null,
                                                         ConfigurationPropertyOptions.None));
                return properties;
            }
        }

        protected override Type EndpointType
        {
            get { return typeof (ServiceEndpoint); }
        }

        protected override ServiceEndpoint CreateServiceEndpoint(ContractDescription contract)
        {
            return new ServiceEndpoint(contract);
        }

        protected override void OnApplyConfiguration(ServiceEndpoint endpoint,
                                                     ServiceEndpointElement serviceEndpointElement)
        {
            endpoint.Address = new EndpointAddress(endpoint.Address.Uri,
                                                   EndpointIdentity.CreateX509CertificateIdentity(
                                                       GetCertificateFromStore()));
        }

        protected override void OnApplyConfiguration(ServiceEndpoint endpoint,
                                                     ChannelEndpointElement channelEndpointElement)
        {
            endpoint.Address = new EndpointAddress(endpoint.Address.Uri,
                                                   EndpointIdentity.CreateX509CertificateIdentity(
                                                       GetCertificateFromStore()));
        }

        private X509Certificate2 GetCertificateFromStore()
        {
            var certificateStore = new X509Store(StoreName, StoreLocation);
            certificateStore.Open(OpenFlags.ReadOnly);
            var matchingCertificates = certificateStore.Certificates.Find(X509FindType, FindValue, false);

            X509Certificate2 matchingCertificate = null;
            if (matchingCertificates.Count > 0)
                matchingCertificate = matchingCertificates[0];
            else throw new InvalidOperationException("Could not find specified certificate");

            certificateStore.Close();
            return matchingCertificate;
        }

        protected override void OnInitializeAndValidate(ChannelEndpointElement channelEndpointElement)
        {

        }

        protected override void OnInitializeAndValidate(ServiceEndpointElement serviceEndpointElement)
        {

        }
    }

}

上述代码的快速摘要:

  • 此类可以在.config文件中显示 - 因此可以通过配置设置属性;
  • 有四个属性指定用于选择X509证书的参数;
  • 在此类的生命周期的某个时刻,端点地址使用满足搜索条件的证书指定的标识进行设置。

您需要一个集合类来保存上述类的元素:

namespace WcfEx
{
    public class X509EndpointCollectionElement : StandardEndpointCollectionElement<ServiceEndpoint, X509EndpointElement>
    {

    }
}

.config文件的system.serviceModel部分如下所示:

<system.serviceModel>
<extensions>
  <endpointExtensions>
    <add name="x509Endpoint" type="WcfEx.X509EndpointCollectionElement, WcfEx, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </endpointExtensions>
</extensions>
<standardEndpoints>
  <x509Endpoint> 
    <standardEndpoint storeLocation="LocalMachine" storeName="TrustedPeople" findValue="cert name" x509SearchType="FindBySubjectName"/>
  </x509Endpoint>
</standardEndpoints> 
<services>
  <service name="WcfHost.Service1">
    <endpoint address="" binding="wsHttpBinding" contract="WcfHost.IService1" kind="x509Endpoint" >
    </endpoint>
  </service>
</services> 
<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

注意事项:

  • 在此非常小心type属性的值 - 它必须与typeof (X509EndpointElement).AssemblyQualifiedName完全相同。
  • 注册后,我们可以将相关配置添加到standardEndpoints元素。
  • 我们使用kind属性将端点“标记”为自定义。

答案 1 :(得分:-1)

我承认我自己还没有使用过它,但如果您使用的是WCF 4,您可以使用它的默认绑定/配置功能。请参阅http://msdn.microsoft.com/en-us/library/ee354381.aspx

上的“简化配置”部分