在 Internet 信息服务 (IIS) 中承载远程对象

由于宿主应用程序域是由 IIS 和 ASP.NET 创建的,因此当您使用 Internet 信息服务 (IIS) 承载远程类型时,不能以编程方式在宿主进程中直接为可远程处理的类型配置远程处理系统。但是,您可以使用 Global.asax 文件来执行可以在其他类型的应用程序域中执行的大量相同编程配置。要在宿主进程为 IIS 时使用配置文件来配置远程处理,必须执行以下操作:

  • 将配置信息放置在您选择使用的 IIS 虚拟目录的 Web.config 文件中。

  • 将可远程处理的类型实现放置在 \bin 目录中,或使用全局程序集缓存工具 (Gacutil.exe) 将其放置在全局程序集缓存中。

此外,您不能执行以下任何操作:

  • 在 IIS 中承载时指定应用程序名。虚拟目录的名称将成为您的应用程序名。

  • 在用于 .NET 远程处理配置的 Web.config 文件中使用 <debug> 元素。

  • 使用 HttpChannel 之外的任何信道。

  • 使用 Web.config 文件和 <client> 元素自动配置客户端 Web 应用程序。如果要使用 IIS 作为远程处理客户端,则必须在 Global.asax 文件中调用 Application_Start 方法中的 RemotingConfiguration.Configure

用于远程处理的配置文件仍将包含系统需要知道的关于类型的基本信息,但必须稍微更改某些声明以适应宿主环境。例如,可以自定义配置特定 HttpChannel,但不应指定该信道的端口;假如 ASP.NET 创建另一个应用程序域来处理负载,远程处理配置将导致这个新的应用程序域尝试再次在同一个端口上侦听,从而引发异常。例如,IIS 承载的 .NET 远程处理 XML Web 服务的简单 Web.config 文件可能与下面的代码示例相似。请记住,在这种情况下,除了将信道属性(此例中为 priority 属性)附加到所用的实例外,不必包含信道配置行。

<configuration>
   <system.runtime.remoting>
      <application>
         <service>
            <wellknown 
               mode="Singleton" 
               type="ServiceClass, ServiceClassAssemblyName"
                objectUri="ServiceClass.rem"
            />
         </service>
         <channels>
            <channel 
               name="MyChannel" 
               priority="100" 
               ref="http"
            />
         </channels>
      </application>
   </system.runtime.remoting>
</configuration>

备注

不要为此处列出的任何信道指定端口。如果您需要应用程序在特定端口上侦听,请使用 Internet 服务管理器指定 IIS 在该端口上侦听。所配置的信道将自动用于处理在该端口提交的远程请求。

要成功将服务器激活的(即 <wellknown>)对象承载在 IIS 内,必须拥有以 .rem 或 .soap 结尾的对象统一资源标识符 (URI)。(对于其他宿主应用程序域,没有这样的要求。)要使用 Soapsuds 工具 (Soapsuds.exe) 为在 IIS 中承载的服务器激活对象生成元数据,要作为参数传递给 Soapsuds.exe 的 URL 应如下所示:

http://<Computer>:<Port>/<VirtDir>/<ObjectURI>?wsdl

对于在 IIS 或任何其他应用程序域中承载的客户端激活的对象,不需要任何格式的对象 URI。要作为参数传递给 Soapsuds.exe 的 URL 如下所示:

http://<Computer>:<Port>/<VirtDir>/RemoteApplicationMetadata.rem?wsdl

IIS 中的编程配置是使用 Global.asax 页完成的。下面的示例显示与上面所示的配置文件相同的配置,但是使用了 Global.asax 文件。

Sub Application_Start()
   Dim props = New Hashtable() As IDictionary
   props("name") = "MyChannel" 
   props("priority") = "100" 
   ' Nothing entries specify the default formatters.
   Dim channel As New HttpChannel( _
      props, _
      Nothing, _
      Nothing _
   )
   ChannelServices.RegisterChannel(channel)
   Dim WKSTE As New WellKnownServiceTypeEntry( _
      GetType(ServiceClass), _
      "HttpService", _
      WellKnownObjectMode.SingleCall
   )
   RemotingConfiguration.RegisterWellKnownServiceType(WKSTE)
End Sub
void Application_Start(){
   IDictionary props = new Hashtable();
   props["name"] = "MyChannel";
   props["priority"] = "100";
   // Null entries specify the default formatters.
   HttpChannel channel = new HttpChannel(
      props, 
      null, 
      null
   );
   ChannelServices.RegisterChannel(channel);
   WellKnownServiceTypeEntry WKSTE = new WellKnownServiceTypeEntry(
      typeof(ServiceClass),
      "HttpService", 
      WellKnownObjectMode.SingleCall
   );
   RemotingConfiguration.RegisterWellKnownServiceType(WKSTE);
} 

换言之,可以采用与在其他类型的宿主应用程序域中承载服务相同的方式在 IIS 中承载服务。有关完整示例,请参见远程处理示例:在 Internet 信息服务 (IIS) 中承载

将 SSL 证书用于 .NET 远程处理

证书标识特定的计算机,该计算机的名称位于证书的公用名称中。但是,很容易更改计算机的名称或使用客户端配置文件中的“localhost”,这会在客户端和服务器证书中的公用名称之间造成不匹配的情况。在 .NET Framework 1.0 版中,这一不匹配的情况将被忽略,并且将在服务器上引发调用。

从 .NET Framework 1.1 版开始,这一不匹配的情况会引发以下异常:“System.Net.WebException:基础连接已经关闭:无法与远程服务器建立信任关系”。如果您无法将远程处理客户端配置为使用证书公用名称,则可以在客户端应用程序配置文件中使用以下设置重写这一不匹配的情况。

<system.net>
   <settings>
      <servicePointManager
         checkCertificateName="true"
      />
   </settings>
</system.net>

要以编程方式使客户端忽略证书名称不匹配,客户端必须创建一个特定类的实例,该类将实现 ICertificatePolicy 接口,并实现 CheckValidationResult,以便在 certificateProblem 值为 0x800c010f 时返回 true。然后,您必须将该对象注册到 System.Net.ServicePointManager 对象,方法是将该对象传递到 ServicePointManager.CertificatePolicy 属性。以下代码是基本的实现。

Public Class MyPolicy Implements ICertificatePolicy 
   Public Function CheckValidationResult(srvPoint As ServicePoint, certificate As X509Certificate, request As WebRequest, certificateProblem As Integer) As Boolean
      ' Check for policy common name mismatch. 
       If certificateProblem = 0 Or certificateProblem = &H800b010f Then
         Return True
      Else
         Return False
      EndIf
   End Function
End Class
public class MyPolicy : ICertificatePolicy {
   public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) {
      // Check for policy common name mismatch. 
      if (certificateProblem == 0 || certificateProblem == 0x800b010f)
         return true;
      else
         return false; 
   }
}

以下代码将前面的类的实例注册到 System.Net ServicePointManager。

System.Net.ServicePointManager.CertificatePolicy = New MyPolicy()
System.Net.ServicePointManager.CertificatePolicy = new MyPolicy();

IIS 承载的远程处理应用程序中的身份验证

下表描述了一些配置设置,它们将在 Internet 信息服务 (IIS) 中承载服务时启用 .NET 远程处理中某些类型的身份验证行为。

所需行为 配置设置 注释

服务器在每次调用时使用客户端的默认凭据对客户端进行身份验证。

在服务器上,在 IIS 中选择“集成 Windows 身份验证”并清除“匿名访问”。

在客户端上,设置“凭据”以使用 CredentialCache.DefaultCredentials

当 useDefaultCredentials 为 true 时,它是 .NET Framework 1.0 版中的默认行为。

如果 useAuthenticatedConnectionSharing 也设置为 false,.NET Framework 1.1 版中将支持此行为。

服务器使用客户端的默认凭据对客户端执行一次身份验证;来自此客户端的后续调用将使用先前经过身份验证的连接。

在服务器上,在 IIS 中选择“集成 Windows 身份验证”并清除“匿名访问”。

在客户端上,将 useDefaultCredentials 设置为 true。

此行为仅在 .NET Framework 1.1 版或更高版本中受支持。

服务器使用自定义或显式客户端凭据对客户端执行一次身份验证;来自此客户端的后续调用将使用先前经过身份验证的连接。

在服务器上,在 IIS 中选择“集成 Windows 身份验证”并清除“匿名访问”。

在客户端上,将 credentials 设置为 ICredentials 实现,或者将 username、password 和 domain 设置为显式值。在任何一种情况下,还必须将 unsafeAuthenticatedConnectionSharing 设置为 true,并提供一个 connectionGroupName 值,该值仅映射到一个经过身份验证的用户。

此行为仅在 .NET Framework 1.1 版或更高版本中受支持。

请参见

参考

远程处理设置架构

概念

激活 URL
远程应用程序的配置
远程处理示例:在 Internet 信息服务 (IIS) 中承载