Windows凭据提供者:修改RDP登录新磁贴的用户名标签
自定义凭据提供者修改RDP登录磁贴标题/创建专属用户磁贴方案
问题背景
在Windows服务器上通过自定义凭据提供者实现RDP登录,已通过UpdateRemoteCredential传输登录数据并成功登录,核心代码如下:
pcpcsOut->ulAuthenticationPackage = pcpcsIn->ulAuthenticationPackage; pcpcsOut->cbSerialization = pcpcsIn->cbSerialization; pcpcsOut->rgbSerialization = pcpcsIn->rgbSerialization; pcpcsOut->clsidCredentialProvider = CLSID_CSamanV2Provider; if (pcpcsOut->cbSerialization > 0 && (pcpcsOut->rgbSerialization = static_cast<BYTE*>(CoTaskMemAlloc(pcpcsIn->cbSerialization))) != nullptr) { CopyMemory(pcpcsOut->rgbSerialization, pcpcsIn->rgbSerialization, pcpcsIn->cbSerialization); return S_OK; }
随后通过自定义Initialize函数创建自动登录磁贴:
_rgpCredentials[0]->Initialize(_cpus, s_rgCredProvFieldDescriptors, s_rgFieldStateNormalPairs, _dwCredUIFlags, wszDomain, wszUsername, wszPassword);
当前磁贴标题为“其他用户”,需求是将其改为RDP登录对应的用户名,或创建该用户的专属磁贴。
解决方案
修改磁贴标题为RDP登录用户名
磁贴的显示标题由CREDENTIAL_PROVIDER_FIELD_DESCRIPTOR结构体中的pszLabel字段控制,对应类型为CPFT_TILE_TITLE的字段(通常是凭据字段数组的第一个元素)。只需在调用Initialize前修改该字段的pszLabel值即可:
- 找到定义磁贴标题的字段(假设为数组索引0),将其
pszLabel设置为传入的RDP登录用户名(可拼接域名) - 确保字段状态包含
CPFS_DISPLAY_IN_SELECTED_TILE和CPFS_DISPLAY_IN_DESELECTED_TILE,保证标题在磁贴选中/未选中状态下都显示 - 注意
pszLabel的内存需通过CoTaskMemAlloc分配,框架会自动释放
示例代码:
// 拼接域名与用户名(可选) WCHAR szTileTitle[256] = {0}; swprintf_s(szTileTitle, L"%s\\%s", wszDomain, wszUsername); // 分配内存并设置标题 s_rgCredProvFieldDescriptors[0].pszLabel = static_cast<WCHAR*>(CoTaskMemAlloc((wcslen(szTileTitle) + 1) * sizeof(WCHAR))); if (s_rgCredProvFieldDescriptors[0].pszLabel) { wcscpy_s(s_rgCredProvFieldDescriptors[0].pszLabel, wcslen(szTileTitle) + 1, szTileTitle); } // 初始化凭据对象 _rgpCredentials[0]->Initialize(_cpus, s_rgCredProvFieldDescriptors, s_rgFieldStateNormalPairs, _dwCredUIFlags, wszDomain, wszUsername, wszPassword);
创建指定用户的专属磁贴
Windows凭据提供者支持为特定用户创建专属磁贴,无需显示“其他用户”:
- 通过
LookupAccountName函数,根据RDP传入的wszDomain和wszUsername获取用户SID - 在凭据对象初始化时,将用户SID绑定到凭据(部分自定义凭据实现会提供绑定SID的接口,或需在凭据类内部维护SID属性)
- 在凭据提供者的
GetCredentialCount方法中,根据缓存的RDP登录用户信息创建对应凭据对象,系统会识别为该用户的专属磁贴
关键步骤示例:
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY; PSID pUserSid = nullptr; DWORD cbSid = 0; WCHAR szDomainName[256] = {0}; DWORD cchDomainName = 256; SID_NAME_USE snu; // 获取用户SID if (LookupAccountName(nullptr, wszUsername, nullptr, &cbSid, szDomainName, &cchDomainName, &snu)) { pUserSid = static_cast<PSID>(CoTaskMemAlloc(cbSid)); if (pUserSid) { LookupAccountName(nullptr, wszUsername, pUserSid, &cbSid, szDomainName, &cchDomainName, &snu); // 将SID绑定到凭据对象(需自定义凭据类支持该接口) _rgpCredentials[0]->SetUserSid(pUserSid); } } // 初始化凭据对象 _rgpCredentials[0]->Initialize(_cpus, s_rgCredProvFieldDescriptors, s_rgFieldStateNormalPairs, _dwCredUIFlags, wszDomain, wszUsername, wszPassword);
注意事项
- 修改后需注销当前会话或重启
Credential Manager服务(VaultSvc)才能生效 - 多用户场景下需为每个登录用户创建独立的凭据对象,避免磁贴冲突
- 内存分配需严格使用
CoTaskMemAlloc,避免内存泄漏
内容的提问来源于stack exchange,提问作者VOLVO
相关产品推荐
相关产品推荐

