メッセージ キューを介したメッセージ セキュリティ
MessageSecurity サンプル では、クライアントに対して X.509v3 証明書認証で WS-Security を使用し、MSMQ 経由でサーバーの X.509v3 証明書を使用するサーバー認証を必要とするアプリケーションを実装する方法を示します。 メッセージ セキュリティは、MSMQ ストア内のメッセージが暗号化された状態を維持し、アプリケーションがメッセージの独自の認証を実行できるようにするために、より望ましい場合があります。
このサンプルは、Transacted MSMQ バインディング サンプルに基づいています。 メッセージは暗号化され、署名されます。
サンプルを設定、ビルド、実行するには
Windows Communication Foundation サンプル のOne-Time セットアップ手順を実行していることを確認します。
サービスが最初に実行される場合は、キューが存在することを確認します。 キューが存在しない場合、サービスによってキューが作成されます。 最初にサービスを実行してキューを作成することも、MSMQ キュー マネージャーを使用して作成することもできます。 Windows 2008 でキューを作成するには、次の手順に従います。
Visual Studio 2012 でサーバー マネージャーを開きます。
[機能] タブを展開します。
[プライベート メッセージ キュー] を右クリックし、[新規作成]、[プライベート キュー] の順に選択します。
[トランザクション] ボックスをオンにします。
新しいキューの名前として「
ServiceModelSamplesTransacted
」と入力します。
ソリューションの C# または Visual Basic エディションをビルドするには、「Build the Windows Communication Foundation Samplesの手順に従います。
同じコンピューターでサンプルを実行するには
パスに、Makecert.exe と FindPrivateKey.exeを含むフォルダーが含まれていることを確認します。
サンプルのインストール フォルダーから Setup.bat を実行します。 これにより、サンプルの実行に必要なすべての証明書がインストールされます。
手記
サンプルが完了したら、Cleanup.bat を実行して証明書を削除してください。 他のセキュリティ サンプルでは、同じ証明書が使用されます。
\service\bin から Service.exe を起動します。
\client\bin から Client.exe を起動します。 クライアント アクティビティがクライアント コンソール アプリケーションに表示されます。
クライアントとサービスが通信できない場合は、「WCF サンプルのトラブルシューティングのヒント」を参照してください。
複数のコンピューターでサンプルを実行するには
Setup.bat、Cleanup.bat、および ImportClientCert.bat ファイルをサービス コンピューターにコピーします。
クライアント コンピューター上にクライアント バイナリ用のディレクトリを作成します。
クライアント プログラム ファイルをクライアント コンピューター上のクライアント ディレクトリにコピーします。 また、Setup.bat、Cleanup.bat、および ImportServiceCert.bat ファイルをクライアントにコピーします。
サーバーで、
setup.bat service
実行します。service
引数を指定してsetup.bat
を実行すると、コンピューターの完全修飾ドメイン名を持つサービス証明書が作成され、サービス証明書が Service.cer という名前のファイルにエクスポートされます。サービスの <service.exe.config> を編集して、新しい証明書名 (serviceCertificate の
findValue
属性) を反映させます。これは、コンピューターの完全修飾ドメイン名と同じです。Service.cer ファイルをサービス ディレクトリからクライアント コンピューター上のクライアント ディレクトリにコピーします。
クライアントで、
setup.bat client
実行します。client
引数でsetup.bat
を実行すると、client.com という名前のクライアント証明書が作成され、クライアント証明書が Client.cer という名前のファイルにエクスポートされます。クライアント コンピューター上の Client.exe.config ファイルで、サービスの新しいアドレスと一致するようにエンドポイントのアドレス値を変更します。 これを行うには、localhost をサーバーの完全修飾ドメイン名に置き換えます。 また、サービスの証明書名を、サービス コンピューターの完全修飾ドメイン名と同じに変更する必要があります (
clientCredentials
のserviceCertificate
のdefaultCertificate
要素のfindValue
属性)。Client.cer ファイルをクライアント ディレクトリからサーバー上のサービス ディレクトリにコピーします。
クライアントで、
ImportServiceCert.bat
実行します。 これにより、Service.cer ファイルから CurrentUser - TrustedPeople ストアにサービス証明書がインポートされます。サーバーで、
ImportClientCert.bat
実行します。これにより、Client.cer ファイルから LocalMachine - TrustedPeople ストアにクライアント証明書がインポートされます。サービス コンピューターで、コマンド プロンプトから Service.exe を起動します。
クライアント コンピューターで、コマンド プロンプトから Client.exe を起動します。 クライアントとサービスが通信できない場合は、「WCF サンプルのトラブルシューティングのヒント」を参照してください。
サンプルの実行後にクリーンアップするには
サンプルの実行が完了したら、samples フォルダーで Cleanup.bat を実行します。
手記
このスクリプトは、コンピューター間でこのサンプルを実行するときに、クライアント上のサービス証明書を削除しません。 コンピューター間で証明書を使用する Windows Communication Foundation (WCF) サンプルを実行している場合は、CurrentUser - TrustedPeople ストアにインストールされているサービス証明書を必ずクリアしてください。 これを行うには、次のコマンドを使用します。
certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>
例:certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com
.
必要条件
このサンプルでは、MSMQ がインストールされ、実行されている必要があります。
対象
クライアントは、サービスの公開キーを使用してメッセージを暗号化し、独自の証明書を使用してメッセージに署名します。 キューからメッセージを読み取るサービスは、信頼されたユーザー ストア内の証明書を使用してクライアント証明書を認証します。 その後、メッセージの暗号化を解除し、サービス操作にメッセージをディスパッチします。
Windows Communication Foundation (WCF) メッセージは MSMQ メッセージの本文でペイロードとして送信されるため、本文は MSMQ ストア内で暗号化されたままになります。 これにより、メッセージが望ましくない開示から保護されます。 MSMQ 自体は、転送しているメッセージが暗号化されているかどうかを認識しないことに注意してください。
このサンプルでは、MSMQ でメッセージ レベルでの相互認証を使用する方法を示します。 証明書は帯域外で交換されます。 サービスとクライアントを同時に起動して実行する必要がないため、これは常にキューに置かれたアプリケーションの場合です。
説明
サンプル のクライアント コードとサービス コードは、Transacted MSMQ バインディング サンプルと同じですが、違いがあります。 操作コントラクトには保護レベルで注釈が付けられます。これは、メッセージに署名して暗号化する必要があることを示します。
// Define a service contract.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true, ProtectionLevel=ProtectionLevel.EncryptAndSign)]
void SubmitPurchaseOrder(PurchaseOrder po);
}
サービスとクライアントを識別するために必要なトークンを使用してメッセージをセキュリティで保護するために、App.config には資格情報が含まれています。
クライアント構成では、サービスを認証するためのサービス証明書を指定します。 信頼されたストアとして LocalMachine ストアを使用して、サービスの有効性に依存します。 また、クライアントのサービス認証用のメッセージに添付されているクライアント証明書も指定します。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesMessageSecurity"
binding="netMsmqBinding"
bindingConfiguration="messageSecurityBinding"
contract="Microsoft.ServiceModel.Samples.IOrderProcessor"
behaviorConfiguration="ClientCertificateBehavior" />
</client>
<bindings>
<netMsmqBinding>
<binding name="messageSecurityBinding">
<security mode="Message">
<message clientCredentialType="Certificate"/>
</security>
</binding>
</netMsmqBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<!--
The clientCredentials behavior allows one to define a certificate to present to a service.
A certificate is used by a client to authenticate itself to the service and provide message integrity.
This configuration references the "client.com" certificate installed during the setup instructions.
-->
<clientCredentials>
<clientCertificate findValue="client.com" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
<serviceCertificate>
<defaultCertificate findValue="localhost" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it is trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certification authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
セキュリティ モードが Message に設定され、ClientCredentialType が Certificate に設定されていることに注意してください。
サービス構成には、クライアントがサービスを認証するときに使用されるサービスの資格情報を指定するサービス動作が含まれています。 サーバー証明書のサブジェクト名は、<serviceCredentials>の findValue
属性で指定されます。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!-- Use appSetting to configure MSMQ queue name. -->
<add key="queueName" value=".\private$\ServiceModelSamplesMessageSecurity" />
</appSettings>
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.OrderProcessorService"
behaviorConfiguration="PurchaseOrderServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>
</baseAddresses>
</host>
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesMessageSecurity"
binding="netMsmqBinding"
bindingConfiguration="messageSecurityBinding"
contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
<!-- The mex endpoint is exposed at http://localhost:8000/ServiceModelSamples/service/mex. -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<netMsmqBinding>
<binding name="messageSecurityBinding">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</netMsmqBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="PurchaseOrderServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by the service to authenticate itself to its clients and to provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
-->
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
<clientCertificate>
<certificate findValue="client.com" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it is trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certification authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</clientCertificate>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
このサンプルでは、次のサンプル コードに示すように、構成を使用した認証の制御と、セキュリティ コンテキストから呼び出し元の ID を取得する方法を示します。
// Service class which implements the service contract.
// Added code to write output to the console window.
public class OrderProcessorService : IOrderProcessor
{
private string GetCallerIdentity()
{
// The client certificate is not mapped to a Windows identity by default.
// ServiceSecurityContext.PrimaryIdentity is populated based on the information
// in the certificate that the client used to authenticate itself to the service.
return ServiceSecurityContext.Current.PrimaryIdentity.Name;
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SubmitPurchaseOrder(PurchaseOrder po)
{
Console.WriteLine("Client's Identity {0} ", GetCallerIdentity());
Orders.Add(po);
Console.WriteLine("Processing {0} ", po);
}
//…
}
実行すると、サービス コードにクライアント ID が表示されます。 サービス コードからの出力例を次に示します。
The service is ready.
Press <ENTER> to terminate service.
Client's Identity CN=client.com; ECA6629A3C695D01832D77EEE836E04891DE9D3C
Processing Purchase Order: 6536e097-da96-4773-9da3-77bab4345b5d
Customer: somecustomer.com
OrderDetails
Order LineItem: 54 of Blue Widget @unit price: $29.99
Order LineItem: 890 of Red Widget @unit price: $45.89
Total cost of this order: $42461.56
Order status: Pending
コメント
クライアント証明書の作成。
バッチ ファイル内の次の行は、クライアント証明書を作成します。 指定されたクライアント名は、作成された証明書のサブジェクト名で使用されます。 証明書は、
My
ストアのCurrentUser
ストアの場所に格納されます。echo ************ echo making client cert echo ************ makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
クライアント証明書をサーバーの信頼された証明書ストアにインストールする。
バッチ ファイル内の次の行は、サーバーが関連する信頼または信頼しない決定を行うことができるように、クライアント証明書をサーバーの TrustedPeople ストアにコピーします。 TrustedPeople ストアにインストールされている証明書が Windows Communication Foundation (WCF) サービスによって信頼されるようにするには、クライアント証明書検証モードを
PeerOrChainTrust
またはPeerTrust
値に設定する必要があります。 構成ファイルを使用してこれを行う方法については、前のサービス構成サンプルを参照してください。echo ************ echo copying client cert to server's LocalMachine store echo ************ certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople
サーバー証明書の作成。
Setup.bat バッチ ファイルの次の行は、使用するサーバー証明書を作成します。
echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
%SERVER_NAME% 変数は、サーバー名を指定します。 証明書は LocalMachine ストアに格納されます。 セットアップ バッチ ファイルがサービスの引数 (
setup.bat service
など) で実行される場合、%SERVER_NAME% にはコンピューターの完全修飾ドメイン名が含まれます。 それ以外の場合は、既定で localhost になります。クライアントの信頼された証明書ストアへのサーバー証明書のインストール。
次の行は、サーバー証明書をクライアントの信頼されたユーザー ストアにコピーします。 Makecert.exe によって生成された証明書はクライアント システムによって暗黙的に信頼されないため、この手順が必要です。 クライアントの信頼されたルート証明書 (Microsoft が発行した証明書など) にルート化された証明書が既にある場合、クライアント証明書ストアにサーバー証明書を設定するこの手順は必要ありません。
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
手記
米国以外のユーザーを使用している場合Microsoft Windows の英語版では、Setup.bat ファイルを編集し、"NT AUTHORITY\NETWORK SERVICE" アカウント名を地域に相当するアカウント名に置き換える必要があります。