远程处理示例:在 Internet 信息服务 (IIS) 中承载
下面的示例实现一个具有几点复杂之处的基本 Web 服务。使用 BinaryFormatter 的原因是有效负载更紧凑,因而系统序列化和反序列化流所花费的时间更少。此外,如果 Internet 信息服务 (IIS) 正在使用 Windows 集成身份验证(也称作 NTLM 身份验证),服务器将对客户端进行身份验证,然后将 IIS 能够验证的身份返回到客户端。最后,您还可以采用如下措施来保护 Web 服务的安全:更改客户端配置文件中的 URL 以使用“https”作为协议方案,配置 IIS 以要求对虚拟目录进行安全套接字层 (SSL) 加密(示例中没有说明这一过程)。
警告
.NET Framework 远程处理在默认情况下不进行身份验证或加密。因此,建议您在与客户端或服务器进行远程交互之前,采取任何必要的措施以确认它们的身份。因为 .NET Framework 远程处理应用程序需要 FullTrust 权限才能执行,所以,未经授权的客户端如果被授予访问您服务器的权限,该客户端就可能像完全受信任的客户端一样执行代码。应始终验证终结点的身份并将通信流加密,通过在 IIS 中承载远程类型,或者通过生成自定义信道接收对来完成这项工作。
编译和运行该示例
将所有文件保存在一个名为 RemoteIIS 的目录中。
通过在命令提示符处键入以下命令编译整个示例:
csc /noconfig /t:library /r:System.Web.dll /out:ServiceClass.dll ServiceClass.cs
csc /noconfig /r:System.Runtime.Remoting.dll /r:System.dll /r:ServiceClass.dll Client.cs
创建一个 \bin 子目录并将
ServiceClass.dll
复制到该子目录中。在 IIS 中创建一个虚拟目录。使虚拟目录的别名为“HttpBinary”,并将源目录设置为“RemoteIIS”目录。
将此虚拟目录的身份验证方法设置为集成 Windows 验证(即以前的 NTLM 身份验证)。
确保 IIS 已经启动,然后在“RemoteIIS”目录中的命令提示符处键入 client。
该应用程序可在单台计算机上运行或通过网络运行。如果要在网络上运行该应用程序,必须用远程计算机的名称替换客户端配置中的"localhost"。
ServiceClass.cs
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Threading;
using System.Web;
public interface IService{
DateTime GetServerTime();
string GetServerString();
}
// IService exists to demonstrate the possibility of publishing only the interface.
public class ServiceClass : MarshalByRefObject, IService{
private int InstanceHash;
public ServiceClass(){
InstanceHash = this.GetHashCode();
}
public DateTime GetServerTime(){
return DateTime.Now;
}
public string GetServerString(){
// Use the HttpContext to acquire what IIS thinks the client's identity is.
string temp = HttpContext.Current.User.Identity.Name;
if (temp == null || temp.Equals(string.Empty))
temp = "**unavailable**";
return "Hi there. You are being served by instance number: "
+ InstanceHash.ToString()
+ ". Your alias is: "
+ temp;
}
}
Web.config
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown
mode="SingleCall" objectUri="SAService.rem"
type="ServiceClass, ServiceClass"/>
</service>
<channels>
<channel ref="http"/>
</channels>
</application>
</system.runtime.remoting>
</configuration>
Client.cs
using System;
using System.Collections;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Security.Principal;
public class Client{
public static void Main(string[] Args){
// Tells the system about the remote object and customizes the HttpChannel
// to use the binary formatter (which understands that base64 encoding is needed).
RemotingConfiguration.Configure("Client.exe.config");
// New proxy for the ServiceClass.
// If you publish only the IService interface, you must use Activator.GetObject.
ServiceClass service = new ServiceClass();
// Programmatically customizes the properties given to the channel. This sample uses the
// application configuration file.
// IDictionary Props = ChannelServices.GetChannelSinkProperties(service);
// Props["credentials"] = CredentialCache.DefaultCredentials;
// Reports the client identity name.
Console.WriteLine("ConsoleIdentity: " + WindowsIdentity.GetCurrent().Name);
// Writes what the server returned.
Console.WriteLine("The server says : " + service.GetServerString());
Console.WriteLine("Server time is: " + service.GetServerTime());
}
}
Client.exe.config
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="http" useDefaultCredentials="true" port="0">
<clientProviders>
<formatter
ref="binary"
/>
</clientProviders>
</channel>
</channels>
<client>
<wellknown
url="https://localhost:80/HttpBinary/SAService.rem"
type="ServiceClass, ServiceClass"
/>
</client>
</application>
</system.runtime.remoting>
</configuration>
请参见
概念
远程应用程序的配置
在 Internet 信息服务 (IIS) 中承载远程对象