BasicHttpBinding.Security.ModeはデフォルトではBasicHttpSecurityMode.Noneとなり、通信データが保護されません。WS-IやASP.NET Web Serviceと互換性を維持してデータを保護するために、https(ssl)を使用します。

動作環境は次のとおり

  • Windows Vista Enterprise(スタンドアロン:WCFサービス,WCFクライアントが同一OS上)
  • 開発環境 Visual Studio 2008 Professional
  • .NET 3.5

1.ソリューションの作成

Visual Studio 上で新規に空のソリューションを作成します。仮にWCFSample009とします。次に、WCFサンプル再作成(ブラッシュアップ) で作成した下記3つのプロジェクトをWCFSample009のソリューションフォルダ直下にコピーし、WCFSample009に既存のプロジェクトとして追加します。

  • WCFSample.ConsoleClient
  • WCFSample.ProductService
  • WCFSample.WPFHost

ソリューションを右クリック→[Properties]を選択し、表示されたダイアログのMultiple Startup projectsにWCFSample.ConsoleClient,WCFSample.WPFHostのActionをStartにセットします。

2.WCFホストのTransportセキュリティの設定

WCFSample.WPHHostのApp.configをService Configuration Editorで編集します。
Service Configuration Editorno左側のペインのBindingsを右クリック→[New Binding Configuration..]を選択します。選択後、表示されるダイアログにbasicHttpBindingを選択し、
右側のペインのBindingタブのNameプロパティをProductServiceBasicHttpBindingにセットします。Securityタブを選択して、ModeをNoneからTransportに変更します。

 

 

続いて、左側のペインの[Services]→[WCFSample.ProductService.ProductService]→[Endpoints]と展開し、(Empty Name)を選択、右側ペインのBindingConfigurationをProductServiceBasicHttpBindingにセット,Addressのプロトコル,ポートをhttpからhttps,8056から8057に変更(http://..:8056/..からhttps://..:8057/..に変更)します。

 

 

上書き保存を行い、Service Configuration Editorを閉じます。

3.WCFクライアントのTransportセキュリティ設定

WCFSample.ConsoleClientのApp.configをService Configuration Editorで編集します。Service Configuration Editorの左側ペインのBindingsを展開、BasicHttpBinding_ProductServiceを選択します。右側ペインのSecurityタブを選択し、ModeをNoneからTransportに変更します(下図参照)。

 

 

続いて、左側ペインの[Client]→[Endpoints]を展開BasicHttpBinding_ProductServiceを選択して、右側ペインのBindingConfigurationがBasicHttpBinding_ProductServiceであることを確認します。addressのプロトコルをhttpからhttpsにポートを8056から8057に変更し上書き保存します。

 

 

4.httpsで使用するポートのアクセス許可の設定

Vistaの場合、http,httpsで使用するポートのアクセス許可を指定する必要があります。確認環境はVistaなので、Windows Server 2003等でも必要かもしれません(その場合はhttpcfg.exeを使用すると思います。コマンドプロンプトをAdministrator権限(run as)で実行してコマンドを入力します。以下のコマンドではhttps通信でポートを8057使用することをuserで指定したユーザに許可しています。コマンドの詳細はヘルプで確認して下さい。

netsh http add urlacl url=https://+:8057/ProductService user=マシン名\ユーザ名

この状況で実行でソリューションを実行すると、クライアントでエラーが発生します。

5.SSL用の証明書の作成とポートへのバインディング

[スタートメニュー]→[All Programs]→[Microsoft Windows SDK]と展開し、CMD ShellをAdministratorとして起動します(Vistaの場合CMD Shellのアイコンを右クリックしてRun as Administratorで実行)。
次のコマンドを入力します。makecertの使い方はオンラインヘルプ参照。

makecert -sr LocalMachine -ss My -n CN=HTTPS-TestServer -sky exchange -sk HTTPS-Key

 

 

[スタートメニュー]→[Run..]でファイル名を指定して実行ダイアル後を開き、mmcと入力します。マイクロソフト管理コンソールが表示されるので、FileメニューのAdd/Removeスナップインを選択、Certificateスナップインを追加します。このとき、証明書のアカウントを選択するダイアログが表示されるので、Computer Accountを選択して[Next]ボタン選択。

 

 

つぎの画面でローカルマシンを選択してFinishボタンクリック。

 

 

スナップインが追加されるので、OKボタンをクリックして、ダイアログを閉じます。

 

 

追加されたスナップインで、[Certificates]→[Personal]→[Certificates]と展開して作成した証明書が表示されることを確認します。

 

 

作成したHTTP-TestServerをダブルクリックし、Certificateダイアログを表示し、Detailsタブを選択ThumbprintのField値を覚えておきます。
下の図では4e b1 36 c9 e9 c7 56 19 dd 38 7d ed f3 7c dd d3 d0 b1 13 98が覚えておくサムプリントです。

 

 

スナップインを閉じます。

つぎに、httpsで使用するポートと、証明書のサムプリントを関連付けます。

Vistaの場合は次のコマンドを入力します。certhashは先ほど確認した証明書のサムプリントです。appidは適当に作成したGUIDです。0.0.0.0はどのアドレスでも関連付けた証明書を使用すて通信することを意味しています。GUIDの生成はいろいろな方法があると思いますが、今回はSQL Server Management Studioのクエリウィンドウからselect newid()を実行して作成しました。

netsh http add sslcert ipport=0.0.0.0:8057 certhash=4eb136c9e9c75619dd387dedf37cddd3d0b11398 appid={4DB5A238-7C90-4D5A-9C45-BBF164BCAEB1}

 

 

Vista以外(Windows Server 2003, XP)の場合は実記で確認していませんが、次のように入力します。

httpcfg set ssl -i 0.0.0.0:8057 -h 4eb136c9e9c75619dd387dedf37cddd3d0b11398

便利リンク
XP, Windows Server 2003の場合はnetsh httpコマンドではなく、OSのサポートツールに含まれるhttpcfg.exeで行います。
Windows Server 2003のサポートツールは次のURLから取得できます。
http://www.microsoft.com/downloads/details.aspx?FamilyId=6EC50B78-8BE1-4E81-B3BE-4E7AC4F0912D&displaylang=en
Windows XP SP2のサポートツールは次のURLから取得できます。
http://www.microsoft.com/downloads/details.aspx?amp;displaylang=en&familyid=49ae8576-9bb9-4126-9761-ba8011fabf38&displaylang=en

WCFのhttp,httpsの構成の参考URLはこちら
http://msdn.microsoft.com/ja-jp/library/ms733768.aspx
http://msdn.microsoft.com/ja-jp/library/ms733791.aspx

netsh のhttp用のコンフィグコマンドのヘルプはこちら
http://www.microsoft.com/japan/technet/windowsserver/2008/library/3ad99bcf-80dc-4280-8d89-5a6a0b8846cd.mspx?mfr=true

以上で関連付けが完了しました。が、今回作成された証明書は信頼された認証機関から作成された証明書ではないので、このまま通信を行うと、クライアント側で証明書が信頼されていないために例外が発生します。そこで、クライアントプログラムに一部変更を加えます。

6.クライアントプログラムの修正

次のクラスをWPFSample.ConsoleClientプロジェクト内に作成し、証明書に問題がある場合は、処理続行の確認をおこない、OKの場合(yが入力された場合)処理が続行されるようにします。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WCFSample.Client.Proxy;
using System.Net.Security;
using System.Net;
using System.Security.Cryptography.X509Certificates;

namespace WCFSample.ConsoleClient
{
    /// <summary>
    /// 証明書に問題がある場合は確認するポリシークラス
     /// </summary>
    class ConfirmCertificatePolicy
    {
        public ConfirmCertificatePolicy()
        {
            ServicePointManager.ServerCertificateValidationCallback += RemoteCertValidation;
        }
        bool RemoteCertValidation(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
        {
            if (error != SslPolicyErrors.None)
            {
                Console.WriteLine("証明書に問題があります。理由:" + chain.ChainStatus[0].StatusInformation);
                Console.Write("処理を続行しますか? y:続行:");
                string input = Console.ReadLine();
                if (input.ToLower() == "y")
                    return true;
                else
                    return false;
            }
            return true;
        }
    }
}

Program.csのMainメソッドの先頭にConfirmCertificatePolicyを追加するコードを追加します。

Program.csの一部

class Program
    {
        static void Main(string[] args)
        {
           // 一文追加
             ConfirmCertificatePolicy p = new ConfirmCertificatePolicy(); 
           System.Console.WriteLine("WCFサービスホストを起動したら、キーを入力して下さい。");
           System.Console.ReadLine();
           ...

今回の修正は開発環境でhttpsの確認を行うためのものです。製品環境では信頼された証明機関で証明書を発行してもらい、その証明書を使用するようにして下さい。

7.動作確認

ソリューションをデバッグ実行します。WCFホストを開始後、クライアントのコンソールにEnterを入力すると、処理続行の確認メッセージが表示されます。

 

 

yを入力してEnterキーを押すと、処理が続行され、プログラムの実行が成功します。

以上です。間違い等がありましたら、ご指摘下さい。