远程处理示例:在 Internet 信息服务 (IIS) 中承载
下面的示例实现稍微复杂一些的基本 Web 服务。要使用 BinaryFormatter,因为这样负载更小,并且系统在序列化和反序列化流时所需的时间最少。此外,如果 Internet 信息服务 (IIS) 正在使用 Windows 集成身份验证(也称为 NTLM 身份验证),服务器将对客户端进行身份验证,然后将 IIS 能够进行身份验证的身份返回给客户端。最后,您可以通过以下方式帮助保护您的 Web 服务:在客户端配置文件中更改 URL 以使用“https”作为协议方案,并配置 IIS 对该虚拟目录要求安全套接字层 (SSL) 加密(示例没有演示这个过程)。
警告: |
---|
.NET Framework 远程处理在默认情况下不进行身份验证或加密。因此,在与客户端或服务器进行远程交互之前,建议您先执行所有必要的步骤来确认它们的身份。由于 .NET Framework 远程处理应用程序需要 FullTrust 权限才能执行,因此未经授权的客户端一旦获得服务器的访问权限,它就可以像完全受信任的客户端那样执行代码。应始终验证终结点的身份并对通信流加密,通过在 IIS 中承载远程类型,或者通过生成自定义信道接收器对,可以完成这项工作。 |
编译和运行此示例
将所有文件保存在名为 RemoteIIS 的目录中。
通过在命令提示符处键入下列命令来编译整个示例:
[Visual Basic]
vbc /t:library ServiceClass.vb vbc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll Client.vb
[C#]
csc /t:library ServiceClass.cs csc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll Client.cs
创建 \bin 子目录,并将
ServiceClass.dll
复制到该目录中。在 IIS 中创建一个应用程序。.将该应用程序的别名命名为“HttpBinary”,并将源目录设置为“RemoteIIS”目录。
将此虚拟目录的身份验证方法设置为集成 Windows 身份验证(以前的 NTLM 身份验证)。如果选择了匿名访问,
HttpContext.Current.User.Identity.Name
将是 null 并且GetServerString
将返回"***unavailable***"
作为用户的别名。为了避免这一情况的发生,请取消选择匿名访问。确保启动了 IIS,在“RemoteIIS”目录中的命令提示符处,键入客户端。
此应用程序可以在一台计算机上运行,也可以在网络上运行。如果要在网络上运行此应用程序,必须用远程计算机的名称替换客户端配置中的“localhost”。
ServiceClass
[Visual Basic]
Imports System
Imports System.Runtime.Remoting
Imports System.Web
Public Interface IService
Function GetServerTime() As DateTime
Function GetServerString() As String
End Interface
Public Class ServiceClass
Inherits MarshalByRefObject
Implements IService
Private InstanceHash As Integer
Public Sub New()
InstanceHash = Me.GetHashCode()
End Sub
Public Function GetServerTime() As Date Implements IService.GetServerTime
Return DateTime.Now
End Function
Public Function GetServerString() As String Implements IService.GetServerString
' Use the HttpContext to acquire what IIS thinks the client's identity is.
Dim temp As String = HttpContext.Current.User.Identity.Name
If (temp Is Nothing Or temp.Equals(String.Empty)) Then
temp = "**unavailable**"
End If
Return "Hi there. You are being served by instance number: " _
& InstanceHash.ToString() _
& ". Your alias is: " _
& temp
End Function
End Class
[C#]
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>
客户端
[Visual Basic]
Imports System
Imports System.Collections
Imports System.Net
Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Security.Principal
Public Class Client
Public Shared Sub Main()
' 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", False)
' New proxy for the ServiceClass.
' If you publish only the IService interface, you must use Activator.GetObject.
Dim service As ServiceClass = New ServiceClass()
' Programmatically customizes the properties given to the channel. This sample uses the
' application configuration file.
Dim Props As IDictionary = ChannelServices.GetChannelSinkProperties(service)
Props.Item("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())
End Sub
End Class
[C#]
using System;
using System.Collections;
using System.Net;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Security.Principal;
class Client
{
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", false);
// 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
<?xml version="1.0" encoding="utf-8" ?>
<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) 中承载远程对象
其他资源
版权所有 (C) 2007 Microsoft Corporation。保留所有权利。