使用 C++ 設定驗證

WMI 的 IWbemLocator::ConnectServer 主要工作之一是傳回 IWbemServices Proxy 的 指標。 透過 IWbemServices Proxy,您可以存取 WMI 基礎結構的功能。 不過, IWbemServices Proxy 的指標具有用戶端應用程式進程的身分識別,而不是 IWbemServices 程式的身分識別。 因此,如果您嘗試使用 指標存取 IWbemServices ,您可以接收拒絕存取的程式碼,例如 E_ACCESSDENIED。 若要避免拒絕存取錯誤,您必須使用 對 CoSetProxyBlanket 介面的呼叫來設定新指標的身分識別。

提供者可以在命名空間上設定安全性,除非您在該命名空間的連線中使用封包隱私權 (PktPrivacy) ,否則不會傳回任何資料。 這可確保資料在跨網路時加密。 如果您嘗試設定較低的驗證層級,您將會收到拒絕存取的訊息。 如需詳細資訊,請參閱 設定 Namepace 安全性描述元

如需在腳本中設定驗證的詳細資訊,請參閱 使用 VBScript 設定預設進程安全性層級

在遠端 IUnknown 介面上設定安全性

在某些情況下,比只需要 Proxy 的指標,才能存取伺服器。 有時候,您可能需要安全地連線到 Proxy 的 IUnknown 介面。 您可以使用 IUnknown查詢遠端系統,以取得介面和其他必要技術。

當 Proxy 位於遠端電腦上時,伺服器會將 Proxy 之 IUnknown 介面的所有呼叫委派給 IUnknown 介面。 例如,如果您在 Proxy 上呼叫 QueryInterface ,而要求的介面不是 Proxy 的一部分,Proxy 就會將呼叫傳送至遠端伺服器。 接著,遠端伺服器會檢查適當的介面支援。 如果伺服器支援 介面,COM 會將新的 Proxy 封送處理回用戶端,讓應用程式可以使用新的介面。

如果用戶端沒有遠端伺服器的存取權限,但正在使用該使用者認證,就會發生問題。 在此情況下,任何嘗試存取遠端伺服器上的 QueryInterface 都失敗。 Proxy 的最終版本也會失敗,因為目前的使用者無法存取遠端伺服器。 這是用戶端應用程式失敗最終 Proxy 發行前的一或兩秒延遲徵兆。 發生失敗的原因是 COM 嘗試使用目前使用者的預設安全性設定來存取遠端伺服器,但不包括第一次允許存取伺服器的已修改認證。 如需詳細資訊,請參閱 在 IWbemServices 和其他 Proxy 上設定安全性

若要避免連線失敗,請使用 CoSetProxyBlanket ,在 從 IUnknown傳回的指標上明確設定安全性驗證。 使用 CoSetProxyBlanket,您可以確定遠端伺服器會收到正確的驗證身分識別。

下列程式碼範例示範如何使用 CoSetProxyBlanket 來存取遠端 IUnknown 介面。

SEC_WINNT_AUTH_IDENTITY_W* pAuthIdentity = 
   new SEC_WINNT_AUTH_IDENTITY_W;
ZeroMemory(pAuthIdentity, sizeof(SEC_WINNT_AUTH_IDENTITY_W));

pAuthIdentity->User = new WCHAR[32];
StringCbCopyW(pAuthIdentity->User,sizeof(L"MyUser"),L"MyUser");
pAuthIdentity->UserLength = wcslen(pAuthIdentity->User);

pAuthIdentity->Domain = new WCHAR[32];
StringCbCopyW(pAuthIdentity->Domain,sizeof(L"MyDomain"),L"MyDomain");
pAuthIdentity->DomainLength = wcslen(pAuthIdentity->Domain);

pAuthIdentity->Password = new WCHAR[32];
pAuthIdentity->Password[0] = NULL;
pAuthIdentity->PasswordLength = wcslen( pAuthIdentity->Password);

pAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

IWbemServices* pWbemServices = 0;

// Set proxy security
hr = CoSetProxyBlanket(pWbemServices, 
                       RPC_C_AUTHN_DEFAULT, 
                       RPC_C_AUTHZ_NONE, 
                       COLE_DEFAULT_PRINCIPAL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE 
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pWbemServices->Release();
   return 1;
}

// Set IUnknown security
IUnknown*    pUnk = NULL;
pWbemServices->QueryInterface(IID_IUnknown, (void**) &pUnk);

hr = CoSetProxyBlanket(pUnk, 
                       RPC_C_AUTHN_DEFAULT, 
                       RPC_C_AUTHZ_NONE, 
                       COLE_DEFAULT_PRINCIPAL, 
                       RPC_C_AUTHN_LEVEL_DEFAULT, 
                       RPC_C_IMP_LEVEL_IMPERSONATE, 
                       pAuthIdentity, 
                       EOAC_NONE 
);
if (FAILED(hr))
{
   cout << "Count not set proxy blanket. Error code = 0x"
        << hex << hr << endl;
   pUnk->Release();
   pWbemServices->Release();
   delete [] pAuthIdentity->User;
   delete [] pAuthIdentity->Domain;
   delete [] pAuthIdentity->Password;
   delete pAuthIdentity;   
   return 1;
}

// cleanup IUnknown
pUnk->Release();

//
// Perform a bunch of operations
//

// Cleanup
pWbemServices->Release();

delete [] pAuthIdentity->User;
delete [] pAuthIdentity->Domain;
delete [] pAuthIdentity->Password;

delete pAuthIdentity;

注意

當您在 Proxy 的 IUnknown 介面上設定安全性時,COM 會建立一份在呼叫 CoUninitialize之前無法釋放的 Proxy 複本。

 

在 WMI 中設定驗證