You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows 10本地进程获取域用户Kerberos凭证句柄技术问询

Solution: Explicitly Provide Domain Credentials to AcquireCredentialsHandle

The core issue here is that when running as mycomputer\localuser, your process doesn't have access to the cached credentials of mydomain\domainuser by default, and the Windows Credential Manager doesn't supply stored credentials to AcquireCredentialsHandle when using SECPKG_CRED_INBOUND mode. To fix this, you need to explicitly pass the domain user's credentials to the function using the SEC_WINNT_AUTH_IDENTITY_EX structure.

Why Your Original Attempts Failed

  • When omitting the identity parameter, AcquireCredentialsHandle tries to use the security context of the running user (localuser), which has no Kerberos credentials linked to domainuser.
  • Stored credentials in the Credential Manager are designed for outbound authentication (like client-side connections), not for inbound server-side credential acquisition.
  • Specifying just the SPN or username without explicit credentials doesn't work because the system can't associate that external identity with the local user's context.

Modified Server Code

Here's how to adjust your code to explicitly provide the domain user's credentials:

#include <string>
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define SECURITY_WIN32
#include <sspi.h>
#pragma comment(lib, "Secur32.lib") // Link against Secur32.lib

int main() {
    CredHandle credentials;
    TimeStamp lifetime;
    std::wstring package = L"Kerberos";
    std::wstring principal = L"myprotocol/domainuser";

    // Define the domain user's credentials
    SEC_WINNT_AUTH_IDENTITY_EX authIdentity{};
    authIdentity.User = (unsigned short*)L"domainuser";
    authIdentity.UserLength = wcslen(L"domainuser");
    authIdentity.Domain = (unsigned short*)L"mydomain.com";
    authIdentity.DomainLength = wcslen(L"mydomain.com");
    authIdentity.Password = (unsigned short*)L"YourDomainUserPassword"; // Replace with actual password
    authIdentity.PasswordLength = wcslen(L"YourDomainUserPassword");
    authIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

    auto res = AcquireCredentialsHandleW(
        principal.c_str(),
        package.c_str(),
        SECPKG_CRED_INBOUND,
        nullptr,
        &authIdentity, // Pass explicit credentials here
        nullptr,
        nullptr,
        &credentials,
        &lifetime
    );

    if (res == SEC_E_OK) {
        std::wprintf(L"Success\n");
        FreeCredentialsHandle(&credentials);
        return 0;
    } else {
        std::wprintf(L"Failure, error code: 0x%X\n", res);
        return res;
    }
}

Key Implementation Notes

  1. Unicode Compliance: We use wide strings (wchar_t) and AcquireCredentialsHandleW to match Windows API's native Unicode requirements, which is critical for correct domain and username parsing.
  2. Password Security: Hardcoding plaintext passwords is a major security risk. In production, use secure storage mechanisms like DPAPI (Data Protection API) to retrieve the password instead of embedding it directly in code.
  3. SPN Validation: Confirm the SPN myprotocol/domainuser is correctly registered in Active Directory and mapped to mydomain\domainuser. You can verify this with the command:
    setspn -L mydomain\domainuser
    
  4. Permissions: The local user mycomputer\localuser needs permission to call AcquireCredentialsHandle with explicit domain credentials (this is allowed by default unless restricted by Group Policy).

Additional Troubleshooting Checks

If you still encounter errors, verify:

  • The domain user's password is correct and not expired.
  • The local computer can reach the domain controller (test with ping mydomain.com and check LDAP connectivity).
  • No duplicate SPNs exist in Active Directory for myprotocol/domainuser.

内容的提问来源于stack exchange,提问作者Arnaud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 10:37:52