Microsoft Visual C# .NET で HttpWebRequest および HttpWebResponse の各クラスを使用してクライアント証明書を送付する方法

文書翻訳 文書翻訳
文書番号: 895971 - 対象製品

必要条件

Microsoft ASP.NET アプリケーションからクライアント証明書を送付するには、次の修正プログラムまたは Service Pack がインストールされている必要があります。

Microsoft .NET Framework 1.0

.NET Framework 1.0 Service Pack 3 (SP3) または 817854 修正プログラムをインストールする必要があります。 関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
817854 [FIX] ASP.NET Web アプリケーションで、クライアント証明書をセキュリティで保護された Web サイトに送信できない

.NET Framework 1.1

.NET Framework 1.1 Service Pack 1 (SP1) または 831138 修正プログラムをインストールする必要があります。 関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
831138 [FIX] System.Net.WebRequest メソッドを使用する .NET Framework アプリケーションで頻繁に OutOfMemoryException エラーが発生する
すべて展開する | すべて折りたたむ

目次

はじめに

この資料では、Microsoft Visual C# .NET で、HttpWebRequest および HttpWebResponse の各クラスを使用してクライアント証明書を送付する方法について説明します。

詳細

Web サーバーでクライアント証明書が必要な場合は、HttpWebRequest および HttpWebResponse の各クラスを使用してクライアント証明書を送付できます。クライアント証明書の送付に使用される証明書を HttpWebRequest クラスを使用して取得するには、次のいずれかの手順を実行します。

方法 1

X509Certificate クラスを使用して .cer ファイルから証明書を読み取り、ClientCertificates プロパティを設定します。

方法 2

CryptoAPI 呼び出しを使用して証明書ストアから証明書を取得し、証明書ストアから受け取った証明書に対して X509Certificate クラスを設定します。次に ClientCertificates プロパティを設定します。

クライアント証明書の送付に必要な条件

ASP.NET アプリケーションを使用するときは、次の条件がすべて満たされている必要があります。
  • クライアント証明書は、CURRENT_USER レジストリ ハイブではなく、LOCAL_MACHINE レジストリ ハイブにインストールする必要があります。クライアント証明書がインストールされている場所を確認するには、次の手順を実行します。
    1. [スタート] ボタンをクリックし、[ファイル名を指定して実行] をクリックします。mmc と入力し、[OK] をクリックします。
    2. [ファイル] メニューの [スナップインの追加と削除] をクリックします。
    3. [スナップインの追加と削除] ダイアログ ボックスで [追加] をクリックします。
    4. [スタンドアロン スナップインの追加] ダイアログ ボックスの [証明書] をクリックし、[追加] をクリックします。
    5. [証明書スナップイン] ダイアログ ボックスの [コンピュータ アカウント] をクリックし、[次へ] をクリックします。
    6. [コンピュータの選択] ダイアログ ボックスで [完了] をクリックします。
    7. [スタンドアロン スナップインの追加] ダイアログ ボックスの [閉じる] をクリックし、[OK] をクリックします。
    8. [証明書 (ローカル コンピュータ)]、[個人] を順に展開し、次に [証明書] をクリックします。
    右側のペインに、クライアント証明書が一覧表示されます。
  • ASP.NET ユーザー アカウントには、クライアント証明書の秘密キーに対するアクセス許可を与える必要があります。ASP.NET ユーザー アカウントにクライアント証明書の秘密キーに対するアクセス許可を与えるには、WinHttpCertCfg.exe ツールを使用します。 関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
    823193 Windows HTTP 5.1 証明書とトレース ツールの入手方法
    このツールの使用方法の詳細については、以下の MSDN (Microsoft Developer Network) Web サイトを参照してください。
    WinHttpCertCfg.exe, a Certificate Configuration Tool
    http://msdn2.microsoft.com/en-us/library/aa384088.aspx

.cer ファイルの使用方法

方法 1 の使用方法はより簡単ですが、この方法には .cer ファイルが必要です。.cer ファイルをインストールしていない場合は、Microsoft Internet Explorer を使用して .cer ファイルをエクスポートします。

次のソース コードには、HttpWebRequest クラスで使用できる証明書を .cer ファイルから取得する方法が記載されています。
//Uncomment the following code if you need a proxy. The boolean true is used to bypass the local address.
//WebProxy proxyObject = new WebProxy("Your Proxy value",true); 
//GlobalProxySelection.Select = proxyObject;

// Obtain the certificate. 
try
{
	//You must change the path to point to your .cer file location. 
	X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\mycert.cer");
	// Handle any certificate errors on the certificate from the server.
	ServicePointManager.CertificatePolicy = new CertPolicy();
	// You must change the URL to point to your Web server.
	HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://YourServer/sample.asp");
	Request.ClientCertificates.Add(Cert);
	Request.UserAgent = "Client Cert Sample";
	Request.Method = "GET";
	HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
	// Print the repsonse headers.
	Console.WriteLine("{0}",Response.Headers);
	Console.WriteLine();
	// Get the certificate data.
	StreamReader sr = new StreamReader(Response.GetResponseStream(), Encoding.Default);
	int count;
	char [] ReadBuf = new char[1024];
	do
	{
		count = sr.Read(ReadBuf, 0, 1024);
		if (0 != count)
		{
			Console.WriteLine(new string(ReadBuf));
		}
						
	}while(count > 0);
}
catch(Exception e)
{
	Console.WriteLine(e.Message);
}
	

//Implement the ICertificatePolicy interface.
class CertPolicy: ICertificatePolicy
{
	public bool CheckValidationResult(ServicePoint srvPoint, 
X509Certificate certificate, WebRequest request, int certificateProblem)
	{
		// You can do your own certificate checking.
		// You can obtain the error values from WinError.h.

		// Return true so that any certificate will work with this sample.
		return true;
	}
}

CryptoAPI 呼び出しの使用方法

証明書を証明書ストアから取得する必要がある場合は、CryptoAPI 関数を使用して証明書を取得し、その証明書を X509Certificate クラス オブジェクトに格納します。X509CertificateCollection クラスによってストア内のすべての証明書が列挙され、それらの証明書が X509CertificateCollection クラス オブジェクトに格納されます。

特定の証明書を取得する場合は、このクラスのコードを変更し、CertFindCertificateInStore 関数を使用して特定の証明書を取得する必要があります。この関数は Wincrypt.h ファイル内に宣言されています。別の方法として、X509CertificateCollection 関数を列挙して、取得する証明書を見つけることもできます。

次のサンプル コードでは、CertEnumCertificatesInStore 関数から返されたコレクション内の最初の証明書が使用されています。
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Runtime.InteropServices;

namespace SelectClientCert
{
	/// Sample that describes how how to select client cetificate and send it to the server.

	class MyCerts{

		private static int CERT_STORE_PROV_SYSTEM = 10;
		private static int CERT_SYSTEM_STORE_CURRENT_USER = (1 << 16);
		///private static int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);

		[DllImport("CRYPT32", EntryPoint="CertOpenStore", CharSet=CharSet.Unicode, SetLastError=true)]
		public static extern IntPtr CertOpenStore(
			int storeProvider, int encodingType,
			int hcryptProv, int flags, string pvPara);

		[DllImport("CRYPT32", EntryPoint="CertEnumCertificatesInStore", CharSet=CharSet.Unicode, SetLastError=true)]
		public static extern IntPtr CertEnumCertificatesInStore(
			IntPtr storeProvider,
			IntPtr prevCertContext);

		[DllImport("CRYPT32", EntryPoint="CertCloseStore", CharSet=CharSet.Unicode, SetLastError=true)]
		public static extern bool CertCloseStore(
			IntPtr storeProvider,
			int flags);
		
		X509CertificateCollection m_certs;

		public MyCerts(){
			m_certs = new X509CertificateCollection();
		}

		public int Init()
		{
			IntPtr storeHandle;
			storeHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, "MY");
			IntPtr currentCertContext;
			currentCertContext = CertEnumCertificatesInStore(storeHandle, (IntPtr)0);
			int i = 0;
			while (currentCertContext != (IntPtr)0) 
			{
				m_certs.Insert(i++, new X509Certificate(currentCertContext));
				currentCertContext = CertEnumCertificatesInStore(storeHandle, currentCertContext);
			}
			CertCloseStore(storeHandle, 0);

			return m_certs.Count;
		}
		
		public X509Certificate this [int index]
		{
			get 
			{
				// Check the index limits.
				if (index < 0 || index > m_certs.Count)
					return null;
				else
					return m_certs[index];
			}
		}
	};
	class MyHttpResource
	{
		String m_url;

		public MyHttpResource(string url){
			m_url = url;
		}

		public void GetFile(){

			HttpWebResponse  result = null;

			try{
			
				HttpWebRequest req = (HttpWebRequest)WebRequest.Create(m_url);
				req.Credentials  = CredentialCache.DefaultCredentials;

				///Method1
				//req.ClientCertificates.Add(X509Certificate.CreateFromCertFile("D:\\Temp\\cert\\c1.cer"));
		
				///Method2
				///Uses interop services
				MyCerts mycert = new MyCerts();
				if(mycert.Init() > 0)
					req.ClientCertificates.Add(mycert[0]);

				result = (HttpWebResponse)req.GetResponse();
				
				Stream ReceiveStream = result.GetResponseStream();
				Encoding encode = System.Text.Encoding.GetEncoding("utf-8");

				StreamReader sr = new StreamReader( ReceiveStream, encode );
				Console.WriteLine("\r\nResponse stream received");

				Char[] read = new Char[256];
				int count = sr.Read( read, 0, 256 );

				Console.WriteLine("HTTP Response...\r\n");
				while (count > 0) 
				{
					String str = new String(read, 0, count);
					Console.Write(str);
					count = sr.Read(read, 0, 256);
				}

			} 
			catch(WebException e) 
			{
            
				Console.WriteLine("\r\nError:");
				#if (DEBUG)
					Console.WriteLine(e.ToString());
				#else		
					Console.WriteLine(e.Message); 				
				#endif

			} 
			finally 
			{
				if ( result != null ) {
					result.Close();
				}
			}
				
		}
	
	}

	class CertSample
	{
		static void Main(string[] args)
		{
			try
			{
				if (args.Length < 1)
				{
					Console.WriteLine("No url is entered to download, returning.\n");
					Console.WriteLine("Usage: CertSample <urltoget>\n");
					Console.WriteLine("  e.g: CertSample https://servername \n"); 

					return;
				}

				MyHttpResource hr = new MyHttpResource(args[0]);
				hr.GetFile();
			}
			catch(Exception e)
			{
				Console.WriteLine(e.ToString());
			}
			return;
		}
	}
}

関連情報

詳細については、次の MSDN (Microsoft Developer Network) Web サイトを参照してください。
X509Certificate クラス
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfsystemsecuritycryptographyx509certificatesx509certificateclasstopic.asp
Platform SDK: Cryptography
http://msdn2.microsoft.com/en-us/library/aa380255.aspx

プロパティ

文書番号: 895971 - 最終更新日: 2007年1月16日 - リビジョン: 1.4
この資料は以下の製品について記述したものです。
  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
キーワード:?
kbhowto kbhowtomaster kbinfo kbprogramming kbwebclasses kbsample kbcode kbaspnet kbdigitalcertificates KB895971
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com