Windows读取CRED_TYPE_DOMAIN_PASSWORD类型CredentialBlob为空问题求助
问题排查与解决方案
核心问题1:Persist参数值非法
你在写入凭据时使用了CRED_PERSIST_LOCAL_MACHINE,但Windows凭据管理器的CREDENTIALA结构体中,Persist字段仅支持以下三个有效值:
CRED_PERSIST_SESSION(1):凭据仅在当前用户会话有效,注销后自动清除CRED_PERSIST_LOCAL(2):凭据存储在本地机器,对所有用户可见(需管理员权限写入)CRED_PERSIST_ENTERPRISE(3):凭据标记为企业级,可随用户账户漫游
非法的Persist值会导致CredWriteA无法正确处理密码数据,最终存储的凭据缺失密码字段,表现为读取时CredentialBlobSize为0。
核心问题2:权限不足(场景限定)
若使用CRED_PERSIST_LOCAL,程序必须以管理员权限运行才能成功写入机器级凭据。无管理员权限时,写入操作可能返回成功,但实际并未完整存储密码数据。
修复后的写入代码
void credWriteWindows() { string targetName; string userName; string password; string targetAlias; cout << "enter target name :" << endl; cin >> targetName; cout << "enter user name :" << endl; cin >> userName; cout << "enter password" << endl; cin >> password; cout << "enter target Alias:" << endl; cin >> targetAlias; CREDENTIALA writeCred = {}; writeCred.Flags = 0; writeCred.Type = CRED_TYPE_DOMAIN_PASSWORD; writeCred.TargetName = const_cast<char*>(targetName.c_str()); // 用size()获取字节数,兼容多字节字符场景 writeCred.CredentialBlobSize = static_cast<DWORD>(password.size()); writeCred.CredentialBlob = reinterpret_cast<LPBYTE>(const_cast<char*>(password.c_str())); // 替换为合法的Persist值,此处以本地存储为例(需管理员权限) writeCred.Persist = CRED_PERSIST_LOCAL; writeCred.UserName = const_cast<char*>(userName.c_str()); writeCred.TargetAlias = const_cast<char*>(targetAlias.c_str()); BOOL result = CredWriteA(&writeCred, 0); if (result) { cout << "Credential write successful" << endl; } else { DWORD errorCode = GetLastError(); cout << "Credential write failed with error code: " << errorCode << endl; } }
额外说明
- 读取代码中
sizeof(readCred->CredentialBlob)输出的是指针的字节长度(32位系统为4,64位为8),并非实际密码数据大小,该输出无意义可删除。 - 若无需机器级凭据,改用
CRED_PERSIST_SESSION可跳过管理员权限要求,但凭据会在用户注销后失效。
内容的提问来源于stack exchange,提问作者Faramarz Jafari
相关产品推荐
相关产品推荐

