新闻详情

新闻详情

首页 / 资讯中心 / 详情

Windows 通用应用平台 UserCertificateStore 示例:在应用证书存储与用户个人证书存储之间移动证书

发布时间:2026/9/25 2:17:42来源:尧图网络
Windows 通用应用平台 UserCertificateStore 示例:在应用证书存储与用户个人证书存储之间移动证书
示例工程【免费下载链接】Windows-universal-samplesAPI samples for the Universal Windows Platform.项目地址https://gitcode.com/gh_mirrors/wi/Windows-universal-samples点击查看免费下载导读本文基于 Windows-universal-samples 仓库中的 UserCertificateStore 示例完整讲解 UWP 应用如何借助UserCertificateStore类在用户个人证书存储MY 存储中添加与删除证书并实现证书在应用证书存储与用户证书存储之间的双向迁移。读者学完后将掌握CertificateStores、CertificateStore、UserCertificateStore三个核心 API 的配合用法、sharedUserCertificates功能声明的配置方法以及 C# 与 C/WinRT 两种语言的完整实现路径。1. 示例定位与核心概念该示例属于 Windows-universal-samples 仓库中 Identity身份/安全/加密类别下的一个独立样例仓库中对应的三个语言目录为C# 版本C/WinRT 版本共享 XAML 界面示例要解决的问题非常具体UWP 应用默认拥有一个应用级证书存储App 证书存储由CertificateStore类表示而系统级用户个人证书存储User Personal certificate store即常说的MY 存储由UserCertificateStore类表示属于用户账户级别的共享资源。本示例演示了在这两类存储之间安全地移动证书的完整流程。示例明确演示了以下三件事枚举所有证书并根据Certificate.IsPerUser属性区分哪些属于应用证书存储、哪些属于用户证书存储把证书从应用存储移到用户存储先通过UserCertificateStore.RequestAddAsync把证书添加到用户存储再从应用存储中删除把证书从用户存储移到应用存储先通过CertificateStore.Add把证书添加到应用存储再通过UserCertificateStore.RequestDeleteAsync从用户存储中删除。关键前置条件要使用UserCertificateStore类应用必须在清单中声明sharedUserCertificates功能capability。注意UserCertificateStore与CertificateStore是平行的两个类——后者表示的是应用自己的证书存储前者表示的是用户的个人证书存储。这一点在阅读 API 文档与编写代码时务必区分清楚。2. 系统要求与功能声明2.1 最低系统版本根据 README 与两个清单文件的TargetDeviceFamily节点本示例要求Windows 10 版本 14393Windows 10 周年更新 / Build 14393或更高版本清单中以MinVersion10.0.14393.0声明见 C# 清单 与 C/WinRT 清单支持Windows.Universal目标设备家族即面向 PC、平板、手机、Xbox 等全系 UWP 设备。2.2 必须声明 sharedUserCertificates 功能这是使用UserCertificateStore的硬性前提。在Package.appxmanifest的Capabilities节点中加入Capabilities uap:Capability NamesharedUserCertificates/ /Capabilities两个语言版本的清单中均已包含该声明C# 清单 / C/WinRT 清单。该功能名称在仓库源码与 README 中的写法存在两种形式README 中写作sharedUserCertificate单数而实际清单文件中生效的是sharedUserCertificates复数。编写自己的应用时请以清单中实际使用的sharedUserCertificates为准否则功能声明无效UserCertificateStore相关 API 将无法访问用户存储。声明了该功能后应用才有权限读取、添加与删除当前 Windows 登录用户个人证书存储中的证书未声明时调用相关 API 会因缺少权限而失败。3. 示例的项目结构与构建运行3.1 目录结构Samples/UserCertificateStore/ ├── README.md # 示例说明文档本文主体来源 ├── cs/ # C# 版本含 .sln / .csproj / 清单 / 场景代码 ├── cppwinrt/ # C/WinRT 版本含 .sln / .vcxproj / IDL / 场景代码 └── shared/ # 两个语言版本共用的 XAML 界面 └── Scenario1_MoveCertificate.xaml该示例只有一个功能场景ScenarioMove certificate移动证书。场景注册在两个语言的SampleConfiguration中C#见 SampleConfiguration.cs场景标题为Move certificate类型为Scenario1_MoveCertificateC/WinRT见 SampleConfiguration.cpp同样注册Scenario{ LMove certificate, xaml_typenameSDKTemplate::Scenario1_MoveCertificate() }。3.2 构建步骤Visual Studio若通过 ZIP 下载示例请解压整个压缩包而不要只解压单个示例文件夹——示例依赖仓库根目录的SharedContent共享内容ZIP 的extendedZipContent配置中也明确将SharedContent与LICENSE一并打包见 README 的 front-matter。启动 Visual Studio选择文件 → 打开 → 项目/解决方案。在解压目录中依次进入Samples子文件夹 → 本示例文件夹 → 首选语言子文件夹C# 或 C双击解决方案文件.slnC#Samples/UserCertificateStore/cs/UserCertificateStore.slnC/WinRTSamples/UserCertificateStore/cppwinrt/UserCertificateStore.sln按CtrlShiftB或选择生成 → 生成解决方案。3.3 部署与运行仅部署选择生成 → 部署解决方案Deploy Solution。部署并运行调试按F5或选择调试 → 开始调试。部署并运行不调试按CtrlF5或选择调试 → 开始执行不调试。提示由于涉及用户证书存储的读写权限建议以当前登录用户身份运行若需要访问其他账户的证书则属于sharedUserCertificates功能的边界之外不在本示例范围内。4. 界面设计双列表 双向移动按钮共享界面文件 Scenario1_MoveCertificate.xaml 定义了两个上下对称的ListView与两个移动按钮上方AppCertificateListView显示Certificates in the App store应用存储中的证书下方UserCertificateListView显示Certificates in the User store用户存储中的证书中间两个使用 Segoe MDL2 Assets 字体图标的按钮上方按钮图标#xe110;触发MoveUserCertificateToAppCertificateStore把选中证书从用户存储移动到应用存储下方按钮图标#xe1fd;触发MoveAppCertificateToUserCertificateStore把选中证书从应用存储移动到用户存储。该 XAML 位于shared/目录C# 与 C/WinRT 版本通过各自的页面类SDKTemplate.Scenario1_MoveCertificate共享同一套界面布局。5. 核心实现枚举证书并区分存储归属5.1 获取两个存储的句柄场景页面初始化时通过CertificateStores静态工厂方法同时取得两个存储对象C# 实现见 Scenario1_MoveCertificate.xaml.csCertificateStore appStore CertificateStores.GetStoreByName(StandardCertificateStoreNames.Personal); UserCertificateStore userStore CertificateStores.GetUserStoreByName(StandardCertificateStoreNames.Personal);对应的 C/WinRT 写法Scenario1_MoveCertificate.cppappStore{ CertificateStores::GetStoreByName(StandardCertificateStoreNames::Personal()) }, userStore{ CertificateStores::GetUserStoreByName(StandardCertificateStoreNames::Personal()) }两个 API 都使用StandardCertificateStoreNames.Personal即 MY 存储名CertificateStores.GetStoreByName返回CertificateStore——应用自己的证书存储CertificateStores.GetUserStoreByName返回UserCertificateStore——当前用户的个人证书存储MY 存储。5.2 枚举全部证书并按归属分流页面导航进入时OnNavigatedTo调用CertificateStores.FindAllAsync()枚举全部证书再依据Certificate.IsPerUser属性决定放入哪个列表IReadOnlyListCertificate certificates await CertificateStores.FindAllAsync(); foreach (Certificate certificate in certificates) { var item new ListViewItem { Content $Subject: {certificate.Subject}, Serial Number: {CryptographicBuffer.EncodeToHexString(CryptographicBuffer.CreateFromByteArray(certificate.SerialNumber))}, Tag certificate }; if (certificate.IsPerUser) { UserCertificateListView.Items.Add(item); // 用户存储中的证书 } else { AppCertificateListView.Items.Add(item); // 应用存储中的证书 } }要点说明IsPerUser是区分两类存储的关键属性true表示该证书位于用户个人证书存储false表示位于应用证书存储列表项内容同时展示主题Subject与序列号Serial Number其中序列号通过CryptographicBuffer.CreateFromByteArray与CryptographicBuffer.EncodeToHexString转换为十六进制字符串展示每个ListViewItem的Tag中保存了对应的Certificate对象后续移动操作直接从Tag取回证书无需再次查询。C/WinRT 版本在 Scenario1_MoveCertificate.cpp 中以co_awaitfire_and_forget异步协程实现了完全相同的逻辑。6. 核心实现证书双向移动的完整流程6.1 从用户存储移动到应用存储C# 实现Scenario1_MoveCertificate.xaml.csprivate async void MoveUserCertificateToAppCertificateStore(object sender, RoutedEventArgs e) { var item (ListViewItem)UserCertificateListView.SelectedItem; if (item ! null) { var certificate (Certificate)item.Tag; appStore.Add(certificate); // 1. 先添加到应用存储 if (await userStore.RequestDeleteAsync(certificate)) // 2. 请求从用户存储删除 { MoveItemBetweenListViews(item, UserCertificateListView, AppCertificateListView); } else { appStore.Delete(certificate); // 3. 用户拒绝则回滚 } } }该流程的顺序设计值得仔细体会先appStore.Add(certificate)把证书副本加入应用存储再await userStore.RequestDeleteAsync(certificate)向系统请求从用户存储中删除该证书——RequestDeleteAsync会弹出用户确认对话框若证书由其他应用或用户本人安装返回bool表示用户是否同意成功则把列表项从用户列表移到应用列表失败用户拒绝则回滚调用appStore.Delete(certificate)把第一步刚加入的副本删除保持两个存储与界面状态一致。对应 C/WinRT 版本见 Scenario1_MoveCertificate.cpp逻辑一致。6.2 从应用存储移动到用户存储C# 实现Scenario1_MoveCertificate.xaml.csprivate async void MoveAppCertificateToUserCertificateStore(object sender, RoutedEventArgs e) { var item (ListViewItem)AppCertificateListView.SelectedItem; if (item ! null) { var certificate (Certificate)item.Tag; if (await userStore.RequestAddAsync(certificate)) // 1. 请求添加到用户存储 { appStore.Delete(certificate); // 2. 成功后才删除应用存储副本 MoveItemBetweenListViews(item, AppCertificateListView, UserCertificateListView); } } }这一方向的流程同样是先加后删await userStore.RequestAddAsync(certificate)请求把证书加入用户个人存储该方法同样会经过系统确认返回bool只有用户同意后才执行appStore.Delete(certificate)删除应用存储中的原证书若用户拒绝返回false则不做任何改动——应用存储中的证书原样保留天然避免了不一致状态。对应 C/WinRT 版本见 Scenario1_MoveCertificate.cpp。6.3 界面列表的同步移动两个方向的移动成功后都会调用MoveItemBetweenListViews把列表项在上下两个ListView之间搬移并自动选中与滚动到该项C# 实现见 Scenario1_MoveCertificate.xaml.csstatic void MoveItemBetweenListViews(ListViewItem item, ListView source, ListView destination) { source.Items.Remove(item); destination.Items.Add(item); destination.SelectedItem item; destination.ScrollIntoView(item); }C/WinRT 的等价实现位于 Scenario1_MoveCertificate.cpp使用source.Items().IndexOfRemoveAtAppend完成同样的操作。6.4 两种移动方向的异同小结方向第一步第二步失败回滚用户存储 → 应用存储appStore.Add先加userStore.RequestDeleteAsync请求删appStore.Delete回滚应用存储 → 用户存储userStore.RequestAddAsync请求加appStore.Delete确认后删不执行第二步无需回滚共同原则先加后删、确认再删确保任何时刻至少有一份证书可用避免移动过程中证书丢失。7. 涉及的 API 与相关主题7.1 核心 API 一览API作用CertificateStores.GetStoreByName(StandardCertificateStoreNames.Personal)获取应用自己的证书存储CertificateStoreCertificateStores.GetUserStoreByName(StandardCertificateStoreNames.Personal)获取用户个人证书存储UserCertificateStore即 MY 存储CertificateStores.FindAllAsync()枚举应用与用户存储中的全部证书Certificate.IsPerUser判断证书归属用户存储true或应用存储falseCertificateStore.Add / Delete在应用证书存储中直接添加/删除证书无需用户确认UserCertificateStore.RequestAddAsync / RequestDeleteAsync请求在用户证书存储中添加/删除证书需用户确认返回bool从源码可以推断的设计要点CertificateStore.Add/Delete操作的是应用自有存储因此是同步、直接的而UserCertificateStore触及用户账户级共享存储必须通过带Request前缀的异步确认 API 执行这正是两类存储 API 形态差异的原因。7.2 相关参考与旧版示例README 中关联的参考主题包括UserCertificateStore类、CertificateStores类、CertificateStore类均属于Windows.Security.Cryptography.Certificates命名空间仓库的 archived/UserCertificateStore 目录保留了旧版 C/CX 与 JavaScript 实现可作为历史参考新版仓库中该示例仅提供 C# 与 C/WinRT 两种语言版本。8. 源码级要点回顾功能声明uap:Capability NamesharedUserCertificates/是使用UserCertificateStore的必要条件见 C# 清单 与 C/WinRT 清单存储句柄获取同一场景中同时持有CertificateStore应用与UserCertificateStore用户两个对象通过StandardCertificateStoreNames.Personal指定 MY 存储归属判定FindAllAsync枚举结果按IsPerUser分流到两个ListView双向移动两个方向都遵循先加后删策略其中涉及用户存储的操作一律走RequestAddAsync/RequestDeleteAsync用户确认流程界面共享C# 与 C/WinRT 共享 Scenario1_MoveCertificate.xaml仅在代码后端C# / C/WinRT上分语言实现。按 README 的要求构建前请确保已解压整个示例集合含SharedContent最低在 Windows 10 Build 14393 及以上环境运行即可在 Visual Studio 中直接复现上述证书迁移的全部行为。赞分享示例工程【免费下载链接】Windows-universal-samplesAPI samples for the Universal Windows Platform.项目地址https://gitcode.com/gh_mirrors/wi/Windows-universal-samples点击查看免费下载相关推荐Traefik 证书配置完全指南用户自定义证书、证书存储与默认证书Certificates StoresTraefik 证书配置完全指南用户自定义证书、证书存储与默认证书Certificates Stores 本篇技术指南围绕 Traefik云原生应用后端API网关负载均衡微服务网络云原生使用 Salt 的 win_pki 状态管理 Windows 证书存储导入与移除证书实战指南使用 Salt 的 win_pki 状态管理 Windows 证书存储导入与移除证书实战指南 导读 win_pki 是 Salt 提供的一个面向 Window运维配置管理后端HsMod终极指南55项功能全面解锁炉石传说游戏体验HsMod终极指南55项功能全面解锁炉石传说游戏体验 HsMod是基于BepInEx框架开发的炉石传说多功能插件提供了55项实用功能涵盖游戏加速、界面优化游戏开发上一篇一步成图革命Consistency Model如何重塑2025生成式AI生态下一篇5步掌握PyBullet UR5机械臂仿真从环境搭建到智能抓取实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Miniconda vs Anaconda:虚拟环境管理与PyTorch CUDA配置实战 2026/9/25 4:54:42

Miniconda vs Anaconda:虚拟环境管理与PyTorch CUDA配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
STM32F407移植FreeRTOS与LwIP:从CubeMX配置到TCP通信实战 2026/9/25 4:54:42

STM32F407移植FreeRTOS与LwIP:从CubeMX配置到TCP通信实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
从AI对话Demo到可演进Agent平台:架构设计与工程实践 2026/9/25 4:54:42

从AI对话Demo到可演进Agent平台:架构设计与工程实践

开篇:从 AI 对话 Demo 到可演进的 Agent 平台这两年 AI 圈最热闹的词,一个是“AI”,一个是“Agent”。市面上 Demo 满天飞,今天一个聊天机器人,明天一个自动写周报的工具,后天又冒出个能帮你订机票的智能体…

阅读更多 →
TypeDoc @include 与 @includeCode 标签实战指南:在文档注释中嵌入外部文件、代码区域与行号片段 2026/9/25 4:54:30

TypeDoc @include 与 @includeCode 标签实战指南:在文档注释中嵌入外部文件、代码区域与行号片段

开发工具文档 【免费下载链接】typedoc Documentation generator for TypeScript projects. 项目地址: https://gitcode.com/gh_mirrors/ty/typedoc 点击查看 免费下载 TypeDoc 的 {include} 标签族允许你在 TSDoc 文档注释或外部 Markdown 文档中直接嵌入仓库里的…

阅读更多 →
LTSPICE参数变量与参数扫描实操指南:批量仿真高效探索设计空间 2026/9/25 4:54:24

LTSPICE参数变量与参数扫描实操指南:批量仿真高效探索设计空间

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
机械仪表与自动化会议论文投稿指南:EI/Scopus检索与见刊策略 2026/9/25 4:54:24

机械仪表与自动化会议论文投稿指南:EI/Scopus检索与见刊策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉