異步呼叫存在嚴重的安全性風險,因為對 接收的回呼 可能不是原始應用程式或腳本異步呼叫的結果。 遠端連線的安全性是以客戶端與遠端電腦上的提供者之間的通訊加密為基礎。 在 C++中,您可以透過呼叫 CoInitializeSecurity中的驗證層級參數來設定加密。 在腳本中,將 AuthenticationLevel 設定在 moniker 連線或 SWbemSecurity 物件上。 如需詳細資訊,請參閱 使用 VBScript 設定預設進程安全性層級。
異步呼叫的安全性風險存在,因為 WMI 會降低回呼上的驗證層級,直到回呼成功為止。 在發出的異步呼叫中,客戶端可以對與 WMI 連線的驗證層級進行設定。 WMI 會擷取用戶端呼叫上的安全性設定,並嘗試使用相同的驗證層級來回呼。 回呼會一律在 RPC_C_AUTHN_LEVEL_PKT_PRIVACY 層級起始。 如果回呼失敗,WMI 會在必要時將驗證層級降低至允許回呼成功的程度,例如 RPC_C_AUTHN_LEVEL_NONE。 在本機系統中進行呼叫且驗證服務不是 Kerberos 的情況下,回呼一律會在 RPC_C_AUTHN_LEVEL_NONE傳回。
最低驗證層級是 RPC_C_AUTHN_LEVEL_PKT (wbemAuthenticationLevelPkt用於腳本)。 不過,您可以指定較高的層級,例如 RPC_C_AUTHN_LEVEL_PKT_PRIVACY (wbemAuthenticationLevelPktPrivacy)。 建議用戶端應用程式或腳本將驗證層級設定為 RPC_C_AUTHN_LEVEL_DEFAULT (wbemAuthenticationLevelDefault),這可讓驗證層級交涉到伺服器指定的層級。
HKEY_LOCAL_MACHINE\Software\Microsoft\WBEM\CIMOM\UnsecAppAccessControlDefault 登錄值可控制 WMI 是否檢查回呼中可接受的驗證層級。 這是在腳本或 Visual Basic 中針對異步呼叫保護接收安全性的唯一機制。 根據預設,此登錄機碼會設定為零。 如果登錄機碼為零,則 WMI 不會驗證驗證層級。 若要保護腳本中的異步呼叫,請將登錄機碼設定為1。 C++用戶端可以調用 IWbemUnsecuredApartment::CreateSinkStub 來控制接收器的存取權。 此值預設會在任何地方產生。
下列主題提供設定異步呼叫安全性的範例:
- 在 VBScript 中的異步呼叫上設定安全性
- 在 C++ 中設定異步呼叫安全性
在 C++ 中設定異步呼叫安全性
IWbemUnsecuredApartment::CreateSinkStub 方法類似於 IUnsecuredApartment::CreateObjectStub 方法,並在一個獨立進程中建立接收器 Unsecapp.exe,以接收回呼。 不過,CreateSinkStub 方法具有 dwFlag參數,指定個別進程如何處理訪問控制。
dwFlag 參數指定 Unsecapp.exe的下列某一動作:
- 使用登錄機碼設定來判斷是否要檢查存取權。
- 忽略登錄機碼,並一律檢查存取權。
- 忽略登錄機碼,絕不檢查存取權。
本主題中的程式代碼範例需要下列 #include 語句才能正確編譯。
#include <wbemidl.h>
下列程式描述如何使用 IWbemUnsecuredApartment執行異步呼叫。
使用 IWbemUnsecuredApartment 執行非同步呼叫
建立一個專用程序,並呼叫 CoCreateInstance 。
下列程式代碼範例會呼叫 CoCreateInstance,以建立專用的程式。
CLSID CLSID_WbemUnsecuredApartment; IWbemUnsecuredApartment* pUnsecApp = NULL; CoCreateInstance(CLSID_WbemUnsecuredApartment, NULL, CLSCTX_LOCAL_SERVER, IID_IWbemUnsecuredApartment, (void**)&pUnsecApp);實例化接收器物件。
下列程式碼範例會建立新的接收物件。
CMySink* pSink = new CMySink; pSink->AddRef();建立資料匯集點的存根。
存根是從接收者生成的包裝函式。
下列程式代碼範例會建立資料接收端的存根。
LPCWSTR wszReserved = NULL; IWbemObjectSink* pStubSink = NULL; IUnknown* pStubUnk = NULL; pUnsecApp->CreateSinkStub(pSink, WBEM_FLAG_UNSECAPP_CHECK_ACCESS, //Authenticate callbacks regardless of registry key wszReserved, &pStubSink);釋放匯入物件指標。
您可以釋放物件指標,因為存根現在擁有指標。
下列程式代碼範例會釋放物件指標。
pSink->Release();在任何異步呼叫中使用存根。
當呼叫完成時,釋放本機參考計數。
下列程式碼範例在非同步呼叫中使用存根。
// pServices is an IWbemServices* object pServices->CreateInstanceEnumAsync(strClassName, 0, NULL, pStubSink);有時,您可能需要在進行非同步呼叫後取消該呼叫。 如果您需要取消呼叫,請使用原本進行呼叫的相同指標取消呼叫。
下列程式代碼範例說明如何取消異步呼叫。
pServices->CancelAsyncCall(pStubSink);使用異步呼叫完成時,請釋放本機參考計數。
在您確認不必取消該異步呼叫之後,才釋放 pStubSink 指標。 此外,在 WMI 釋放 pSink 接收指標後,請勿釋放 pStubSink。 在釋放 pStubSink 之後,pSink 會建立循環參考計數,導致接收器和插桩永遠保留在記憶體中。 相反地,釋放指標的可能位置位於 IWbemObjectSink::SetStatus 呼叫中,WMI 會報告原始異步呼叫已完成。
完成後,呼叫 Release()來取消初始化 COM。
下列程式代碼範例示範如何在 pUnsecApp 指標上呼叫Release()。
pUnsecApp->Release();
如需 CoInitializeSecurity 函式和參數的詳細資訊,請參閱 COM 檔。