撰寫已驗證的 SSPI 用戶端

所有 RPC 用戶端/伺服器會話都需要用戶端與伺服器之間的系結。 若要將安全性新增至用戶端/伺服器應用程式,程式必須使用已驗證的系結。 本節說明在用戶端與伺服器之間建立已驗證系結的程式。

如需相關資訊,請參閱 Platform Software Development Kit (SDK) 中 與大部分安全性套件和通訊協定搭配使用的程式

建立用戶端系結控制碼

若要使用伺服器程式建立已驗證的會話,用戶端應用程式必須為其系結控制碼提供驗證資訊。 若要設定已驗證的系結控制碼,用戶端會叫用 RpcBindingSetAuthInfoRpcBindingSetAuthInfoEx 函 式。 這兩個函式幾乎完全相同。 它們之間的唯一差異在於用戶端可以使用 RpcBindingSetAuthInfoEx 函式來指定服務品質。

下列程式碼片段顯示 RpcBindingSetAuthInfo 的呼叫外觀。

// This code fragment assumes that rpcBinding is a valid binding 
// handle between the client and the server. It also assumes that
// pAuthCredentials is a valid pointer to a data structure which
// contains the user's authentication credentials.

dwStatus = DsMakeSpn(
    "ldap",
    "ServerName.domain.com",
    NULL,
    0,
    NULL,
    &pcSpnLength,
    pszSpn);

//...

rpcStatus = RpcBindingSetAuthInfo(
    rpcBinding,                       // Valid binding handle
    pszSpn,                           // Principal name 
    RPC_C_AUTHN_LEVEL_PKT_INTEGRITY,  // Authentication level
    RPC_C_AUTHN_GSS_NEGOTIATE,        // Use Negotiate SSP
    NULL,                             // Authentication credentials <entity type="ndash"/> use current thread credentials
    RPC_C_AUTHZ_NAME);                // Authorization service

在用戶端成功呼叫 RpcBindingSetAuthInfoRpcBindingSetAuthInfoEx 函式之後,RPC 執行時間程式庫會自動驗證系結上的所有 RPC 呼叫。 用戶端選取的安全性與驗證層級僅適用于該系結控制碼。 衍生自系結控制碼的內容控制碼會使用相同的安全性資訊,但對系結控制碼的後續修改將不會反映在內容控制碼中。 如需詳細資訊,請參閱 內容控制碼

驗證層級會維持有效狀態,直到用戶端選擇另一個層級,或直到進程終止為止。 大部分的應用程式都不需要變更安全性層級。 用戶端可以查詢任何系結控制碼,以叫用 RpcBindingInqAuthClient 並傳遞系結控制碼來取得其授權資訊。

提供用戶端認證給伺服器

伺服器會使用用戶端的系結資訊來強制執行安全性。 用戶端一律會傳遞系結控制碼做為遠端程序呼叫的第一個參數。 不過,除非伺服器在 IDL 檔案或伺服器的應用程式組態檔中宣告為遠端程式的第一個參數,否則伺服器無法使用控制碼, (ACF) 。 您可以選擇列出 IDL 檔案中的系結控制碼,但這會強制所有用戶端宣告及操作系結控制碼,而不是使用自動或隱含系結。 如需詳細資訊,請參閱 IDL 和 ACF 檔案

另一種方法是讓系結控制碼離開 IDL 檔案,並將 explicit_handle 屬性放入伺服器的 ACF 中。 如此一來,用戶端就可以使用最適合應用程式的系結類型,而伺服器會使用系結控制碼,就像明確宣告一樣。

從系結控制碼擷取用戶端認證的程式如下:

  • RPC 用戶端會呼叫 RpcBindingSetAuthInfo ,並在傳遞至伺服器的系結資訊中包含其驗證資訊。
  • 伺服器通常會呼叫 RpcImpersonateClient ,使其行為就像是用戶端一樣。 如果未驗證系結控制碼,呼叫就會失敗,並出現RPC_S_NO_CONTEXT_AVAILABLE。 若要取得用戶端的使用者名稱,請在模擬時呼叫 RpcBindingInqAuthClient ,或在 Windows XP 或更新版本的 Windows 上呼叫 RpcGetAuthorizationCoNtextForClient 以取得授權內容,然後使用 Authz 函式來擷取名稱。
  • 伺服器通常會呼叫 CreatePrivateObjectSecurity ,以使用 ACL 建立物件。 完成此動作之後,稍後的安全性檢查就會自動進行。