Win10/UWP开发—凭据保险箱PasswordVault

PasswordVault用户凭据保险箱其实并不算是Win10的新功能,早在Windows 8.0时代就已经存在了,本文仅仅是介绍在UWP应用中如何使用凭据保险箱进行安全存储和检索用户凭据。

那么什么是凭据保险箱呢?简单的说就是开发者可以在用户输入完凭证(一般是用户名和密码),凭证有效的情况下将该凭证存储在叫做"凭据保险箱"里,该凭据保险箱里的用户凭据将会自动漫游到用户设备的Windows账户中并随时能够再次被App获取。

例如:有一个UWP的App运行在PC上,某用户在使用该App时登录了自己的账户并允许将账户凭据保存在"凭据保险箱"中,那么当该用户再使用平板电脑、手机或者其他同一个Windows账户的Windows设备时第一次打开该App,我们就可以从Windows账户中将该用户的数据漫游到新设备进行用户登录的操作。

说的简单点就是用户的账户和密码会被漫游到Windows账户中,日后及时是跨设备使用该App,只要设备Windows账户没变,就可以实现在新设备上快捷登陆的功能。

要想使用"凭据保险箱",我们需要了解以下几个类:


– Windows.Security.Credentials.PasswordVault 表示凭据的"凭据保险箱"

保险箱的内容特定于应用程序或服务。应用程序和服务无法访问与其他应用程序或服务关联的凭据。

– PasswordVault.Add(PasswordCredential credential); 添加一个凭证保险箱

– PasswordVault.Remove(PasswordCredential credential); 移除一个凭证保险箱

– PasswordVault.Retrieve(System.String resource, System.String userName); 读取一个凭证保险箱

– PasswordVault.FindAllByResource(System.String resource); 搜索与指定资源相匹配的凭据保险箱

– Windows.Security.Credentials.PasswordCredential 表示凭据对象

– PasswordCredential.PasswordCredential(System.String resource, System.String userName, System.String password); 创建一个凭据对象

– PasswordCredential.UserName 凭据对象存储的UserName

– PasswordCredential.Resource 凭据对象所属的资源名

– PasswordCredential.Password 凭据对象存储的密码

 

我们通过例子来看一下"凭据保险箱"是如何工作的(注:本文不考虑实现 记住密码 自动登陆 功能

首先创建一个UWP通用项目,

然后新建一个LoginPage页面,并将起始页改为LoginPage页面

在LoginPage上布局出一个登陆框如下:

xaml代码:

 1 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
 2     <StackPanel Margin="0,0,0,128" HorizontalAlignment="Center" VerticalAlignment="Center">
 3         <StackPanel Orientation="Horizontal">
 4             <TextBlock Text="账  户:"/>
 5             <TextBox Text="{x:Bind UserName,Mode=TwoWay}" PlaceholderText="请输入您的账户" Width="240"/>
 6         </StackPanel>
 7         <StackPanel Margin="0,4" Orientation="Horizontal">
 8             <TextBlock Text="密  码:"/>
 9             <PasswordBox PlaceholderText="请输入您的密码" Password="{x:Bind Psw,Mode=TwoWay}" Width="240"/>
10         </StackPanel>
11
12         <CheckBox IsChecked="{x:Bind RoamCredential,Mode=TwoWay}"  Content="漫游我的登录凭证" HorizontalAlignment="Right" ToolTipService.ToolTip="勾选漫游凭证后,您的登录信息将被漫游到本机WindowsLive账户"  />
13
14         <Grid Margin="0,12,0,0" >
15             <Button  Click="{x:Bind QuickLogin}" Content="WindowsLive快捷登陆"/>
16             <Button Click="{x:Bind Login}" Content="登  录" HorizontalAlignment="Right"/>
17         </Grid>
18     </StackPanel>
19 </Grid>

后台代码中,我们先实现"登录按钮"的Click方法:

 1         private async void Login(object sender, RoutedEventArgs args)
 2         {
 3             // 假设做用户账户和密码的验证工作(这里不考虑登录是否成功 一律登录成功)
 4             await ShowLoding();
 5             if (RoamCredential != true) return;
 6             //添加用户凭证到 PasswordVault
 7             var vault = new PasswordVault();
 8             vault.Add(new PasswordCredential(
 9                 _resourceName, UserName, Psw));
10         }
11
12         /// <summary>
13         /// 显示登陆中Tip 并跳转到MainPage
14         /// </summary>
15         /// <returns>Null</returns>
16         private async Task ShowLoding()
17         {
18             var dialog = new ContentDialog
19             {
20                 Title = "提示",
21                 Content = "正在登录",
22                 IsPrimaryButtonEnabled = true
23             };
24 #pragma warning disable CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法
25             dialog.ShowAsync();
26 #pragma warning restore CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法
27
28             await Task.Delay(2000);
29             dialog.Content = "登录成功";
30             await Task.Delay(1000);
31             dialog.Hide();
32             Frame.Navigate(typeof(MainPage), _userName);
33         }

假设用户的用户名和密码验证通过情况下,如果用户允许保存凭据到 "凭据保险箱",我们就可以使用PasswordVault对象的Add方法添加到"凭据保险箱"里一个PasswordCredential 凭据对象,然后跳转到MainPage,并传递用户名。

当用户点击使用"Windows账户快捷登陆"按钮时,我们首先去检测在该App的ResourceName下,一共有几个用户凭据,如果有多个则需要让用户选择一个账户进行登陆,代码如下:

 1 private async void QuickLogin(object sender, RoutedEventArgs args)
 2 {
 3     var credential = await GetCredentialFromLocker();
 4     if (credential == null) return;
 5     UserName = credential.UserName;
 6     Psw = credential.Password;
 7     await ShowLoding();
 8 }
 9 /// <summary>
10 /// 获取密码凭证
11 /// </summary>
12 /// <returns>PasswordCredential</returns>
13 private async Task<PasswordCredential> GetCredentialFromLocker()
14 {
15     PasswordCredential credential = null;
16
17     var vault = new PasswordVault();
18     var credentialList = vault.FindAllByResource(_resourceName);
19     if (credentialList.Count > 0)
20     {
21         if (credentialList.Count == 1)
22         {
23             credential = credentialList[0];
24         }
25         else
26         {
27             _defaultUserName = await GetDefaultUserNameUI(credentialList.Select(s => s.UserName));
28             if (!string.IsNullOrEmpty(_defaultUserName))
29             {
30                 //读取凭证
31                 credential = vault.Retrieve(_resourceName, _defaultUserName);
32             }
33         }
34     }
35
36     return credential;
37 }
38
39 /// <summary>
40 /// 获取一个用户名,如果存在多个用户凭证则选择一个
41 /// </summary>
42 /// <param name="userList">用户名集合</param>
43 /// <returns>UserName</returns>
44 private async Task<string> GetDefaultUserNameUI(IEnumerable<string> userList)
45 {
46     var userName = string.Empty;
47     var dialog = new ContentDialog
48     {
49         Title = "账户选择",
50         IsPrimaryButtonEnabled = true,
51         IsSecondaryButtonEnabled = true,
52         BorderThickness = new Thickness(0, 0, 1, 1),
53         PrimaryButtonText = "确定",
54         SecondaryButtonText = "取消"
55     };
56     var sp = new StackPanel();
57     var tb = new TextBlock { Text = "请选择您要登录哪个账户:" };
58     var cm = new ComboBox();
59     foreach (var user in userList)
60     {
61         // ReSharper disable once PossibleNullReferenceException
62         cm.Items.Add(new TextBlock
63         {
64             Text = user
65         });
66     }
67     cm.SelectedIndex = 0;
68     sp.Children.Add(tb);
69     sp.Children.Add(cm);
70     dialog.Content = sp;
71     dialog.PrimaryButtonClick += (s, a) =>
72     {
73         // ReSharper disable once PossibleNullReferenceException
74         userName = (cm.SelectedItem as TextBlock).Text;
75     };
76     dialog.SecondaryButtonClick += (s, a) => { dialog.Hide(); };
77     await dialog.ShowAsync();
78     return userName;
79 }

至此我们的App就支持了使用“凭据保险箱”功能,只要Windows账户一致,不论在什么windows设备上我们都可以做快捷登陆,下面是效果(本机demo的Win账户是公司的账户,和自己的手机上账户不一致,没法演示跨设备,不过我们可以使用删除App重新安装的方式来查看凭据是否被漫游了,答案是肯定的)

推荐一个UWP开发群:53078485 大家可以进来一起学习

时间: 2024-08-29 20:21:58

Win10/UWP开发—凭据保险箱PasswordVault的相关文章

Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App

安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneGap.ionic.AngularJS这些框架或库的关系,我个人理解是这样,PhoneGap是一个商业项目,用来实现HTML5式的跨平台开发,后来Adobe公司将其中的核心代码开源,就是Cordova,Cordova只负责实现JavaScript调用原生代码的功能,是一个壳,而壳里具体用什么样式,在H

Win10 UWP开发系列:解决Win10不同版本的Style差异导致的兼容性问题

原文:Win10 UWP开发系列:解决Win10不同版本的Style差异导致的兼容性问题 最近在开发一个项目时,遇到了一个奇怪的问题,项目依赖的最低版本是10586,目标版本是14393,开发完毕发布到商店后,很多用户报无法正常加载页面.经查,有问题的都是Win10 10586版本. 我上篇博客中写到的自定义的AppBar控件,也存在这个问题,10586会报错. 为此特意下载了10586的SDK调试.错误显示,一个样式找不到,名为ListViewItemBackground.因为开发的时候是基于

Win10 UWP开发系列——开源控件库:UWPCommunityToolkit

原文:Win10 UWP开发系列--开源控件库:UWPCommunityToolkit 在开发应用的过程中,不可避免的会使用第三方类库.之前用过一个WinRTXamlToolkit.UWP,现在微软官方发布了一个新的开源控件库—— UWPCommunityToolkit 项目代码托管在Github上:https://github.com/Microsoft/UWPCommunityToolkit 包括以下几个类库: 都可以很方便的从Nuget上安装. NuGet Package Name des

Win10/UWP开发—使用Cortana语音与App后台Service交互

上篇文章中我们介绍了使用Cortana调用前台App,不熟悉的移步到:Win10/UWP开发—使用Cortana语音指令与App的前台交互,这篇我们讲讲如何使用Cortana调用App的后台任务,相比调用前台的App,调用后台任务有个有点就是App不用被启动即可为用户提供服务. 要想使用Cortana调用App后台任务,首先我们需要定义VCD文件,我们依旧使用上篇中的代码,让它支持Cortana调用后台任务. 创建后台任务 新增一个[Windows运行时组件]项目,暂时起名叫做:XiaoMiBa

Win10 UWP开发系列:实现Master/Detail布局

在开发XX新闻的过程中,UI部分使用了Master/Detail(大纲/细节)布局样式.Win10系统中的邮件App就是这种样式,左侧一个列表,右侧是详情页面.关于这种 样式的说明可参看MSDN文档:https://msdn.microsoft.com/zh-cn/library/windows/apps/xaml/dn997765.aspx 样式如下: 在微软官方的Sample里,有这种样式的代码示例,下载地址:https://github.com/Microsoft/Windows-univ

Win10 UWP开发实现Bing翻译

微软在WP上的发展从原来的Win7到Win8,Win8.1,到现在的Win10 UWP,什么是UWP,UWP即Windows 10 中的Universal Windows Platform简称.即Windows通用应用平台,在Win 10 Mobile/Surface(Windows平板电脑)/PC/Xbox/HoloLens等平台上运行,uwp不同于传统pc上的exe应用也跟只适用于手机端的app有本质区别.它并不是为某一个终端而设计,而是可以在所有windows10设备上运行. 简单的说,u

Win10/UWP开发—使用Cortana语音指令与App的前台交互

Win10开发中最具有系统特色的功能点绝对少不了集成Cortana语音指令,其实Cortana语音指令在以前的wp8/8.1时就已经存在了,发展到了Win10,Cortana最明显的进步就是开始支持调用App 的App Service.当然App Service也是Win10 App的新特性之一,通过调用App Service就可以在App没有前台运行的时候为Cortana提供数据交互.这样一来Cortana就具有了两种App交互方式: Cortana语音指令与前台App的交互 Cortana语

Win10 UWP 开发系列:使用SQLite

在App开发过程中,肯定需要有一些数据要存储在本地,简单的配置可以序列化后存成文件,比如LocalSettings的方式,或保存在独立存储中.但如果数据多的话,还是需要本地数据库的支持.在UWP开发中,可以使用SQLite.本篇文章说一下如何在UWP中使用SQLite.因为SQLite是跨平台的,版本众多,我刚开始用的时候不知道要装哪个,什么WP8的.WP8.1的.Win RT的……简直摸不着头脑.希望这篇文章能让大家少走点弯路. 其实这篇文章写到一半就看到已经有大神写了这个:http://ww

Win10/UWP开发-Ink墨迹书写

在UWP开发中,微软提供了一个新型的InkCanvas控件用来让用户能书写墨迹,在新版的Edga浏览器中微软自己也用到了该控件使用户很方便的可以在web上做笔记. InkCanvas控件使用很简单,从工具箱里拖出一个InkCanvas控件即可,InkCanvas有个属性叫InkPresenter,通过它我们可以多样化的设置我们的画笔属性,InkPresenter里面有几个重要的属性: 1 // 获取或设置输入数据用于从中提取 InkStroke 的输入设备类型. 2 3 public CoreI