リモート処理の例 : インターネット インフォメーション サービス (IIS: Internet Information Services) でのホスティング

このトピックの対象は、既存のアプリケーションとの下位互換性のために残されているレガシ テクノロジに特定されています。新規の開発には、このトピックを適用しないでください。分散アプリケーションは、現在は Windows Communication Foundation (WCF) を使用して開発する必要があります。

基本の Web サービスを実装するサンプルを次に示します。このサンプルには、複雑な部分が数箇所含まれています。ペイロードを小さくし、システムによるストリームのシリアル化や逆シリアル化にかかる時間を短縮するため、BinaryFormatter が使用されます。さらに、IIS が Windows 統合認証 (NTLM 認証とも呼ばれます) を使用する場合、サーバーがクライアントを認証し、IIS が認証できた ID をクライアントに返します。最後に、クライアント構成ファイル内の URL を変更してプロトコル スキームに "https" を使用し、さらに IIS を構成して該当の仮想ディレクトリに SSL (Secure Sockets Layer) 暗号化を要求することによって、Web サービスを保護できます。

c2swb8ah.Caution(ja-jp,VS.100).gif注意 :
.NET Framework リモート処理で既定では、認証も暗号化も実行されません。したがって、クライアントやサーバーとリモートで通信する前に、それらの ID の確認に必要な手順をすべて実行することをお勧めします。.NET Framework リモート処理アプリケーションの実行には、FullTrust アクセス許可が必要です。認証されていないクライアントがサーバーへのアクセスを許可された場合は、完全な信頼を与えられていると見なされ、コードの実行が可能になってしまいます。IIS でリモート型をホストするか、リモート型をホストするためのカスタム チャネル シンク ペアを構築することによって、常にエンドポイントを認証し、通信ストリームを暗号化してください。

このサンプルをコンパイルして実行するには

  1. RemoteIIS という名前のディレクトリ内にあるすべてのファイルを保存します。

  2. コマンド プロンプトで、次のコマンドを入力してサンプル全体をコンパイルします。

    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
    
  3. \bin サブディレクトリを作成し、このディレクトリに ServiceClass.dll をコピーします。

  4. IIS でアプリケーションを作成します。アプリケーションのエイリアスを "HttpBinary" とし、ソース ディレクトリを "RemoteIIS" ディレクトリに設定します。

  5. この仮想ディレクトリの認証方法を統合 Windows 認証 (以前の NTLM 認証) に設定します。匿名アクセスを選択すると、HttpContext.Current.User.Identity.Namenull になり、GetServerString はユーザー エイリアスに "***unavailable***" を返します。これを防ぐためには、匿名アクセスの選択を解除します。

  6. IIS が開始されていることを確認します。コマンド プロンプトで "RemoteIIS" ディレクトリから「client」と入力します。

このアプリケーションは、1 台のコンピューター上で、またはネットワーク経由で実行されます。このアプリケーションをネットワーク上で実行する場合は、クライアント構成の "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>

参照

概念

リモート アプリケーションの構成
インターネット インフォメーション サービス (IIS) でのリモート オブジェクトのホスト

その他のリソース

リモート処理の例