Senden eines Clientzertifikats mit den Klassen "HttpWebRequest" und "HttpWebResponse" in Microsoft Visual C# .NET

SPRACHE AUSWÄHLEN SPRACHE AUSWÄHLEN
Artikel-ID: 895971 - Produkte anzeigen, auf die sich dieser Artikel bezieht
Dieser Artikel ist eine Übersetzung des folgenden englischsprachigen Artikels der Microsoft Knowledge Base:
895971 How to send a client certificate by using the HttpWebRequest and HttpWebResponse classes in Microsoft Visual C# .NET

Voraussetzungen

Damit Sie ein Clientzertifikat aus Microsoft ASP.NET-Anwendungen senden können, müssen Sie die folgenden Hotfixes bzw. Service Packs installiert haben:

Microsoft .NET Framework 1.0

Sie müssen entweder das .NET Framework 1.0 Service Pack 3 (SP3) oder Hotfix 817854 installiert haben. Weitere Informationen finden Sie im folgenden Artikel der Microsoft Knowledge Base:
817854 Update: ASP.NET-Webanwendung kann kein Client-Zertifikat an eine sichere Website senden

.NET Framework 1.1

Sie müssen entweder das .NET Framework 1.1 Service Pack 1 (SP1) oder Hotfix 831138 installiert haben. Weitere Informationen finden Sie im folgenden Artikel der Microsoft Knowledge Base:
831138 UPDATE: eine Framework-Anwendung stellt OutOfMemoryException-Fehler fest, die sehr häufig die System.net.webrequest-methode verwendet
Bitte beachten Sie: Bei diesem Artikel handelt es sich um eine Übersetzung aus dem Englischen. Es ist möglich, dass nachträgliche Änderungen bzw. Ergänzungen im englischen Originalartikel in dieser Übersetzung nicht berücksichtigt sind. Die in diesem Artikel enthaltenen Informationen basieren auf der/den englischsprachigen Produktversion(en). Die Richtigkeit dieser Informationen in Zusammenhang mit anderssprachigen Produktversionen wurde im Rahmen dieser Übersetzung nicht getestet. Microsoft stellt diese Informationen ohne Gewähr für Richtigkeit bzw. Funktionalität zur Verfügung und übernimmt auch keine Gewährleistung bezüglich der Vollständigkeit oder Richtigkeit der Übersetzung.
Alles erweitern | Alles schließen

Auf dieser Seite

Einführung

Dieser Artikel beschreibt, wie Sie in Microsoft Visual C# .NET ein Clientzertifikat mit den Klassen HttpWebRequest und HttpWebResponse senden.

Weitere Informationen

Wenn der Webserver ein Clientzertifikat benötigt, können Sie dies mithilfe der Klassen HttpWebRequest und HttpWebResponse senden. Wenden Sie eine der folgenden Methoden an, um ein Zertifikat zu erhalten, das zum Senden eines Clientzertifikats mit der Klasse HttpWebRequest verwendet werden kann:

Methode 1

Verwenden Sie die Klasse X509Certificate, um das Zertifikat aus einer CER-Datei zu lesen, und legen Sie die Eigenschaft ClientCertificates fest.

Methode 2

Verwenden Sie CryptoAPI-Aufrufe zum Beziehen des Zertifikats aus dem Zertifikatsspeicher. Weisen Sie dem Zertifikat, das sie aus dem Zertifikatsspeicher erhalten haben, dann die Klasse X509Certificate zu. Anschließend können Sie die Eigenschaft ClientCertificates festlegen.

Voraussetzungen für das Senden eines Clientzertifikats

Wenn Sie mit ASP.NET-Anwendungen arbeiten, vergewissern Sie sich, dass folgende Voraussetzungen erfüllt sind:
  • Das Clientzertifikat muss in der Registrierungsstruktur LOCAL_MACHINE und nicht in CURRENT_USER installiert sein. Gehen Sie folgendermaßen vor, um den Installationsort des Clientzertifikats zu ermitteln:
    1. Klicken Sie auf Start, klicken Sie auf Ausführen, geben Sie mmc ein, und klicken Sie auf OK.
    2. Klicken Sie im Menü Datei auf Snap-In hinzufügen/entfernen.
    3. Klicken Sie im Dialogfeld Snap-In hinzufügen/entfernen auf Hinzufügen.
    4. Klicken Sie im Dialogfeld Eigenständiges Snap-In hinzufügen auf Zertifikate, und klicken Sie anschließend auf Hinzufügen.
    5. Wählen Sie im Dialogfeld Zertifikat-Snap-In die Option Computerkonto aus, und klicken Sie dann auf Weiter.
    6. Klicken Sie im Dialogfeld Computer auswählen auf Fertig stellen.
    7. Klicken Sie im Dialogfeld Eigenständiges Snap-In hinzufügen auf Schließen und dann auf OK.
    8. Erweitern Sie Zertifikate (Lokaler Computer), erweitern Sie Persönlich, und klicken Sie dann auf Zertifikate.
    Im rechten Fensterbereich sollte das Clientzertifikat aufgeführt sein.
  • Sie müssen dem ASP.NET-Benutzerkonto die Berechtigungen für den privaten Schlüssel des Clientzertifikats erteilen. Verwenden Sie zum Erteilen der Berechtigungen das Tool "WinHttpCertCfg.exe". Weitere Informationen finden Sie im folgenden Artikel der Microsoft Knowledge Base:
    823193 INFO: wie wird Windows HTTP 5.1 bekommen Zertifikat und Tools der Ablaufverfolgung
    Weitere Informationen zur Verwendung dieses Tools erhalten Sie auf folgender Website des Microsoft Developer Network (MSDN):
    WinHttpCertCfg.exe, a certificate configuration tool http://msdn2.microsoft.com/en-us/library/aa384088.aspx

Verwenden einer CER-Datei

Methode 1 ist leichter anzuwenden, setzt jedoch voraus, dass Sie eine CER-Datei haben. Wenn Sie keine CER-Datei installiert haben, exportieren Sie die CER-Datei mit dem Microsoft Internet Explorer.

Der folgende Quellcode beschreibt, wie Sie ein Zertifikat aus einer CER-Datei erhalten, das Sie mit der Klasse HttpWebRequest verwenden können.
//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;
	}
}

Verwenden von CryptoAPI-Aufrufen

Falls Sie das Zertifikat aus dem Zertifikatsspeicher beziehen müssen, verwenden Sie die CryptoAPI-Funktionen zum Beziehen des Zertifikats und speichern es dann in einem Objekt der Klasse X509Certificate. Die Klasse X509CertificateCollection zählt alle Zertifikate in einem Speicher auf und legt sie in einem Objekt der Klasse X509CertificateCollection ab.

Wenn Sie ein bestimmtes Zertifikat beziehen wollen, müssen Sie den Klassencode dazu mit der Funktion CertFindCertificateInStore modifizieren. Diese Funktion wird in der Datei "Wincrypt.h" deklariert. Alternativ können Sie eine Aufzählung für die Funktion X509CertificateCollection erzeugen, um das gewünschte Zertifikat zu finden.

Der folgende Beispielcode verwendet das erste Zertifikat der Sammlung, die von der CertEnumCertificatesInStore-Funktion zurückgegeben wird.
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;
		}
	}
}

Informationsquellen

Weitere Informationen finden Sie auf den folgenden MSDN-Websites:
X509Certificate class (X509-Zertifikate)
http://msdn2.microsoft.com/de-de/library/system.security.cryptography.x509certificates.x509certificate(en-us,vs.71).aspx
Platform SDK: Cryptography (Plattform-SDK: Kryptographie)
http://msdn2.microsoft.com/de-de/library/aa380255(en-us).aspx

Eigenschaften

Artikel-ID: 895971 - Geändert am: Montag, 25. Februar 2008 - Version: 1.5
Die Informationen in diesem Artikel beziehen sich auf:
  • Microsoft .NET Framework 1.1
  • Microsoft .NET Framework 1.0
Keywords: 
kbhowto kbhowtomaster kbinfo kbprogramming kbwebclasses kbsample kbcode kbaspnet kbdigitalcertificates KB895971
Microsoft stellt Ihnen die in der Knowledge Base angebotenen Artikel und Informationen als Service-Leistung zur Verfügung. Microsoft übernimmt keinerlei Gewährleistung dafür, dass die angebotenen Artikel und Informationen auch in Ihrer Einsatzumgebung die erwünschten Ergebnisse erzielen. Die Entscheidung darüber, ob und in welcher Form Sie die angebotenen Artikel und Informationen nutzen, liegt daher allein bei Ihnen. Mit Ausnahme der gesetzlichen Haftung für Vorsatz ist jede Haftung von Microsoft im Zusammenhang mit Ihrer Nutzung dieser Artikel oder Informationen ausgeschlossen.

Ihr Feedback an uns

 

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