원격 서비스 예제: IIS에서 호스팅
이 항목은 이전 버전의 기존 응용 프로그램과의 호환성을 위해 유지되고 있으나 새로운 개발에는 권장되지 않는 레거시 기술에 대해 설명합니다. 분산 응용 프로그램은 이제 WCF(Windows Communication Foundation)를 사용하여 개발됩니다.
다음 샘플에서는 몇 가지 복잡한 사항이 있는 기본 웹 서비스를 구현합니다. 페이로드가 더 간결하고 시스템에서 스트림을 serialize 및 deserialize하는 데 걸리는 시간이 짧기 때문에 BinaryFormatter를 사용합니다. 또한 IIS(인터넷 정보 서비스)에서 Windows 통합 인증(NTLM 인증이라고도 함)을 사용하는 경우 서버가 클라이언트를 인증한 다음 IIS에서 인증할 수 있었던 ID를 클라이언트에 반환합니다. 마지막으로 "https"를 프로토콜 체계로 사용하도록 클라이언트 구성 파일의 URL을 변경하고 해당 가상 디렉터리에 SSL(Secure Sockets Layer) 암호화가 필요하도록 IIS를 구성하여 웹 서비스를 보호할 수 있습니다(이 프로세스는 샘플에 표시되지 않음).
주의: |
---|
.NET Framework Remoting에서는 기본적으로 인증 또는 암호화를 수행하지 않습니다. 따라서 원격으로 클라이언트 또는 서버와 상호 작용하기 전에 해당 클라이언트 또는 서버의 ID를 확인하는 데 필요한 모든 단계를 수행하는 것이 좋습니다. .NET Framework Remoting 응용 프로그램이 실행되려면 FullTrust 권한이 필요하기 때문에 인증되지 않은 클라이언트가 서버에 액세스할 수 있도록 허용된 경우에는 클라이언트가 완전히 신뢰된 것처럼 코드를 실행할 수 있습니다. 따라서 원격 형식을 IIS에 호스팅하거나 이 작업을 수행할 사용자 지정 채널 싱크 쌍을 작성하여 항상 끝점을 인증하고 통신 스트림을 암호화하십시오. |
이 샘플을 컴파일하고 실행하려면
모든 파일을 RemoteIIS 디렉터리에 저장합니다.
명령 프롬프트에 다음 명령을 입력하여 전체 샘플을 컴파일합니다.
vbc /t:library ServiceClass.vb vbc /r:System.Runtime.Remoting.dll /r:ServiceClass.dll Client.vb
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" 디렉터리에서 client를 입력합니다.
이 응용 프로그램은 단일 컴퓨터에서 실행되거나 네트워크에서 실행됩니다. 네트워크를 통해 이 응용 프로그램을 실행하려면 클라이언트 구성의 **"localhost"**를 원격 컴퓨터의 이름으로 바꿉니다.
ServiceClass
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
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
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
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>