4

最終的には IoT 向けの UWP アプリを C# で作成していますが、現在はローカルでデバッグするだけです。Windows.Web.Http.HttpClientテスト用に同じマシンでコンソールアプリとして作成し、実行している自己ホスト型の WCF REST Web サービスに接続するために使用しています。サービスには証明書による相互認証が必要なので、CA 証明書、サービス証明書、およびクライアント証明書を持っています。

私の UWP コードは次のように動作します。

  1. クライアント証明書と CA 証明書がインストールされているかどうか、アプリ証明書ストアを確認します。
  2. そうでない場合は、それぞれ PFX ファイルと CER ファイルからインストールします。
  3. を に取り付け、フィルターを に追加しますCertificateHttpBaseProtocolFilterHttpClient
  4. 電話するHttpClient.PostAsync

電話した後PostAsync、次のエラーが表示されますAn Error Occurred in the Secure Channel Support。オンラインで十分な検索を行った後、常識的にHttpClient、相互認証された SSL 接続を確立する際の問題が原因で、バーフィングしていると確信しています。しかし、私のトラブルシューティングに基づいて、理由がわかりません。

さらにトラブルシューティングを行うために、 を使用して単純な古いコンソール アプリを作成しSystem.Net.Http.HttpClient、クライアント証明書をリクエストに添付すると、すべてがうまく機能します。残念ながら、System.NetUWP では完全にはサポートされていません。また、証明書を UWP にアタッチしないことも試みましたがHttpClient、アプリは UI でインストール済みの証明書を選択するように求めてきました。正しい証明書を選択しても、同じ例外が発生します (これにより、少なくとも証明書が正しくインストールされ、アプリの観点から CA で適切に検証されていることがわかります)。さらに、ブラウザから Web サービスで GET を押し、プロンプトが表示されたらクライアント証明書を選択し、ファイルをダウンロードできます。

私は Fiddler を使用してみましたが、トラフィックをプロキシする方法のために、Web サービスが要求を禁止として拒否することを除いて、もう少しうまくいくようです (おそらく、Fiddler が要求に正しいクライアント証明書を含めていないため) )。Windows で localhost を使用して Wireshark を動作させるのは面倒なので、まだ Wireshark にアクセスしていません。

私の次のステップは、クライアント認証を必要としないように Web サービスの変更を開始し、それが問題かどうかを確認することです。

2 つの質問:Windows.Web.Http.HttClientこの場合、なぜ機能しないのですか? そして、それほど重要ではありませんが、これをさらにデバッグするのに役立つ優れた HTTP 監視ツールに関する推奨事項はありますか?

4

2 に答える 2

3

この MSDN の投稿に答えがあることがわかりました。事前にAPIへの別の無意味な呼び出しを必要とするMS側の見落としのようです。しかたがない。

http://blogs.msdn.com/b/wsdevsol/archive/2015/03/26/how-to-use-a-shared-user-certificate-for-https-authentication-in-an-enterprise-application. aspx

記事からの抜粋:

ただし、セキュリティ サブシステムでは、共有ユーザー証明書ストアに格納されている証明書の秘密鍵へのアクセスを許可する前に、ユーザーの確認が必要です。さらに複雑なことに、クライアント証明書がコードで指定されている場合、下位レベルのネットワーク機能は、アプリケーションが既にこれを処理していると想定し、ユーザーに確認を求めません。

証明書に関連する Windows ランタイム クラスを見ると、証明書の秘密キーへのアクセスを明示的に要求する方法が見つからないため、アプリ開発者はどうすればよいでしょうか?

解決策は、選択した証明書を使用して小さなデータに「署名」することです。アプリケーションが CryptographicEngine.SignAsync を呼び出すと、基になるコードが秘密キーへのアクセスを要求して署名を行います。この時点で、ユーザーはアプリケーションが証明書の秘密キーにアクセスできるようにするかどうかを尋ねられます。関数の同期バージョン: Sign は、確認ダイアログの表示をブロックするオプションを使用するため、この関数の「非同期」バージョンを呼び出す必要があることに注意してください。

例えば:

public static async Task<bool> VerifyCertificateKeyAccess(Certificate selectedCertificate)
{
    bool VerifyResult = false;  // default to access failure
    CryptographicKey keyPair = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(
                                        selectedCertificate, HashAlgorithmNames.Sha1, 
                                        CryptographicPadding.RsaPkcs1V15);
    String buffer = "Data to sign";
    IBuffer Data = CryptographicBuffer.ConvertStringToBinary(buffer, BinaryStringEncoding.Utf16BE);

    try
    {
        //sign the data by using the key
        IBuffer Signed = await CryptographicEngine.SignAsync(keyPair, Data);
        VerifyResult = CryptographicEngine.VerifySignature(keyPair, Data, Signed);
    }
    catch (Exception exp)
    {
        System.Diagnostics.Debug.WriteLine("Verification Failed. Exception Occurred : {0}", exp.Message);
        // default result is false so drop through to exit.
    }

    return VerifyResult;
}

その後、クライアント証明書を使用する前にこの関数を呼び出すように前のコード例を変更して、アプリケーションが証明書の秘密キーにアクセスできるようにすることができます。

于 2016-07-15T07:22:01.713 に答える