如何以程式設計的方式安裝網際網路資訊伺服器 (IIS) 的 SSL 憑證

文章翻譯 文章翻譯
文章編號: 313624 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

重要本文包含有關編輯中繼庫的資訊。 編輯中繼庫之前請確認您有問題發生時,可以還原的備份複本。有關如何執行這項作業,請參閱 」 設定備份/還原 > 說明主題中 Microsoft 管理主控台 (MMC)]。

結論


本文將逐步說明如何以程式設計方式建立,並再安裝安全通訊端層 (SSL) 憑證網際網路資訊伺服器 (IIS)。雖然 IIS 4.0 版和 IIS 版本 5.0 每個提供使用者介面 (UI),以建立並再安裝 SSL 伺服器憑證,您可以也完成工作以程式設計的方式。



建立的步驟,然後安裝 SSL 憑證 (英文)

若要以程式設計方式建立並再安裝 IIS 伺服器的 SSL 憑證依照下列步驟執行:
  1. 您必須將要求傳送至憑證授權單位來發行伺服器憑證。如果您已經有該憑證而然後您將其儲存在 IIS 伺服器上檔案,並不會傳送要求。
  2. 將憑證匯入適當的憑證存放區。
  3. 將 IIS 設定為使用步驟 1 取得的憑證。



設定 IIS 建立,並再安裝 SSL 憑證

警告如果您不正確地編輯中繼庫可能會導致嚴重的問題,甚至必須重新安裝任何使用中繼庫的產品。 Microsoft 無法保證可以獲得解決的問題,因此,如果您不正確地編輯中繼庫產生。編輯中繼庫,請自行負擔相關的風險。

附註永遠中繼庫之前先備份您編輯它。 請依照下列步驟來設定 IIS 以建立並再安裝 SSL 憑證:
  1. 使用 Microsoft Windows 加密 API 來取得 指紋 的憑證屬性。
  2. 您必須設定 IIS Metabase 屬性 SSLCertHash憑證碼 的值。
  3. 您必須設定 IIS Metabase 屬性 SSLStoreName,至您想要使用存放區。
請參閱下列文章小節,以取得之憑證的 指模 的程式碼範例,然後取得 SSLCertHash 屬性:
C Code to Obtain the Thumbprint of a Server Authentication Certificate
C Code to Enter the SSLCertHash Property into the Metabase



在特定的網站上啟用 SSL 的步驟

您執行 < 設定 IIS 以建立和次要來安裝 SSL 憑證 > 一節中的步驟之後您就可以啟用 SSL 上特定網站或特定資料夾中。若要如何讓您必須啟用 SSL 選項在您想要使用的資料夾中。下列步驟執行對應的 < 設定 IIS 以建立和次要來安裝 SSL 憑證 > 一節中所述的每個步驟:
  1. 當您呼叫 CEnroll::createPKCS10() 方法時,會建立憑證要求。設定為下列的預先定義值的使用方式: szOID_PKIX_KP_SERVER_AUTH
    #define szOID_PKIX_KP_SERVER_AUTH       "1.3.6.1.5.5.7.3.1"		
  2. 當您呼叫 ICertRequest::Submit () 方法時,憑證要求提交到憑證授權單位。
  3. 從該憑證授權單位,擷取憑證以及然後在適當的存放區中安裝它。IIS 伺服器憑證精靈 」 尋找只可用於在本機電腦憑證存放區伺服器驗證的憑證。




若要設定 IIS 的步驟

將憑證儲存到儲存區之後您必須設定 IIS,如下所示:
  1. 使用 CertGetCertificateContextProperty() 方法來取得 憑證碼 屬性和 CERT_HASH_PROP_ID 屬性的值。CertGetCertificateContextProperty() 函式會使用 CryptHashCertificate() 方法來計算 CERT_HASH_PROP_ID 屬性的值。如果不存在的雜湊值,CertGetCertificateContextProperty() 傳回 SHA1 演算法。
  2. 您必須建立一個新二進位 Metabase 屬性,SSLCertHash,對應到 Web 站台。憑證 指紋 取得這一節的步驟 1 中的設定 SSLCertHash。這個問題時結構描述不正確地指定 SSLCertHash 屬性為已展開的 null 已經終止字串,而不是為二進位資料,然後再您不能使用 IIS 管理物件匯入 SSLCertHash。您可以使用只有 IIS Admin 基底物件匯入這個值。若要使用 IIS 管理基底物件 SSLCertHash,您必須使用 Decimal 值 5506。
  3. 您必須建立新字串的 Metabase 屬性,SSLStoreName,對應的 Web 站台。將字串值,SSLStoreName。您可能可以設定 SSLStoreName 透過 (比方說在 ADSI 指令碼) 的 [IIS 管理物件或透過 IIS 管理基底物件。若要使用 IIS 管理基底物件 SSLStoreName,使用 Decimal 值 5511。




C 的程式碼,以取得伺服器驗證憑證指紋

下列範例 Microsoft C 程式碼將告訴您,如何取得的伺服器驗證憑證 指紋 屬性:
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

//--------------------------------------------------------------------
//    Define the name of the store where the needed certificate
//    can be found. 

#define CERT_STORE_NAME  L"MY"

//--------------------------------------------------------------------
//   Declare local functions.
//   Local function definitions follow main.

void HandleError(char *s);

void main(void)
{
//--------------------------------------------------------------------
// Declare and initialize local variables. 
// This includes initializing a pointer to the message. 
// Usually, the message will exist somewhere and a pointer will
// be passed to the application.

//--------------------------------------------------------------------
// System store handle

HCERTSTORE hStoreHandle;   

//--------------------------------------------------------------------
// Pointer to a certificate

PCCERT_CONTEXT pCert;
PCCERT_CONTEXT pPrevCert;
 
LPBYTE pEncodedBytes = NULL;
LPBYTE pHash;
DWORD cbData, i;

//--------------------------------------------------------------------
// Open a certificate store.

if ( !( hStoreHandle = CertOpenStore(
   CERT_STORE_PROV_SYSTEM,
   0,
   NULL,
   CERT_SYSTEM_STORE_LOCAL_MACHINE,
   CERT_STORE_NAME)))
{
     HandleError("The MY store could not be opened.");
}


pPrevCert = NULL;

for (; ((pCert = CertEnumCertificatesInStore(hStoreHandle, pPrevCert)) 
	                                         != NULL);
    pPrevCert = pCert)
{
    CERT_ENHKEY_USAGE *pKeyUsage;
    DWORD j, nLen;
    BOOL bFound = FALSE;
    char certName[1024];

    nLen = sizeof(certName);
    certName[0] = 0;
    if (CertNameToStr(MY_TYPE, &(pCert->pCertInfo->Subject),
        CERT_X500_NAME_STR,
        certName,
        sizeof(certName)))
    {
        printf("Checking %s certificate\n", certName);
    }

    cbData = 0;
    if (!CertGetEnhancedKeyUsage(pCert,
        0,
        NULL,
        &cbData) || cbData == 0)
    {
        if (GetLastError() == CRYPT_E_NOT_FOUND)
        {
            printf("%s certificate is for all key usages\n", certName);
            break;
        }
        else
            printf("CertGetEnhancedKeyUsage failed with error code : %08X\n",
                GetLastError());
    }
    pKeyUsage = (CERT_ENHKEY_USAGE *)
        HeapAlloc(GetProcessHeap(), 0, cbData);
    if (pKeyUsage == NULL)
    {
        printf("HeapAlloc failed with error code : %08X\n",
            GetLastError());
        HandleError("Certificate not found.");
    }
    if (!CertGetEnhancedKeyUsage(pCert,
        0,
        pKeyUsage,
        &cbData))
    {
        if (GetLastError() == CRYPT_E_NOT_FOUND)
        {
            printf("%s certificate is for all key usages\n", certName);
            HeapFree(GetProcessHeap(), 0, pKeyUsage);
            break;
        }
        else
        {
            printf("CertGetEnhancedKeyUsage failed with error code : %08X\n",
                GetLastError());
            HeapFree(GetProcessHeap(), 0, pKeyUsage);
            continue;
        }
    }

    if (pKeyUsage->cUsageIdentifier == 0)
    {
        printf("%s certificate is for all key usages\n", certName);
        HeapFree(GetProcessHeap(), 0, pKeyUsage);
        break;
    }

    bFound = FALSE;
    for (j = 0; j < pKeyUsage->cUsageIdentifier; j++)
    {
        if (strcmpi(pKeyUsage->rgpszUsageIdentifier[j], 
			        szOID_PKIX_KP_SERVER_AUTH) == 0)
        {
            printf("%s certificate is for Server Authentication\n", 
				   certName);
            bFound = TRUE;
            break;
        }
    }

    HeapFree(GetProcessHeap(), 0, pKeyUsage);
    if (bFound)
        break;
}

if (pCert == NULL)
   HandleError("Certificate not found.");

if (pPrevCert)
{
    CertFreeCertificateContext(pPrevCert);
    pPrevCert = NULL;
}

/// CASE 2 Get the hash from the certificate
pHash = NULL;
cbData = 0;
CertGetCertificateContextProperty(pCert, CERT_HASH_PROP_ID, NULL, &cbData);
if (cbData == 0)
{
   HandleError("CertGetCertificateContextProperty 1 failed");
}

pHash = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, cbData);
if (pHash == NULL)
{
   HandleError("HeapAlloc failed");
}
if (!CertGetCertificateContextProperty(pCert, CERT_HASH_PROP_ID, pHash, 
	                                   &cbData))
{
   HandleError("CertGetCertificateContextProperty 2 failed");
}

printf("CERT_HASH_PROP_ID Length is %d\n", cbData);
printf("CERT_HASH_PROP_ID BYTES [", cbData);

for (i = 0; i < cbData; i++)
{
    printf("%02X", pHash[i]);
}
printf("]\n");

//--------------------------------------------------------------------
// Clean up and free memory.

if (pEncodedBytes)
    HeapFree(GetProcessHeap(), 0, pEncodedBytes);

if (pHash)
    HeapFree(GetProcessHeap(), 0, pHash);

if(pCert)
     CertFreeCertificateContext(pCert);
if(CertCloseStore(
      hStoreHandle, 
      CERT_CLOSE_STORE_CHECK_FLAG))
{
    printf("The store closed and all certificates are freed. \n");
}
else
{
    printf("Store closed -- \n"
          "not all certificates, CRLs or CTLs were freed");
}
} // End of main

//--------------------------------------------------------------------
//  This example uses the function HandleError, a simple error
//  handling function, to print an error message to the standard error 
//  (stderr) file and exit the program. 
//  For most applications, replace this function with one 
//  that does more extensive error reporting.

void HandleError(char *s)
{
    fprintf(stderr,"An error occurred in running the program. \n");
    fprintf(stderr,"%s\n",s);
    fprintf(stderr, "Error number %x.\n", GetLastError());
    fprintf(stderr, "Program terminating. \n");
    exit(1);
} // End of HandleError




C Metabase 中輸入 SSLCertHash 屬性的程式碼

下列範例程式碼說明如何使用 IIS 管理基底物件在 Metabase 中設定 SSLCertHash 方法。下列程式碼會使用任意的二進位陣列為憑證 指紋。實際的程式碼會使用 指紋 值,取得當"取得 [指紋的有伺服器驗證憑證 > 一節中執行程式碼。視您如何定義 SetData 方法一起編譯時期,您可以設定 SSLCertHash,或如果您已經為網站設定 SSL,可以取得 SSLCertHash 存在。 The SSLCertHash method return the existing CertHash:
#define UNICODE // unicode must be defined for Metabase access
#define INITGUID 
#include <windows.h>
#include <httpfilt.h>
#include <stdio.h> 

#define SETDATA

#include <iadmw.h>    // COM Interface header 
#include <iiscnfg.h>  // MD_ & IIS_MD_ #defines 



extern "C" wmain (int argc, TCHAR ** argv)
{  
	IMSAdminBase  *pIMeta;  
	METADATA_HANDLE MyHandle; 
    HRESULT hres;
   	METADATA_RECORD record = {0};
    TCHAR szError [2048];
	BYTE *myData=NULL;
    DWORD dwSize = sizeof (record);
 	DWORD i;

	// this just a sample of some thumbprint
	BYTE bar[]={0x24, 0xC6, 0xBA, 0xBB, 0x81, 0x76, 0x05, 0xC9, 0xC3, 
		        0x97, 0x6D, 0x4D, 0xEB, 0x85, 0x8F, 0x4F, 0xBF, 0x38,
				0xFD};
    
    
    CoInitialize (NULL);
    
    // get a pointer to the IIS Admin Base Object
	hres = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, 
			IID_IMSAdminBase, (void **) &pIMeta);  
	if (FAILED(hres))  
	{
	    wsprintf (szError, L"CoCreateInstance Failed. Error: %x\n", hres);
        printf ("%S\n", szError);
		CoUninitialize();
        return TRUE;  
	}
    
    // for this test use only 1st server instance
    hres = pIMeta->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", 
		METADATA_PERMISSION_READ|METADATA_PERMISSION_WRITE, 20, &MyHandle); 
	if (FAILED (hres) )
	{
		wsprintf (szError, L"OpenKey Failed. Error: %x\n", hres);
        printf ("%S\n", szError);
		goto clean;
	}
    
	// SSLCertHash = 5506
	record.dwMDIdentifier =  5506;
    record.dwMDAttributes =METADATA_INHERIT;
    record.dwMDUserType=IIS_MD_UT_SERVER;
    record.dwMDDataType= BINARY_METADATA;
    record.pbMDData = (unsigned char *) myData;

#ifndef SETDATA
#pragma message ("Building for GetData\n")    
	again:
    hres = pIMeta->GetData (MyHandle,argv[1], &record, &dwSize);
   	if (FAILED (hres) )
	{
		if (hres == MD_ERROR_DATA_NOT_FOUND)
		{
			printf ("%S\n", L"Data not found, no certificate is set!");
			goto clean;
		}
		else if (HRESULT_CODE(hres)==ERROR_INSUFFICIENT_BUFFER)
		{
			record.dwMDDataLen=dwSize;
			myData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, dwSize);
			record.pbMDData  = (unsigned char *)myData;
		    goto again;
		}
		else  
		{
			wsprintf (szError, L"GetData Failed. Error: %x\n", hres);
			printf ("%S\n", szError);
			goto clean;;
		}
	}

	printf ("%S", L"Got thumbprint. You can compare" 
		          L" it with the MMC for IIS value:\n");	
	for ( i=0; i<(record.dwMDDataLen/sizeof (BYTE)); i++)		
		printf ("%2X ", myData[i]);  
	HeapFree(GetProcessHeap(), 0, myData);
#else
#pragma message ("Building for SetData\n")

	
	record.pbMDData = bar;
	record.dwMDDataLen = 19; // in real code it should be the size 
                                                   // of the thumbprint buffer
	hres = pIMeta->SetData (MyHandle,argv[1], &record);
	if (FAILED (hres) )
	{
		printf ("Set data failed: 0x%x!\n", hres);
		goto clean;
	}
	else
		printf ("New thumbprint is set\n");
#endif

clean:
	pIMeta->CloseKey(MyHandle); 
	pIMeta->SaveData();
	pIMeta->Release();
	CoUninitialize();

	return 1;
}



?考

如需詳細資訊,請按一下下列的文件編號,檢視 「 Microsoft 知識庫 」 中的文件:
315588如何保障 ASP.NET 應用程式使用用戶端憑證的安全

屬性

文章編號: 313624 - 上次校閱: 2006年7月11日 - 版次: 2.2
這篇文章中的資訊適用於:
  • Microsoft Internet Information Server 4.0
  • Microsoft Internet Information Services 5.0
關鍵字:?
kbmt kbcrypt kbapi kbhowtomaster kbsecurity kbisapiext kbhowto KB313624 KbMtzh
機器翻譯
重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,而非使用人工翻譯而成。Microsoft 同時提供使用者人工翻譯及機器翻譯兩個版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,機器翻譯的文章可能不盡完美。這些文章中也可能出現拼字、語意或文法上的錯誤,就像外國人在使用本國語言時可能發生的錯誤。Microsoft 不為內容的翻譯錯誤或客戶對該內容的使用所產生的任何錯誤或損害負責。Microsoft也同時將不斷地就機器翻譯軟體進行更新。
按一下這裡查看此文章的英文版本:313624
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

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