2012-03-15 46 views
6

我想根據域控制器驗證一組憑據。例如:如何驗證域憑證(從本機代碼)?

Username: joel 
Password: splotchy 
Domain: STACKOVERFLOW 

在.NET 3.5和更新的版本中you can use PrincipalContext.ValidateCredentials(username, password)

否則你有麻煩。

繼Microsoft知識庫文章How to validate user credentials on Microsoft operating systems在代碼中,我得到的地方,你打電話AcceptSecurityContext點:

ss = AcceptSecurityContext(
     @pAS._hcred,   //[in]CredHandle structure 
     phContext,    //[in,out]CtxtHandle structure 
     @InBuffDesc,   //[in]SecBufferDesc structure 
     0,      //[in]context requirement flags 
     SECURITY_NATIVE_DREP, //[in]target data representation 
     @pAS._hctxt,   //[in,out]CtxtHandle strcture 
     @OutBuffDesc,   //[in,out]SecBufferDesc structure 
     ContextAttributes,  //[out]Context attribute flags 
     @Lifetime);   //[out]Timestamp struture 

除了函數失敗:

SEC_E_NO_AUTHENTICATING_AUTHORITY(0x80090311 )

該功能失敗。沒有權威可以聯繫認證。這可能是由於以下情況:

  • 驗證方的域名不正確。
  • 該域名不可用。
  • 信任關係失敗。

這將是一個有用的錯誤,但我可以使用驗證從.NET 3.5相同的憑據:

using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domain)) 
{ 
    valid = context.ValidateCredentials(username, password);     
} 

什麼可能會發生,讓.NET來驗證一組憑據,而本機代碼不能?


更新LogonUser也失敗:

LogonUser("[email protected]", null, "splotchy", 
     LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_WINNT50, out token); 

1311 - There are currently no logon servers available to service the logon request 

更新兩個:我都試過首選Negotiate提供商,以及作爲第四Ë的Windows NT4遺產「NTLM」提供

String package = "Negotiate"; //"NTLM" 

QuerySecurityPackageInfo(package, [out] packageInfo); 
... 
AcquireCredentialsHandle(
     null,     //[in] principle 
     package,    //[in] package 
     SECPKG_CRED_OUTBOUND, //[in] credential use 
     null,     //[in] LogonID 
     pAuthIdentity,  //[in] authData 
     null,     //[in] GetKeyFn, not used and should be null 
     null,     //[in] GetKeyArgument, not used and should be null 
     credHandle,   //[out] CredHandle structure 
     expires);    //[out] expiration TimeStamp structure 
+0

你是如何調用'InitializeSecurityContext'? (哪個SSP,特別是?)你如何設置CredHandle? – 2012-03-15 16:34:03

+0

@EdwardThomson我試過優選'Negotiate'提供商,以及'NTLM'。 'CredHandle'通過調用'AcquireCredentialsHandle'來初始化。 – 2012-03-15 18:02:20

+0

我似乎記得有一個類似的問題,雖然這是幾年前,這個問題是模糊的。如果您運行瓦特/提升權限,是否有任何更改? (域管理員也許?) – 2012-03-15 18:04:02

回答

0

我相信,這是解決相同問題的另一question您發佈。

我有點理解你現在要做的事情。讓我回顧一下你在另一篇文章中寫的內容。

Username Password Domain    Machine on domain? Validate as 
======== ======== ================= ================== ============== 
iboyd  pass1  .     No     Local account 
iboyd  pass1  (empty)   No     Local account 
iboyd  pass1  stackoverflow.com No     Domain account 
iboyd  pass1  .     Yes     Local account 
iboyd  pass1  (empty)   Yes     Domain account 
iboyd  pass1  stackoverflow.com Yes     Domain account 

你想

  1. 認證來自一個域中的用戶,你的機器不信任
  2. 驗證從您的機器信任
  3. 域用戶進行認證的本地用戶

您可以通過做適當的SSPI握手與域控制器實現前兩種情況。您在另一個問題中提到的知識庫文章是做迴環SSPI握手。在第一種情況下不起作用,因爲客戶機不信任您正在進行身份驗證的域。這應該是爲什麼你看到SEC_E_NO_AUTHENTICATING_AUTHORITY

長話短說,如果你想要做同樣的事情

PrincipalContext.ValidateCredentials(username, password); 

您需要從域用戶處理不同的本地用戶。對於域用戶,您需要撥打ldap_bind_s以使用給定憑證綁定到域控制器。對於本地用戶,您需要使用ADsOpenObject綁定到WINNT://您計算機的名稱使用給定的憑據。這是什麼PrincipalContext.ValidateCredentials做我從反射器中讀取。

我看不出有任何相當於一個單獨的本地API做同樣的事情你。