如何:在企业中锁定终结点

大企业往往要求开发的应用程序符合企业安全策略。 下面的主题讨论如何开发和安装可用于验证安装在计算机上的所有 Windows Communication Foundation (WCF) 客户端应用程序的客户端终结点验证程序。

在这种情况下,该验证程序为客户端验证程序,因为此终结点行为已添加到 machine.config 文件中的客户端 <commonBehaviors> 一节。 WCF 仅为客户端应用程序加载常见终结点行为,并仅为服务应用程序加载常见服务行为。 若要为服务应用程序安装此相同验证程序,验证程序必须为服务行为。 有关详细信息,请参阅 <commonBehaviors> 一节。

重要

应用程序在部分信任环境中运行时,如果服务或终结点行为未使用 AllowPartiallyTrustedCallersAttribute 属性 (APTCA) 进行标记且被添加到配置文件的 <commonBehaviors> 一节,则不会运行这些服务或终结点行为,并且在这种情况下不会引发任何异常。 若要强制运行公共行为(如验证程序),必须执行以下任一操作:

  • 使用 AllowPartiallyTrustedCallersAttribute 属性标记常见行为,以便该行为在作为部分信任应用程序进行部署时可以运行。 请注意,可以在计算机上设置注册表项,以防运行标有 APTCA 的程序集。

  • 确保如果应用程序是作为完全受信任的应用程序部署的,则用户不能修改代码访问安全设置,从而无法在部分信任环境中运行该应用程序。 如果用户可以这样做,则自定义验证程序不会运行,且不引发任何异常。 有关确保这一点的一种方法,请参阅 levelfinal 选项(使用代码访问安全策略工具 (Caspol.exe))。

有关详细信息,请参阅部分信任最佳做法支持的部署方案

创建终结点验证程序

  1. 使用 IEndpointBehavior 方法中所需的验证步骤创建一个 Validate。 以下代码是一个示例。 (InternetClientValidatorBehavior 取自安全验证示例。)

    public class InternetClientValidatorBehavior : IEndpointBehavior
    {
        public void AddBindingParameters(ServiceEndpoint serviceEndpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { }
        public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, System.ServiceModel.Dispatcher.ClientRuntime behavior) { }
        public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { }
    
        public void Validate(ServiceEndpoint endpoint)
        {
            BindingElementCollection elements = endpoint.Binding.CreateBindingElements();
    
            if (EndpointIsDual(endpoint, elements))
                throw new InvalidOperationException("InternetClientValidator: endpoint uses 'dual' mode. This mode is disallowed for use with untrusted services.");
    
            if (EndpointAllowsNtlm(endpoint, elements))
                throw new InvalidOperationException("InternetClientValidator: endpoint allows NTLM. This mode is disallowed for use with untrusted services.");
    
            if (EndpointAllowsTransactionFlow(endpoint, elements))
                throw new InvalidOperationException("InternetClientValidator: endpoint flows transaction ids. This mode is disallowed for use with untrusted services.");
        }
    
  2. 创建用于注册步骤 1 中创建的终结点验证程序的新 BehaviorExtensionElement。 下面的代码示例演示了此过程。 (此示例的原始代码位于安全验证示例中。)

    public class InternetClientValidatorElement : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get { return typeof(InternetClientValidatorBehavior); }
        }
    
        protected override object CreateBehavior()
        {
            return new InternetClientValidatorBehavior();
        }
    }
    
  3. 确保用强名称对编译的程序集签名。 有关详细信息,请参阅强名称工具 (SN.EXE) 和适用于所用语言的编译器命令。

将验证程序安装到目标计算机中

  1. 使用恰当的机制安装终结点验证程序。 在企业中,可以使用组策略和 Systems Management Server (SMS)。

  2. 使用 Gacutil.exe(全局程序集缓存工具)将强名称程序集安装到全局程序集缓存中。

  3. 使用 System.Configuration 命名空间类型执行以下操作:

    1. 使用完全限定的类型名将扩展添加到 <behaviorExtensions> 一节并锁定该元素。

      // Register our validator configuration element.
      ExtensionsSection extensions
        = machine.GetSection(@"system.serviceModel/extensions") as ExtensionsSection;
      if (extensions == null)
        throw new Exception("not extensions section.");
      ExtensionElement validator
        = new ExtensionElement(
          "internetClientValidator",
          "Microsoft.ServiceModel.Samples.InternetClientValidatorElement, InternetClientValidator, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
        );
      validator.LockItem = true;
      if (extensions.BehaviorExtensions.IndexOf(validator) < 0)
        extensions.BehaviorExtensions.Add(validator);
      
    2. 将行为元素添加到 <commonBehaviors> 一节的 EndpointBehaviors 属性并锁定该元素。 (要在服务上安装验证程序,则该验证程序必须是 IServiceBehavior,并已添加到 ServiceBehaviors 属性。)下面的代码示例演示执行步骤 a. 和步骤 b. 后的正确配置,唯一的例外是没有强名称。

      // Add a new section for our validator and lock it down.
      // Behaviors for client applications must be endpoint behaviors.
      // Behaviors for service applications must be service behaviors.
      CommonBehaviorsSection commonBehaviors
        = machine.GetSection(@"system.serviceModel/commonBehaviors") as CommonBehaviorsSection;
      InternetClientValidatorElement internetValidator = new InternetClientValidatorElement();
      internetValidator.LockItem = true;
      commonBehaviors.EndpointBehaviors.Add(internetValidator);
      
    3. 保存 machine.config 文件。 下面的代码示例执行步骤 3 中的所有任务,但在本地保存已修改的 machine.config 文件的副本。

      // Write to disk.
      machine.SaveAs("newMachine.config");
      
      // Write our new information.
      SectionInformation cBInfo = commonBehaviors.SectionInformation;
      Console.WriteLine(cBInfo.GetRawXml());
      Console.WriteLine(extensions.SectionInformation.GetRawXml());
      Console.Read();
      

示例

下面的代码示例演示如何将公共行为添加到 machine.config 文件并将副本保存到磁盘。 InternetClientValidatorBehavior 取自安全验证示例。

Configuration machine = ConfigurationManager.OpenMachineConfiguration();
// Register our validator configuration element.
ExtensionsSection extensions
  = machine.GetSection(@"system.serviceModel/extensions") as ExtensionsSection;
if (extensions == null)
  throw new Exception("not extensions section.");
ExtensionElement validator
  = new ExtensionElement(
    "internetClientValidator",
    "Microsoft.ServiceModel.Samples.InternetClientValidatorElement, InternetClientValidator, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
  );
validator.LockItem = true;
if (extensions.BehaviorExtensions.IndexOf(validator) < 0)
  extensions.BehaviorExtensions.Add(validator);

// Add a new section for our validator and lock it down.
// Behaviors for client applications must be endpoint behaviors.
// Behaviors for service applications must be service behaviors.
CommonBehaviorsSection commonBehaviors
  = machine.GetSection(@"system.serviceModel/commonBehaviors") as CommonBehaviorsSection;
InternetClientValidatorElement internetValidator = new InternetClientValidatorElement();
internetValidator.LockItem = true;
commonBehaviors.EndpointBehaviors.Add(internetValidator);
// Write to disk.
machine.SaveAs("newMachine.config");

// Write our new information.
SectionInformation cBInfo = commonBehaviors.SectionInformation;
Console.WriteLine(cBInfo.GetRawXml());
Console.WriteLine(extensions.SectionInformation.GetRawXml());
Console.Read();

.NET Framework 安全性

您可能还需要对配置文件元素进行加密。 有关更多信息,请参见“另请参见”部分。

请参阅