在CreateProcessWithLogon进程中,如何让WNetAddConnection2W调用Windows存储凭据?
在CreateProcessWithLogon进程中自动连接带存储凭据的映射网络驱动器
核心问题剖析
你遇到的问题根源在于:
WNetAddConnection2W本身不会主动读取凭据管理器的存储凭据,除非你不指定用户名/密码,交由系统自动匹配;CredEnumerate/CredRead返回空CredentialBlob,要么是凭据格式不匹配、进程权限不足,要么是未正确解密加密的凭据数据。
具体解决建议
1. 确保进程加载用户配置文件
使用CreateProcessWithLogon创建进程时,必须指定LOGON_WITH_PROFILE标志。用户的凭据存储属于配置文件的一部分,若未加载配置文件,系统无法定位到已存储的凭据,自然无法自动连接。
2. 让WNetAddConnection2W自动调用存储凭据
不要手动传入lpUserName和lpPassword,调用时设置以下标志:
CONNECT_UPDATE_PROFILE:将连接信息持久化到用户配置文件;CONNECT_USE_DEFAULT_CREDENTIALS:触发系统自动从凭据管理器匹配对应凭据。
示例代码:
NETRESOURCEW nr = {0}; nr.dwType = RESOURCETYPE_DISK; nr.lpRemoteName = L"\\\\your-server\\your-share"; DWORD err = WNetAddConnection2W(&nr, NULL, NULL, CONNECT_UPDATE_PROFILE | CONNECT_USE_DEFAULT_CREDENTIALS); if (err != NO_ERROR) { // 根据错误码处理(如ERROR_NO_SUCH_LOGON_SESSION说明配置文件未加载) }
3. 改用WNetUseConnection简化流程
WNetUseConnection会自动尝试多种凭据来源(默认凭据、已存储凭据),比WNetAddConnection2W更适配自动连接场景,无需手动处理凭据读取:
NETRESOURCEW nr = {0}; nr.dwType = RESOURCETYPE_DISK; nr.lpRemoteName = L"\\\\your-server\\your-share"; DWORD err = WNetUseConnectionW(NULL, &nr, NULL, NULL, 0, NULL, NULL, NULL); if (err == NO_ERROR) { // 连接成功 }
4. 正确读取并解密凭据(手动处理场景)
若必须手动读取凭据,需注意以下几点:
- 匹配目标名称格式:网络共享的凭据目标名称通常为
\\\\server\\share,或带域名前缀domain\\\\server\\share,需与凭据管理器中存储的完全一致; - 解密加密数据:Windows存储的凭据是加密状态,需在进程用户上下文内调用
CryptUnprotectData解密; - 指定凭据类型:调用
CredRead时,dwType需设为CRED_TYPE_DOMAIN_PASSWORD(网络共享凭据的标准类型)。
示例代码片段:
CREDENTIALW* pCred = NULL; BOOL ret = CredReadW(L"\\\\your-server\\your-share", CRED_TYPE_DOMAIN_PASSWORD, 0, &pCred); if (ret && pCred->CredentialBlobSize > 0) { DATA_BLOB inBlob = {pCred->CredentialBlobSize, pCred->CredentialBlob}; DATA_BLOB outBlob = {0}; if (CryptUnprotectData(&inBlob, NULL, NULL, NULL, NULL, 0, &outBlob)) { // outBlob.pbData为解密后的明文密码 LocalFree(outBlob.pbData); } CredFree(pCred); }
5. 检查进程权限
确保CreateProcessWithLogon创建的进程拥有SE_NETWORK_LOGON_NAME权限,且令牌为交互式登录令牌(非交互式令牌可能受限访问凭据存储),可通过AdjustTokenPrivileges启用所需权限。
内容的提问来源于stack exchange,提问作者Achim Schön
相关产品推荐
相关产品推荐

