2015-03-03 166 views
0

我寫了一個自定義Windows Credentials Provider來捕獲用戶登錄名。此提供程序的主要目的之一是存儲用戶的密碼,並在登錄時將其用於Windows上運行的C#服務。從憑證提供程序向C#服務提供憑證信息

這導致我發現存儲憑證信息的位置和方式的問題。在登錄時(即用戶提供有效的登錄信息並選擇登錄),服務應該能夠獲取信息並使用它。

什麼是將證書信息傳遞給服務的正確方式?

該登錄用戶提供的憑證都或多或少根據對憑據提供所提供的微軟樣品,其中GetSerialization看起來像這樣的部分:

hr = ProtectIfNecessaryAndCopyPassword(_rgFieldStrings[SFI_PASSWORD], _cpus, &pwzProtectedPassword); 

g_pwzProtectedPassword = pwzProtectedPassword; 

if (SUCCEEDED(hr)) 
{ 
    PWSTR pszDomain; 
    PWSTR pszUsername; 
    hr = SplitDomainAndUsername(_pszQualifiedUserName, &pszDomain, &pszUsername); 
    if (SUCCEEDED(hr)) 
    { 
     KERB_INTERACTIVE_UNLOCK_LOGON kiul; 
     hr = KerbInteractiveUnlockLogonInit(pszDomain, pszUsername, pwzProtectedPassword, _cpus, &kiul); 
     if (SUCCEEDED(hr)) 
     { 
      // We use KERB_INTERACTIVE_UNLOCK_LOGON in both unlock and logon scenarios. It contains a 
      // KERB_INTERACTIVE_LOGON to hold the creds plus a LUID that is filled in for us by Winlogon 
      // as necessary. 
      hr = KerbInteractiveUnlockLogonPack(kiul, &pcpcs->rgbSerialization, &pcpcs->cbSerialization); 
      if (SUCCEEDED(hr)) 
      { 
       ULONG ulAuthPackage; 
       hr = RetrieveNegotiateAuthPackage(&ulAuthPackage); 
       if (SUCCEEDED(hr)) 
       { 
        pcpcs->ulAuthenticationPackage = ulAuthPackage; 
        pcpcs->clsidCredentialProvider = CLSID_CredentialProvider; 
        // At this point the credential has created the serialized credential used for logon 
        // By setting this to CPGSR_RETURN_CREDENTIAL_FINISHED we are letting logonUI know 
        // that we have all the information we need and it should attempt to submit the 
        // serialized credential. 
        *pcpgsr = CPGSR_RETURN_CREDENTIAL_FINISHED; 
       } 
      } 
     } 
     CoTaskMemFree(pszDomain); 
     CoTaskMemFree(pszUsername); 
    } 
    CoTaskMemFree(pwzProtectedPassword); 
} 

編輯:

我試着使用Windows Credential Manager API來保存密碼,但似乎沒有效果。當我嘗試獲取登錄後的用戶名/密碼時,我什麼也沒有返回。

DWORD cbCreds = (DWORD)(1 + strlen(password)); 

CREDENTIALW cred = { 0 }; 
cred.Type = CRED_TYPE_GENERIC; 
cred.TargetName = TargetName; 
cred.CredentialBlobSize = cbCreds; 
cred.CredentialBlob = (LPBYTE)password; 
cred.Persist = CRED_PERSIST_LOCAL_MACHINE; 
cred.UserName = *username; 

return ::CredWriteW(&cred, 0) ? true : false; 

回答

0

認爲管道將是與服務進行通信的正確方式。 使用Windows Credential Manager保存/加載密碼時,由於登錄會話不同並且用戶的SID在未登錄時被禁用,所以不起作用。

相關問題