新型应用程序

Windows 应用商店应用中的身份验证和标识

Rachel Appel

Rachel Appel目前,绝大多数的应用程序和网站都要求使用某种形式的登录或凭据。原因之一是,它们中有许多可以根据已保存的用户首选项来自定义体验。因为需要用户登录的站点和应用程序众多,所以您需要使用户登录的操作简单化。在本文中,您将了解 Windows 平台上通过启用 Microsoft 帐户或第三方登录以及作为补充的身份验证方法(如智能卡或生物身份验证)进行应用程序身份验证的基础知识。

新型应用程序身份验证和用户标识

很多时候,对用户而言,收集用户凭据比丰富体验更为痛苦。因此,当您必须存储用户凭据时,您希望能够通过一种既可以保证安全性又可以保持易用性的方式来实现。

使用独立的凭据提供程序,例如 Microsoft 帐户(以前的 Windows Live ID)、Facebook 或 OAuth,会是您依靠受信任实体管理和存储用户信息的一种很不错的方式。同时,它还为用户提供了一种持久稳固的个性化 UI。此外,我们不得不面对一个事实:用户根本记不得他所有的密码,尤其是他不常使用的站点和应用程序的密码。要求用户创建和记住另一组凭据只会给他的体验添加苦恼而已。光是这一点就可能会导致对您的应用商店评价下降,与您想达到的效果背道而驰。

在开发人员方面,存储用户凭据意味着比起使用诸如 Facebook 登录之类的工具,需要编写更多的代码、进行更多的测试和 Bug 修复。将登录数据存储在本地数据库中也可能存在安全漏洞。您可以通过使用受信任的实体(如 Microsoft、Facebook、Twitter、OAuth 或任何可信的第三方凭据服务)减轻用户和自己的压力。该服务使用合适的算法存储用户凭据和私人信息,因此较为安全。您需要做的只是对 API 进行调用,让其为您执行所有繁重的工作。

使用 Microsoft 帐户

当使用 Microsoft 帐户时,用户期望登录体验能够与 Windows 登录相似、一致。不用自己创建用于收集信息的 UI 控件,而应该使用 Microsoft 帐户 API 随附的控件。幸运的是,这让编码也变得更加简单。对登录信息进行编码是一个无聊的工作,可以而且应该使用诸如 Microsoft 帐户 API 之类的 API 提取。

如果您需要登录,应在启动该应用程序时,显示登录 UI。如果用户可以在会话之间保持登录状态,或不需要登录,可将其添加到“设置”中。另外,不要忘记确保用户可以注销。这是很容易忘记的,因为许多用户喜欢对其喜爱的网站和应用程序保持登录状态。

如果有人需要借用电话或设备,就可能会出问题。如果只能登录而不能注销,下一个使用的人就有可能使用该应用程序,并伪装成第一个人在用。另一方面,第一个人可能会因无法在初始处注销而永远无法分享他的设备。

务必让用户可以很容易地从您应用程序的所有屏幕上看到他/她保持登录状态。这并不一定是一个枯燥的文字更新。您可以在用户的 OneDrive 照片存储中显示他的头像或者一些照片(如果使用 Microsoft 帐户的话)。创意无极限,只要用户可以轻松看到并改变他的状态即可。常用的一种方法是在应用程序的右上角显示用户的头像缩略图。

Microsoft 帐户身份验证

使用 Microsoft 帐户身份验证为您提供对所有 Microsoft Live 服务(如 OneDrive、Outlook.com、MSDN 订阅、Xbox,甚至是 Windows 8 设备和应用程序)的流畅登录体验。

为了能够使用可能包含敏感用户信息的服务,您必须使用 Microsoft 开发人员中心在线登录应用程序 (bit.ly/1egpvHx)。这样做可以让您在您的应用程序中使用 Microsoft 帐户服务,以便您可以将用户连接到各种资源。

因为您正在使用可以访问个人数据的服务,所以需要在应用程序中提供一个可访问的明确的隐私声明。如果您需要帮助编写一个隐私策略,您可以使用 myapppolicy.comw8privacy.azurewebsites.net 帮助您生成一个。当您建立了隐私策略之后,可以用“设置”浮出控件来显示该隐私策略。

最后,您需要提供用于登录和注销的代码。为此,您可以使用一个包含登录按钮(此按钮在登录之后变为注销按钮)的浮出控件。这些按钮会启动执行相应登录或注销操作的对话框。图 1 显示创建“帐户设置”浮出控件的 XAML。

图 1 此代码创建“帐户设置”浮出控件

<SettingsFlyout
  x:Class="App.Account"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="using:App"
  xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d"
  IconSource="Assets/SmallLogo.png"
  Title="Account"
  d:DesignWidth="346">
  <StackPanel x:Name="accountSettings">
    <Button x:Name="SignInButton" Click="SignInClick" Content="Sign in" />
  </StackPanel>
</SettingsFlyout>

正如您所看到的,它是用一个带有按钮的控件。 该按钮是用户启动登录界面所使用的按钮。 将登录按钮放在浮出控件中是一个习惯做法。 若要了解有关创建“设置”浮出控件的详细信息,请参阅“精通 Windows 应用商店应用中的控件和设置”(bit.ly/1hy7Fk2)。 让用户通过单击登录按钮事件而登录到您的应用程序的代码应如下:

private async void SignInButton_Click(object sender, 
  RoutedEventArgs e)
{
  LiveAuthClient authClient = new LiveAuthClient();
  LiveLoginResult authResult =
    await authClient.LoginAsync(new List<string>() 
   { "wl.signin", "wl.basic"  });
  if (authResult.Status == LiveConnectSessionStatus.Connected)
  {
    // Perform post authentication duties
  }
}

如果用户尚未登录,它就会显示 Microsoft 帐户登录屏幕(通常称为登录同意页)(见图 2)。 正如您所看到的,实现登录过程并不需要太多的代码。 您可以使用 LiveAuthClient 的 Session 属性在整个应用程序中查询会话状态。

The Microsoft Account Sign-in Screen
图 2 Microsoft 帐户登录屏幕

您可以执行与 HTML 和 JavaScript 同样的活动,但步骤略有不同。 首先,通过“添加引用”命令引用 Windows Live SDK。 然后,作为在 HTML 开发中的惯例,在 HTML 文档中使用 <script> 标签来引用脚本,如下所示:

<script src="///LiveSDKHTML/js/wl.js"></script>

但是,您可能希望在开发过程中使用调试版本。 在这种情况下,您可以使用以下引用:

<script src="//js.live.
net/v5.0/wl.debug.js"></script>

图 3 包含让用户登录的 WinJS 代码。 您需要调用 WL.init 和 WL.Event.subscribe,以便可以初始化 Microsoft 帐户,以及对登录时所发生的事件进行订阅。 XAML 应用程序不需要进行该初始化。 在登录事件中,可以显示连接状态或登录后即需进行的操作。

图 3 让用户登录的 WinJS 代码

(function () {
  "use strict";
  WL.init();
  WL.Event.subscribe("auth.login", loginComplete);
  document.querySelector("#SignInButton").addEventListener("click",
    function () {
      login();
    });
  function loginComplete() {
    WinJS.log("User has signed in!")
  }
  function login() {
    var session = WL.getSession();
    if (session) {
      WinJS.log("You are already signed in!")
    }
    else {
      WL.login({ scope: "wl.basic" }).then(
        function () {
          // Perform post authentication duties
        },
        function (response) {
          WinJS.log("Could not connect, status = " + response.status);
        });
    }   
  }
})();

图 3 中的代码执行的操作与其相对应的 XAML 相同,即实际上让用户登录。 无论您使用何种语言,wl.login 方法都需要您传入某个作用域。 作用域是一个权限级别,或是应用程序可以代表用户并代表其执行操作的范围。 正如您可能想到的,作用域是用户控制的。 您可以在扮作用户的角色过程中尝试做您想要做的任何事情,但 Windows 运行时会迫使您先要取得用户的同意,然后才能继续。

Web 身份验证代理 (OAuth)

使用集中客观的第三方凭据服务(如 Microsoft 帐户、Facebook、Twitter、LinkedIn、OAuth 等等)是一个很好的身份验证策略。 用户更容易记住他们经常访问或更为喜欢的站点密码。 使用一个知名的验证器也意味着您可以关注更少的基础结构代码,为业务逻辑或 UI 工作的研究留出更多的时间。

Web 身份验证代理是一种便于执行身份验证的方法。 通过 Web 身份验证代理,您可以省去处理安全存储用户信息的麻烦。 相反地,您还能正确地加密所有的个人信息。 Web 身份验证代理是应用程序和身份验证提供程序之间的联络中枢。 这也使得跨多个应用程序的单一登录得以实现。

在代码中调用 Web 身份验证代理,以从特定的身份验证服务(如 Facebook)检索并显示对话框或网页(见图 4)。 该对话框与用户平常在登录提供程序的网站或应用程序时所见到的登录屏幕相同。 在大多数情况下,您可以进行自定义,以使它看起来像似您应用程序的一个自然组成部分。

图 4 使用 Web 身份验证代理登录

async public Task<string> WebAuthenticate(){
  string startURL =
    "https://<providerendpoint>?client_
    id=<clientid>&scope=<scopes>&response_type=token";
  string endURL = "http://<appendpoint>";
  System.Uri startURI = new System.Uri(
    "https://<providerendpoint>?client_
    id=<clientid>&scope=<scopes>&response_type=token");
  System.Uri endURI = new System.Uri(
    "http://<appendpoint>");
  string result;
  try
  {
    var webAuthenticationResult =
      await WebAuthenticationBroker.AuthenticateAsync(
      WebAuthenticationOptions.None,
      startURI,
      endURI);
    switch (webAuthenticationResult.ResponseStatus)
    {
      case WebAuthenticationStatus.Success:
        result = webAuthenticationResult.ResponseData.ToString();
        break;
      case WebAuthenticationStatus.ErrorHttp:
        result = 
          webAuthenticationResult.ResponseErrorDetail.ToString();
        break;
      default:
        result = webAuthenticationResult.ResponseData.ToString();
        break;
    }
  }
  catch (Exception ex)
  {
    result = ex.Message;
  }
  return result;
}

智能卡身份验证

Microsoft 早已使用智能卡作为一种用来验证到公司网络的 VPN 连接,以及提供对建筑物及其他公司资源进行安全访问的方法。 现在,您可以轻松地将智能卡并入您的软件中。 Windows.Devices.SmartCards 命名空间包含的类(SmartCard 和 SmartCardConnection)让您能够编写用来验证和管理智能卡的代码。 虽然智能卡好像过于复杂,但实际上则不然。 例如,如果您想验证什么卡目前位于阅读器中,可以编写类似下面的代码:

string selector = SmartCardReader.GetDeviceSelector();
DeviceInformationCollection devices = 
  await DeviceInformation.FindAllAsync(selector);
foreach (DeviceInformation device in devices)
{
  SmartCardReader reader =
    await SmartCardReader.FromIdAsync(device.Id);
  IReadOnlyList<SmartCard> cards = await reader.FindAllCardsAsync();
}

请注意,Windows.Devices.DeviceInformation 获取有关每个设备的信息。 在 Windows 中,这是查询硬件的标准方法。 Windows 运行时显示许多与硬件进行通信的对象,而这些硬件之前是无法供 .NET 开发人员使用的。

生物身份验证

虽然由于许多设备和机器都不支持该硬件,您不太可能使用除标准用户名/密码技术以外的身份验证形式,但您仍可以使用已存储和已注册的指纹来读取软件。 这是一个强大的功能,对那些有访问需求的人也非常有帮助。

请考虑使用 Lenovo Carbon Touch X1 便携式计算机。 这种机型在靠近键盘处有一个指纹读取器内置在便携式计算机中。 Windows 8 生物身份验证使您可以使用此类型的身份验证。 图 5 显示您将用于生物身份验证的代码。

图 5 指纹身份验证

var availability = 
  await UserConsentVerifier.CheckAvailabilityAsync();
if (UserConsentVerifierAvailability.Available) {
  var consentResult = 
  await UserConsentVerifier.RequestVerificationAsync(userMessage);
}
var consentResult = 
  await UserConsentVerifier.RequestVerificationAsync(userMessage);
switch (consentResult)
{
  case UserConsentVerificationResult.Verified:
    returnMessage = "Fingerprint verified.";
    break;
  case UserConsentVerificationResult.DeviceBusy:
    returnMessage = "Biometric device is busy.";
    break;
  case UserConsentVerificationResult.DeviceNotPresent:
    returnMessage = "No biometric device found.";
    break;
  case UserConsentVerificationResult.NotConfiguredForUser:
    returnMessage = "The user has no fingerprints registered.";
    break;
  case UserConsentVerificationResult.RetriesExhausted:
    returnMessage = "Too many failed attempts.";
    break;
  case UserConsentVerificationResult.Canceled:
    returnMessage = "Fingerprint authentication canceled.";
    break;
  default:
    returnMessage = "Fingerprint authentication is currently unavailable.";
    break;
}

图 5 中的代码显示一个类似于图 2 的模式对话框,区别在于:它会在调用 CheckAvailabilityAsync 过程中提示用户在生物识别设备上扫描他们的手指。在用户扫描了手指之后,您可以查询一致性结果,看它是否是一个可验证的扫描。

注销

通过使用 Microsoft 帐户,您可以提供无缝集成到 Windows 8 中的丰富一致的体验。现在,您有多种身份验证提供程序,您应该在生成自己的之前使用它们。无论您使用 Twitter、Facebook、Microsoft,还是其他方法,安全地管理用户私人信息而面临的挑战和问题都已得到解决。这些提供程序也会将安全性保持为最新状态。这使得知名的第三方验证成为新型应用程序身份验证的最佳选择。

除非它是绝对必要的,否则不要创建自己的算法来存储用户的私人信息。如果您需要保留这些信息,请使用诸如“凭据保险箱”之类的服务。您可以使用“凭据保险箱”安全地保留用户凭据。这为应用程序提供了一种跨应用程序会话使用户自动登录的方法,因为她的凭据存储在可启用漫游的云保管库中。

当您的应用程序在多个设备(如平板电脑和手机)上运行时,漫游是一个必须具备的功能。通过使用“凭据保险箱”,您可以安全地锁定凭据,也可以在您应用程序的不同版本以及社交网络或其他外部站点之间进行传递。此外,您不必维护基础结构来存储用户信息。您可以在 bit.ly/1qFxfmG 找到有关“凭据保险箱”的详细信息。

有了像生物身份验证这类增强的身份验证,您商店的应用程序一定会获得最好的评价。UI 时尚美观、易于使用且具有所有的附加功能。并非所有设备都会具有完全相同的身份验证外围设备,因此不要将生物识别之类的身份验证作为进行身份验证的唯一方式。

Rachel Appel是一名顾问、作家、导师和前 Microsoft 员工,在 IT 行业有 20 多年的经验。她常在 Visual Studio Live!、DevConnections、MIX 等顶级行业大会上发言。她的专业是开发侧重于 Microsoft 系列开发技术和开放式 Web 并且符合业务和技术需要的解决方案。有关 Appel 的详细信息,请访问她的网站 rachelappel.com

衷心感谢以下 Microsoft 技术专家对本文的审阅: Frank La Vigne