異步內容
異步 SSPI 安全性內容可讓呼叫端在呼叫完成時繼續,而不會封鎖並接收通知。 目前只有核心模式 TLS 用戶端和伺服器支援異步內容。 下列異步 SSPI 函式會在異步安全性內容上運作:
異步內容管理類型
物件名稱 | 描述 |
---|---|
SspiAsyncNotifyCallback | 用來通知異步 SSPI 呼叫完成的回呼。 |
異步內容管理功能
API 名稱 | 描述 |
---|---|
SspiCreateAsyncContext | 建立 SspiAsyncContext 的實例,用來追蹤異步呼叫。 |
SspiReinitAsyncContext | 標記異步內容以供重複使用。 |
SspiSetAsyncNotifyCallback | 註冊異步呼叫完成時收到通知的回呼。 |
SspiAsyncContextRequiresNotify | 判斷指定的異步內容是否需要在呼叫完成時通知。 |
SspiGetAsyncCallStatus | 取得與所提供內容相關聯之異步呼叫的目前狀態。 |
SspiFreeAsyncContext | 釋放在呼叫 SspiCreateAsyncContext 函式時建立的內容。 |
異步 SSPI 函式
除了與同步對應專案相同的所有參數之外,下列函式還接受異步內容。
API 名稱 | 描述 |
---|---|
SspiAcquireCredentialsHandleAsync | 以異步方式取得句柄,以預先存在安全性主體的認證。 |
SspiAcceptSecurityContextAsync | 讓傳輸應用程式的伺服器元件以異步方式建立伺服器與遠端客戶端之間的安全性內容。 |
SspiInitializeSecurityContextAsync | 初始化異步安全性內容。 |
SspiDeleteSecurityContextAsync | 刪除先前呼叫 SspiInitializeSecurityContextAsync 函式或 SspiAcceptSecurityContextAsync 函式所起始之指定安全性內容相關聯的本機數據結構。 |
SspiFreeCredentialsHandleAsync | 釋出認證句柄。 |
API 範例
一般呼叫流程的運作方式如下:
- 使用 SspiCreateAsyncContext 建立 SspiAsyncContext 內容來追蹤呼叫
- 為內容註冊 SspiAsyncNotifyCallback
- 使用 SspiAcceptSecurityContextAsync 進行異步呼叫
- 在回呼時,使用 SspiGetAsyncCallStatus 擷取結果
- 使用 SspiDeleteSecurityContextAsync刪除 SspiAsyncContext。 如果使用 SspiReinitAsyncContext重複使用內容,請返回步驟 2。
下列範例示範 SspiAcceptSecurityContextAsync 的調用。 範例會等候呼叫完成並擷取結果。
在完整的 SSPI 交握中,SspiAcceptSecurityContextAsync 和 SspiInitializeSecurityContextAsync 會呼叫多次,直到傳回SEC_E_OK為止。 SspiReinitAsyncContext 已提供方便使用,並在此案例中促進效能。
判斷提示可用來醒目提示在成功案例中預期的內容。
#include <sspi.h>
void AsyncCallCompleted(
_In_ SspiAsyncContext* AsyncContext,
_In_opt_ PVOID pCallbackData
)
{
// Get result.
SECURITY_STATUS Status = SspiGetAsyncCallStatus(AsyncContext);
ASSERT(SEC_E_OK == Status);
// *Perform any needed callback actions, use pCallbackData if needed*
// Clean up async context when done.
SspiFreeAsyncContext(AsyncContext);
}
void DoASCCall(
_In_opt_ PCredHandle phCred,
_In_opt_ PCtxtHandle phContext,
_In_opt_ PSecBufferDesc pInput,
_In_opt_ PSecBufferDesc pOutput,
_Out_ unsigned long* pfContextAttr,
_Out_opt_ PTimeStamp ptsExpiry
)
{
// Create context for async call
SspiAsyncContext* AsyncContext = SspiCreateAsyncContext();
// Check for out of memory condition
ASSERT(AsyncContext);
// Register callback that continues execution upon completion.
PVOID pCallbackData = … ; // *Setup any state needed for callback.*
SECURITY_STATUS Status = SspiSetAsyncNotifyCallback(AsyncContext,
AsyncCallCompleted,
pCallbackData);
ASSERT(SEC_E_OK == Status);
// Queue asynchronous call.
Status = SspiAcceptSecurityContextAsync(AsyncContext,
phCred,
phContext,
pInput,
ASC_REQ_CONNECTION,
SECURITY_NATIVE_DREP,
phContext,
pOutput,
pfContextAttr,
ptsExpiry);
// All async functions return the status of queueing the async call,
// not the call’s result.
ASSERT(SEC_E_OK == Status);
// At this point, the call can be pending or complete.
// If complete, the result or error is returned.
// For this example, we assume if it finished, it finished with SEC_E_OK.
Status = SspiGetAsyncCallStatus(AsyncContext);
ASSERT(SEC_I_ASYNC_CALL_PENDING == Status ||
SEC_E_OK == Status);
// Execution will continue in the callback upon completion
}