方法 : トランスポート セキュリティを使用します。
[このドキュメントはプレビュー版であり、後のリリースで変更されることがあります。 空白のトピックは、プレースホルダーとして挿入されています。]
.NET Compact Framework Version 3.5 では、デスクトップ上の Windows Communication Foundation (WCF) サービスに接続するには、HTTPS トランスポートの使用できます。 これはサポート サーバー認証とクライアント認証しています。
ここでは、サービスの構成の例について説明し、相互認証用のクライアント コードを修正方法を示します。
注意
サーバー認証の場合のみ、クライアント証明書が必要ないです。メッセージ セキュリティの .NET Compact Framework 3.5 でもサポートされますがこの例で使用されていません。
デスクトップの WCF サービスを作成するには
作成し、サーバー証明書とクライアント証明書をインストールします。
以下の手順は、証明書の生成ツール (たとえば、Makecert.exe https://msdn.microsoft.com/ja-jp/library/bfsktky3(v=vs.100)) を使用し、このトピックの範囲を超えていますに固有です。 次のタスク必要があります。
自己署名入り証明書を作成し、名前 (たとえば、会社名を使用します。会社) です。
会社の によって署名されたサーバー証明書を作成します。 サーバー証明書名のサービスにアクセスするために使用される URL ホスト名と一致する必要があります。
会社の によって署名されたクライアント証明書を作成します。
注意
現在のユーザーにインストールではなくローカル コンピューターにサーバー証明書をインストールすることを推奨します。それ以外の場合は、サービスがインターネット インフォメーション サービス (IIS) でホストされている、現在のユーザーにインストールする場合、動作しません。
新しい Web サービス プロジェクトを作成します。
Web.config ファイルをここに示す例に置き換えます。 次の要素と、ファイル内の属性を変更します。
新しいサービスを使用しているに service name 属性を変更します。
新しい動作の名前を参照する behaviorConfiguration 属性を変更します。
サービス インターフェイスを参照するには、endpoint contract 属性を変更します。
注意
binding <endpoint> 要素の属性値が"basicHttpBinding"かを確認します。.NET Compact Framework は、テキストのエンコーディングがないバイナリ エンコーディング サポートします。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="CalculatorService" behaviorConfiguration="MyServiceTypeBehaviors"> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="transport" contract="ICalculatorService" /> <endpoint address="mex" binding="basicHttpBinding" bindingConfiguration="transport" contract="IMetadataExchange" /> </service> </services> <bindings> <basicHttpBinding> <binding name="transport"> <security mode="Transport"> <transport clientCredentialType="Certificate" /> </security> </binding> </basicHttpBinding> </bindings> <!--For debugging purposes set the includeExceptionDetailInFaults attribute to true--> <behaviors> <serviceBehaviors> <behavior name="MyServiceTypeBehaviors"> <serviceMetadata httpsGetEnabled="True" httpsGetUrl=""/> <serviceDebug includeExceptionDetailInFaults="False" /> <serviceCredentials> <clientCertificate> <authentication trustedStoreLocation="LocalMachine" revocationMode="NoCheck" certificateValidationMode="ChainTrust"/> </clientCertificate> </serviceCredentials> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
WCF サービスのソース コードで、コードから属性を ServiceContractOperationContract で指定された任意のパラメーターを削除します。
注意
このサンプルは、ServiceContractOperationContract などの契約で指定されたパラメーターのサポートを実装しません。場合パラメーター サポート コントラクトは、WCF の .NET Compact Framework ServiceModel ユーティリティ ツール (NetCFSvcUtil.exe) を使用してクライアント コードを生成することができます。このツールはこれらのパラメーターの多くのサポート、.NET Compact Framework に基づくアプリケーションにビルドします。NetCFSvcUtil.exe は .NET Compact Framework の電源社で使用できます。詳細については、Power Toy .NET Compact Framework を参照してください。
次の例を簡略化の電卓アプリケーションの WCF サービスのソース コードに示します。
<ServiceContract()> _ PublicInterface ICalculatorService <OperationContract()> _ Function Add(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDouble '<OperationContract()> _Function Subtract(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleEndInterfacePublicClass CalculatorService Implements ICalculatorService PublicFunction Add(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleImplements ICalculatorService.Add Return n1 + n2 EndFunctionPublicFunction Subtract(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleImplements ICalculatorService.Subtract Return n1 - n2 EndFunctionEndClass
[ServiceContract()] publicinterface ICalculatorService { [OperationContract] double Add(double n1, double n2); [OperationContract] double Subtract(double n1, double n2); } publicclass CalculatorService : ICalculatorService { publicdouble Add(double n1, double n2) { return n1 + n2; } publicdouble Subtract(double n1, double n2) { return n1 - n2; } }
Web サイトまたは仮想ディレクトリを作成し、Web サービス プロジェクトを参照します。 Web サーバー上には HTTPS とクライアント証明書を要求するサービス構成します。
注意
指定 IIS では、してください、サーバーの証明書とクライアントの証明書
Web サーバーを起動します。
Web サービス記述言語 (WSDL) の出力を表示し、localhost に、サービスを実行する場合は、https://localhost/CalculatorService/Service.svc?wsdl に移動します。 WCF サービスの指定した同じ Web プロジェクト名を使用します。
アクセスすることを確認することができます、ディレクトリ、デスクトップ ブラウザーと、デバイスのブラウザーから HTTPS を使用しています。
ある証明書が正しく構成されて、サービスにアクセスすることができます前に確認する必要があります。 Web サーバーを構成、WCF サービスに対する要求を処理する必要があります。
.NET Compact Framework クライアントを作成するには
サービスが実行中に、コマンドラインを開き、WCF サービスがあるディレクトリに移動します。
コマンド プロンプトで WCF ServiceModel デスクトップ ユーティリティ ツール、WCF クライアント プロキシを生成するには、(SvcUtil.exe) を実行します。 以下に、localhost のサービスがホストされている SvcUtil のコマンド ラインの呼び出しを示します。
svcutil.exe /language:c# https://localhost/CalculatorService/Service.svc
サポートされていない属性と要素を次を含む、生成されたクライアント プロキシ コードから削除します。
すべての System.ServiceModel 属性。
IClientChannel クラスへの参照。
<endpoint> 構成名への参照。
内部チャネル上で ServiceContract インターフェイスのメソッドが呼び出されるメソッドの実装。
この手順の例を「方法 : HTTP トランスポートを使用します。」を参照してください。
クライアント プロジェクトを作成します。
プロジェクトに、生成されたクライアント プロキシを追加します。
生成されたプロキシ コード、内には、ユーザー定義 ClientBase<TChannel> クラスに ClientBase への完全限定参照を変更します。
生成されたプロキシ コードで、ユーザー定義 Call クラスの ClientBase メソッドを呼び出してメソッドの実装を追加します。
Public Function Add(ByVal n1 AsDouble, ByVal n2 AsDouble) AsDoubleImplements ICalculatorService.Add Return System.Convert.ToDouble(MyBase.Call("Add", "https://fabrikam.com/CalcService/ICalculatorService/Add", NewString() {"n1", "n2"}, NewObject() {n1, n2}, GetType(Double))) EndFunction
public double Add(double n1, double n2) { return (double)base.Call("Add", "https://fabrikam.com/CalcService/ICalculatorService/Add", newstring[] { "n1", "n2" }, newobject[] { n1, n2 }, typeof(double)); }
プロジェクトにプロキシの基本クラスを追加します。 このクラスを"ClientBase"と呼びます。
ClientBase の実装を指すには、クライアント プロキシの基本クラス参照を変更します。
注意
次の使用例で CustomBodyWriterClientBase クラスは、プリミティブ型のみをサポートします。以外のプリミティブ型をサポートするには、OnWriteBodyContents メソッドを拡張です。たとえば、メッセージ データ シリアル化するカスタム シリアライザーを呼び出す可能性があります。ここでは、XML シリアライザーが消費する属性に、生成されたクライアント プロキシ内のコードの属性に変換しましょう。このシナリオでは、する必要がありますまず、次スイッチ追加 SvcUtil を実行するとします。/serializer:xmlserializer http://エンドポイント。
ClientBase クラスの例を次のコードに示します。 ClientCredentials オブジェクトは、この例では、 testuser の名前は、クライアントによって使用された X.509 証明書を指定するには使用されます。
Public Class ClientBase(Of TChannel AsClass) Private requestChannel As IRequestChannel Private messageVersion As MessageVersion PublicSubNew(ByVal binding As System.ServiceModel.Channels.Binding, ByVal remoteAddress As System.ServiceModel.EndpointAddress) 'this.remoteAddress = remoteAddress;Me.messageVersion = binding.MessageVersion Dim parameters = New System.ServiceModel.Channels.BindingParameterCollection() ' Specifies the X.509 certificate used by the client.Dim cc AsNew ClientCredentials() cc.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "testuser") parameters.Add(cc) Dim channelFactory As IChannelFactory(Of IRequestChannel) channelFactory = binding.BuildChannelFactory(Of IRequestChannel)(parameters) channelFactory.Open() Me.requestChannel = channelFactory.CreateChannel(remoteAddress) EndSubPublicFunction [Call](ByVal op AsString, ByVal action AsString, ByVal varnames() AsString, ByVal varvals() AsObject, ByVal returntype As Type) AsObject requestChannel.Open(TimeSpan.MaxValue) 'Message msg = 'Message.CreateMessage(MessageVersion.<FromBinding>, ' action, ' new CustomBodyWriter(op, varnames, varvals, '"<ns passed in from Proxy>"));Dim msg As Message = Message.CreateMessage(Me.messageVersion, action, New CustomBodyWriter(op, varnames, varvals, "<ns passed in from Proxy>")) Dim reply As Message = requestChannel.Request(msg, TimeSpan.MaxValue) Dim reader As XmlDictionaryReader = reply.GetReaderAtBodyContents() reader.ReadToFollowing(op + "Result") Return reader.ReadElementContentAs(returntype, Nothing) EndFunctionEndClassFriendClass CustomBodyWriter Inherits BodyWriter Private op AsStringPrivate varnames() AsStringPrivate varvals() AsObjectPrivate ns AsStringPublicSubNew(ByVal op AsString, ByVal varnames() AsString, ByVal varvals() AsObject, ByVal ns AsString) MyBase.New(True) Me.op = op Me.varnames = varnames Me.varvals = varvals Me.ns = ns EndSubProtectedOverridesSub OnWriteBodyContents(ByVal writer As XmlDictionaryWriter) writer.WriteStartElement(op, ns) Dim i AsIntegerFor i = 0 To varnames.Length writer.WriteElementString(varnames(i), varvals(i).ToString()) Next i writer.WriteEndElement() EndSubEndClass
public class ClientBase<TChannel> where TChannel : class { private IRequestChannel requestChannel; private MessageVersion messageVersion; public ClientBase(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) { //this.remoteAddress = remoteAddress;this.messageVersion = binding.MessageVersion; BindingParameterCollection parameters = new System.ServiceModel.Channels.BindingParameterCollection(); // Specifies the X.509 certificate used by the client. ClientCredentials cc = new ClientCredentials(); cc.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "testuser"); parameters.Add(cc); IChannelFactory<IRequestChannel> channelFactory = binding.BuildChannelFactory<IRequestChannel>( parameters); channelFactory.Open(); this.requestChannel = channelFactory.CreateChannel(remoteAddress); } publicobject Call(string op, string action, string[] varnames, object[] varvals, Type returntype) { requestChannel.Open(TimeSpan.MaxValue); //Message msg =//Message.CreateMessage(MessageVersion.<FromBinding>,// action,// new CustomBodyWriter(op, varnames, varvals,//"<ns passed in from Proxy>")); Message msg = Message.CreateMessage(this.messageVersion, action, new CustomBodyWriter(op, varnames, varvals, "<ns passed in from Proxy>")); Message reply = requestChannel.Request(msg, TimeSpan.MaxValue); XmlDictionaryReader reader = reply.GetReaderAtBodyContents(); reader.ReadToFollowing(op + "Result"); return reader.ReadElementContentAs(returntype, null); } } internalclass CustomBodyWriter : BodyWriter { privatestring op; privatestring[] varnames; privateobject[] varvals; privatestring ns; public CustomBodyWriter(string op, string[] varnames, object[] varvals, string ns) : base(true) { this.op = op; this.varnames = varnames; this.varvals = varvals; this.ns = ns; } protectedoverridevoid OnWriteBodyContents(XmlDictionaryWriter writer) { writer.WriteStartElement(op, ns); for (int i = 0; i < varnames.Length; i++) writer.WriteElementString(varnames[i], varvals[i].ToString()); writer.WriteEndElement(); } }
ClientBase.cs に次の参照を追加します。
作成し、クライアント プロキシを使用してクラスを追加します。
バインディング オブジェクトを使用して HTTPS およびクライアント証明書の認証の使用経由でトランスポートのセキュリティを指定する例を次に示します。 また、クライアント プロキシを呼び出すコードを示します。
Class Program ''' <summary> ''' The main entry point for the application. ''' </summary> <MTAThread()> _ SharedSub Main() Dim serverAddress AsString = CalculatorServiceClient.ServiceEndPoint.Uri.AbsoluteUri Dim binding AsNew BasicHttpBinding() ' Specifies transport security over HTTPS and the use of a ' client certificate for authentication. binding.Security.Mode = BasicHttpSecurityMode.Transport binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate Dim proxy = New CalculatorServiceClient(binding, New EndpointAddress(serverAddress)) MessageBox.Show("Add 3 + 6...") MessageBox.Show(proxy.Add(3, 6).ToString()) MessageBox.Show("Subtract 8 - 3...") MessageBox.Show(proxy.Subtract(8, 3).ToString()) EndSubEndClass
static class Program { /// <summary>/// The main entry point for the application./// </summary> [MTAThread] staticvoid Main() { string serverAddress = CalculatorServiceClient.ServiceEndPoint.Uri.AbsoluteUri; BasicHttpBinding binding = new BasicHttpBinding(); // Specifies transport security over HTTPS and the use of a// client certificate for authentication. binding.Security.Mode = BasicHttpSecurityMode.Transport; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; ICalculatorService proxy = new CalculatorServiceClient(binding, new EndpointAddress(serverAddress)); MessageBox.Show("Add 3 + 6..."); MessageBox.Show((proxy.Add(3, 6)).ToString()); MessageBox.Show("Subtract 8 - 3..."); MessageBox.Show((proxy.Subtract(8, 3)).ToString()); } }
クライアント証明書はデバイス上の現在のユーザーの証明書ストアに配置されていることを確認します。
クライアント アプリケーションをビルドし、デバイスに展開します。
WCF サービスが実行されていると、デバイスがネットワークに接続されている、デバイス上でクライアント アプリケーションを起動します。
コードのコンパイル方法
WCF サービスのソース コードには、次の名前空間への参照が必要です。
ClientBase クラスのソース コードには、次の名前空間への参照が必要です。
クライアント アプリケーションで Main メソッドを格納するクラスのソース コードには、次の名前空間への参照が必要です。
セキュリティ
次の使用例は、相互認証に基づくトランスポートのセキュリティを実装します。 メッセージ セキュリティを実装しません。