65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows Mobile 应用开发第六部分:设备安全和应用程序部署

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (7投票s)

2009 年 10 月 30 日

Ms-PL

17分钟阅读

viewsIcon

56388

了解设备安全、测试以及在 Windows Mobile 设备上安装您的应用程序。

引言

为 Windows Mobile 设备开发应用程序与为桌面应用程序开发非常相似,特别是如果您使用了 Visual Basic .NET 或 Visual C#。您可以使用相同的开发工具来开发您的应用程序,尽管为 Windows Mobile 设备开发应用程序与为桌面应用程序开发之间存在一些差异。根据设备制造商或销售设备的移动运营商的不同,Windows Mobile 设备可能具有不同的安全模型。从开发者的角度来看,设备安全决定了一个应用程序是否可以在设备上运行,以及它对系统资源的访问权限。它还会影响您如何分发和安装您的应用程序,特别是当您希望面向来自不同移动运营商的不同制造商的广泛设备时。

本文提供了有关理解设备安全、使用 Visual Studio 2008 的安全管理器测试不同安全配置以及如何在 Windows Mobile 设备上成功安装您的应用程序的信息。

Windows Mobile 设备安全

不同的 Windows Mobile 设备可能安装了不同的安全配置。根据设备制造商或移动运营商的不同,设备可能完全允许安装新应用程序,设备可能在安装或首次运行应用程序之前提示用户,或者设备可能完全被锁定,阻止安装未签名且不包含匹配证书(设备证书存储中可用)的新应用程序。

存在不同安全配置的原因在于,大多数现代 Windows Mobile 设备都具备手机功能,并将用于通过移动运营商拥有的网络进行通信。保护 Windows Mobile 设备的一个重要原因是网络完整性。当然,移动运营商希望保护他们的网络免受最终用户可以轻易安装在设备上的故障软件的侵害。这就是为什么在 Windows Mobile 设备上安装任何应用程序并不总是那么容易的原因,即使该应用程序是专门为在 Windows Mobile 设备上运行而编写的。

为了满足移动运营商要求的安全需求,Windows Mobile 设备可以拥有不同的安全配置。Windows Mobile 设备上安全配置的确切方式不仅取决于移动运营商或企业组织,还取决于所使用的特定 Windows Mobile 设备。Windows Mobile 设备上的安全性至关重要,并且已深度集成到操作系统中。不同安全层级的结合在一起,形成了一个安全配置,该配置精确地决定了应用程序是否可以安装在设备上以及它们如何运行(如果允许运行)。

应用程序执行权限

根据特定 Windows Mobile 设备的安全性配置,应用程序可能允许运行,也可能被阻止执行。Windows Mobile 设备为应用程序执行定义了以下权限:

  • 特权 – 应用程序可以在设备上执行任何操作,对文件系统和系统注册表拥有完全写入访问权限,并且还允许安装可能允许其他应用程序在特定 Windows Mobile 设备上运行的证书。
  • 普通 – 应用程序的执行受到限制;它不能调用受信任的 Win32 API,不能写入注册表的受保护区域,不能写入系统文件,也不能安装证书。
  • 阻止 – 应用程序根本不允许执行。

应用程序证书

为了确定应用程序的执行权限,可以使用证书对您的应用程序进行签名。Windows Mobile 设备为此目的包含两个不同的证书存储:特权证书存储和普通证书存储。如果您使用来自特权存储的证书对您的应用程序进行签名,它将获得特权访问权限。使用来自普通存储的证书签名的应用程序将获得普通访问权限。由于另一个方(OEM 或移动运营商)维护这些证书存储,因此您必须与这些组织合作,以便为特定方签名您的应用程序。但是,作为 ISV,您可能希望您的应用程序在广泛的 Windows Mobile 设备上运行。尤其是考虑到这一点,Mobile2Market 计划应运而生,您可以通过该计划提交您的应用程序进行验证,并使其获得所需的证书签名。通过 Mobile2Market 对应用程序进行签名也意味着您或您的组织将被识别为应用程序的发布者。

应用程序访问级别

不同的访问级别决定了一个未签名应用程序在 Windows Mobile 设备上被允许做什么。这些不同的访问级别称为“层”。Windows Mobile 使用以下含义的两个不同访问级别:

  • 单层安全 – 允许签名应用程序在设备上执行;它将以特权权限运行,从而拥有完全的设备访问权限。未签名应用程序可能允许在设备上执行,但这取决于设备的安全性配置。如果允许未签名应用程序运行,它也将以特权权限运行。
  • 双层安全 – 允许签名应用程序在设备上执行,但它将根据应用程序签名的证书类型,以特权或普通权限运行。未签名应用程序可能允许在设备上执行,但这取决于设备的安全性配置。如果允许未签名应用程序运行,它将始终以普通权限运行。

设备安全配置

现在您已经了解了在 Windows Mobile 设备上运行的不同应用程序权限以及如何使用证书对应用程序进行签名,还有一个重要问题尚未得到解答。您的应用程序(尤其是未签名应用程序)是否可以安装在特定的 Windows Mobile 设备上?Windows Mobile 设备定义了许多标准的设备安全配置,其中一些允许用户安装和运行未签名应用程序。

  • 安全关闭 – 所有应用程序都将在设备上运行,并且都将以特权权限运行。签名应用程序和未签名应用程序之间没有区别。
  • 单层提示 - 所有签名应用程序都将在设备上运行,并且都将以特权权限运行。用户决定是否允许未签名应用程序在他们的设备上运行。如果用户接受未签名应用程序,它将以特权权限运行。
  • 双层提示 - 所有签名应用程序都将在设备上运行,但执行权限由应用程序签名的证书类型决定(特权或普通)。用户决定是否允许未签名应用程序在他们的设备上运行。如果用户接受未签名应用程序,它将以普通权限运行。
  • 第三方签名 – 只允许签名应用程序在设备上运行。执行权限由应用程序签名的证书类型决定(特权或普通)。为了获得您的应用程序签名,您必须注册一个开发者计划,例如 Mobile2Market。通过大多数移动运营商购买的大多数 Windows Mobile 设备都在证书存储中安装了 Mobile2Market 证书。
  • 锁定 - 只允许签名应用程序在设备上运行。执行权限由应用程序签名的证书类型决定(特权或普通)。

执行权限与 DLL

还有一件事您需要考虑。与应用程序一样,动态链接库(DLL)可以是未签名的,也可以使用特权或普通证书进行签名。由于 DLL 在应用程序中使用,这会引发一个有趣的问题。例如,如果一个特权应用程序调用一个未签名的 DLL,而该 DLL 本身调用了一个受信任的 Win32 API,会发生什么?如果 DLL 被提升到与调用应用程序相同的访问权限,这将引入安全漏洞。因此,以下规则适用于调用 DLL 的应用程序,列出了授予 DLL 的访问级别:

应用程序/DLL 组合 无安全 单层提示 双层提示
未签名应用程序
未签名 DLL 特权 如果允许,则为特权 如果允许,则为非特权
已签名的普通 DLL 特权 如果允许,则为特权 如果允许,则为非特权
已签名的特权 DLL 特权 如果允许,则为特权 如果允许,则为非特权
已签名的普通应用程序
未签名 DLL 特权 特权 如果允许,则为非特权
已签名的普通 DLL 特权 特权 非特权
已签名的特权 DLL 特权 特权 非特权
已签名的特权应用程序
未签名 DLL 特权 特权 不允许!
已签名的普通 DLL 特权 特权 不允许!
已签名的特权 DLL 特权 特权 特权

在不同设备安全配置下测试您的应用程序

Visual Studio 2008 工具集中的一个工具是设备安全管理器。它允许您检索 Windows Mobile 设备和设备模拟器上的当前安全设置。

注意:只有当设备当前的安全配置允许您这样做时,才能更改物理设备上的安全设置。此外,您必须小心将物理设备设置为“锁定”安全配置,因为这是一个不可逆的操作。设备安全管理器会对此发出警告。使用设备模拟器,您可以安全地尝试所有不同的安全配置。

使用设备安全管理器,您可以部署当前定义的任何安全配置,也可以导入新的安全配置。您还可以获取已安装在连接的 Windows Mobile 设备或设备模拟器的证书存储中的所有证书列表。

MOB4DEVS06/mob06fig1.jpg

图 1 - 设备安全管理器

设备安全配置可以通过 XML 文件定义,就像 Visual Studio 2008 提供的以下示例一样。

<wap-provisioningdoc />
  <characteristic type="SecurityPolicy" />
    <parm name="4102" value="1" /> 
    <parm name="4122" value="0" /> 
    <parm name="4123" value="0" /> 
  </characteristic />
</wap-provisioningdoc />

在不同安全配置下测试不同的访问级别

现在您已经了解了如何设置不同的安全配置,您可能想要尝试不同的安全设置。以下代码片段可以帮助您开始编写一个非常简单的应用程序,该应用程序调用一个受信任的 Win32 API。如果您将此代码片段同时添加到应用程序和 DLL 中,并使用不同的证书对应用程序和 DLL 进行代码签名,当然,也可以完全不签名,您就可以在不同的安全配置下测试应用程序的行为。

[DllImport("coredll.dll")]
public extern static void PowerOffSystem();
private void btnInstructions_Click(object sender, EventArgs e)
{
    PowerOffSystem();
}

如果允许调用此 API 的应用程序调用受信任的 API,您将看到设备模拟器会立即消失,因为它被关闭了。如果应用程序不允许调用受信任的 API,则什么也不会发生。API 仅被忽略。

另一方面,如果您尝试写入设备文件系统或注册表的受保护区域,此类调用将导致 `UnauthorizedAccessException`。

应用程序安装

设备安全也会影响应用程序安装。到目前为止,本文一直假设通过 Visual Studio 2008 部署应用程序,并通过设备安全管理器设置安全配置。这些是在应用程序开发过程中很好的选择,但总有一天,您将准备好发布您的应用程序。当然,您希望为最终用户提供出色的安装体验,这意味着您必须以 CAB 文件或甚至 Microsoft Installer (MSI) 文件的形式发布您的应用程序。如果您决定将应用程序打包成 CAB 文件,最终用户必须将 CAB 文件复制到他们的 Windows Mobile 设备上,然后他们可以使用 Explorer 来解压和安装应用程序。如果您决定将 CAB 文件包装到 Microsoft Installer 文件中,用户就可以从桌面安装您的应用程序,只要他们的 Windows Mobile 设备通过 ActiveSync(Windows XP)或 Windows Mobile 设备中心(Windows Vista)连接。

如果设备具有严格的安全配置,它可能不允许在设备上安装未签名的 CAB 文件。这意味着您不仅要考虑签名您的应用程序,还要考虑签名您的 CAB 文件。为了自动化此过程,Windows Mobile 6 SDK 包含 `cabsigntool.exe`。此实用程序在命令提示符下运行,并利用一个底层工具:`signtool.exe`。由于 `signtool.exe` 是 Visual Studio 2008 的一部分,因此建议启动 Visual Studio 2008 命令提示符,以便使用 `signtool.exe`,而无需自己设置环境变量来查找此工具。

以下是如何从命令提示符使用 `cabsigntool.exe` 的示例:

cabsigntool "C:\Users\UserVS2008\Documents\Visual Studio 
2008\Projects\HOL6SampleApp\DVDsMobileCAB\Debug\DVDsMobileCAB.cab" 
"C:\Users\UserVS2008\Documents\Visual Studio 
2008\Projects\HOL6SampleApp\DVDsMobileCAB\Debug\DVDsMobileCAB.cab" 
-f "C:\Program Files\Windows Mobile 6 SDK\Tools\Security\SDK Development 
Certificates\SampleUnPrivDeveloper.pfx"

在此示例中,CAB 文件 `DVDsMobileCab.cab` 及其包含的所有可执行文件和程序集都使用 Windows Mobile 6 SDK 中找到的一个非特权测试证书进行了签名。`cabsigntool.exe` 本身也可以在 Windows Mobile 6 SDK 中找到,路径为:`c:\program files\Windows Mobile 6 SDK\Tools\Security`。正如您所见,手动输入 `cabsigntool.exe` 的命令行参数容易出错。因此,创建包含整个命令的批处理文件可能更好,特别是如果您想更频繁地运行 `cabsigntool.exe`。

更新应用程序

与使用 Visual Studio 2008 开发的桌面应用程序不同,智能设备应用程序无法使用 ClickOnce 技术进行部署,ClickOnce 技术允许在应用程序的新版本可用时实现自更新功能。您可以自己创建类似的功能,例如通过 Web 服务。在本白皮书中,您将获得关于如何创建类似于 ClickOnce 的更新机制的高层概述。示例只是一个起点,但应该为您提供足够的信息和想法来创建自己的应用程序更新机制。

为了能够自动更新应用程序,您可以例如使用 Web 服务,该服务包含用于返回应用程序最新发布版本的版本号的方法,并将其与安装在 Windows Mobile 设备上的当前版本号进行比较。由于您需要更新正在运行的应用程序,因此需要一个单独的安装程序来进行此操作。您甚至可以使用相同的安装程序从头开始初始安装应用程序。

安装新应用程序

要安装全新的自动更新应用程序,您可以通过 ASP.NET 网站进行部署。为了下载应用程序,用户应浏览到应用程序可供下载的网站。

MOB4DEVS06/mob06fig2.jpg

图 2 - 包含应用程序和下载应用程序更新程序的网站

在图 2 中,您可以看到一个提供新应用程序下载的网站。通过单击链接,用户不会安装应用程序本身,而是会在设备上安装一个应用程序安装程序。应用程序安装程序将存储在应用程序将要安装的相同文件夹中。安装程序还在设备上的“程序文件”文件夹中创建一个快捷方式,名称为实际应用程序的名称。

一旦应用程序更新程序下载完成,用户只需导航到“程序”,然后单击应用程序的快捷方式即可启动应用程序更新程序。由于应用程序本身尚未提供,应用程序更新程序将启动而不是实际的应用程序,如图 3 所示。

MOB4DEVS06/mob06fig3.jpg

图 3 - 首次启动应用程序

应用程序更新程序使用命令行参数来确定它是被用户启动还是从实际应用程序内部启动。后者用于应用程序有更新可在网站上使用时。以下代码是应用程序更新程序的一部分,在 `Form_Load` 事件中运行,展示了如何区分初始安装和更新安装。

private void MainForm_Load(object sender, EventArgs e)
{
    if (_args == null || _args.Length == 0 || _args[0].Length == 0)
    {
        _args = new string[1];
        _args[0] = initialURL;
        label1.Text = Properties.Resources.InstallString;
    }
    else
    {
        label1.Text = Properties.Resources.UpgradeString;
    }
}

当应用程序首次安装时,它将更新存储在“程序文件”文件夹中的快捷方式,因此下次用户从“程序文件”文件夹内部启动应用程序时,实际应用程序将启动,而不是应用程序更新程序。

MOB4DEVS06/mob06fig4.jpg

图 4 - 通过应用程序更新程序安装和启动应用程序

一旦应用程序通过应用程序安装程序安装完成,只要用户通过“菜单 | 退出”终止安装程序,应用程序就会自动启动。以下代码展示了如何从应用程序安装程序内部启动主应用程序。请注意,此代码片段包含硬编码的路径,这并非最佳实践,但可以根据您自己的需求轻松改进。

private void menuExit_Click(object sender, EventArgs e)
{
   if (label1.Text.Equals(Properties.Resources.InstallString) && ! appInstalled)
   {
      Close();
   }
   else
   {
      StartDVDsMobile();
   }
}

private void StartDVDsMobile()
{
   Process theApp = null;
   try
   {
      theApp = Process.Start(@"\Program Files\DVDsMobile\DVDsMobile.exe",
      Process.GetCurrentProcess().Id.ToString());
   }
   catch (Win32Exception exc)
   {
      if (exc.NativeErrorCode == ERROR_FILE_NOT_FOUND)
      {
          MessageBox.Show("DVDsMobile.exe not found.");
      }
      else if (exc.NativeErrorCode == ERROR_ACCESS_DENIED)
      {
          MessageBox.Show("No permissions to start DVDsMobile.exe.");
      }
   }
}

在上面的代码片段中,您可以看到 `menuExit_Click` 事件处理程序用于确定是自动启动应用程序还是简单地终止它。如果安装了新版本的应用程序,应用程序更新程序将启动新版本的应用程序,并将其自身的进程标识传递给它,以便应用程序可以终止应用程序更新程序。虽然这并非必需,但它将为最终用户提供更好的体验,因为最终用户几乎不会注意到在当前进程终止之前启动了一个新进程。

更新应用程序

每次用户启动应用程序时,它都会调用托管在安装应用程序更新程序的同一网站上的 Web 服务。该 Web 服务具有返回应用程序所有程序集的最新版本的方法。应用程序将其自身的版本号与从 Web 服务调用返回的版本号进行比较。如果托管网站上有更新的版本可用,将提示用户安装最新版本或运行当前版本。这种方法的缺点是启动应用程序需要更长的时间。优点是用户始终可以使用最新版本。为了保持示例代码简单,应用程序不检查网络连接是否可用,这在实际应用程序中当然应该添加。这可以通过利用状态和通知代理功能轻松完成。

MOB4DEVS06/mob06fig5.jpg

图 5 - 自动升级进行中

要下载新版本的应用程序,应用程序更新程序会访问网站并通过隐藏的 Web 浏览器控件下载最新版本。使用 Web 浏览器控件可以简化将文件下载到设备的过程,而无需额外的 Web 服务方法。网站的代码未在此白皮书中显示,但您可以在 Windows Mobile RampUp 第 7 部分中创建完全相同的安装体验,其中实践操作实验室将引导您一步步完成整个示例。以下代码展示了应用程序如何发现新版本自身可用。

private void MainFormNoTouch_Load(object sender, EventArgs e)
{
   this.Text = Properties.ResourcesNoTouch.MainFormNoTouchTitle;
   this.menuItemExit.Text = Properties.ResourcesNoTouch.MenuItemExitText;
   if (_processID != -1)
   {
      // We have just been updated, so kill our update process.
      Process.GetProcessById(_processID).CloseMainWindow();
   }
   else
   {
      DVDsMobileUpdateService.DVDsMobileUpdateService updateService = 
        new DVDsMobileNoTouch.DVDsMobileUpdateService.DVDsMobileUpdateService();
      string[] latestDVDsMobileVersion = updateService.DVDsMobileVersion().Split(
        new char[] { '.' });
      string[] latestDVDsMobileVersionNoTouch =
        updateService.DVDsMobileVersionNoTouch().Split(
        new char[] {'.'});
      string[] currentDVDsMobileVersion = _callingAssembly.Split(
        new char[] { '.' });
      Version currentDVDsMobileVersionNoTouch =
        Assembly.GetExecutingAssembly().GetName().Version;
      bool update = false;
      update = (Convert.ToInt32(latestDVDsMobileVersion[0]) >
                   Convert.ToInt32(currentDVDsMobileVersion[0])) ||
               (Convert.ToInt32(latestDVDsMobileVersion[1]) >
                   Convert.ToInt32(currentDVDsMobileVersion[1])) ||
               (Convert.ToInt32(latestDVDsMobileVersionNoTouch[0]) >
                   currentDVDsMobileVersionNoTouch.Major) ||
               (Convert.ToInt32(latestDVDsMobileVersionNoTouch[1]) >
                   currentDVDsMobileVersionNoTouch.Minor);
      if (update)
      {
         if (MessageBox.Show(
             "A new version of DVDsUpdate is found! " +
             "Do you want to install the new version?",
             "New version available",
             MessageBoxButtons.YesNo, 
             MessageBoxIcon.Question,
             MessageBoxDefaultButton.Button2) == DialogResult.Yes)
         {
             Process.Start(@"\Program Files\DVDsMobile\DVDsMobileAutoUpdater.exe",
               @"http://192.168.2.102:5746/DownloadForm.aspx");
             Application.Exit();
         }
      }
   }
}

在上面的代码片段中,您可以看到 `Form Load` 事件处理程序用于确定新版本的应用程序是否可用。为了找出这一点,应用程序调用 `DVDsMobileUpdateService` Web 服务上的两个方法。应用程序还读取其自身的版本号;如果存在更新的版本,用户将看到一个消息框,通过该消息框,他们可以决定是安装最新版本还是继续运行当前版本。如果用户决定运行最新版本,应用程序更新程序将立即启动,应用程序将自行终止。一旦设备上安装了新版本的应用程序,应用程序更新程序将启动该新版本的应用程序,允许用户开始使用该应用程序。

本系列相关文章

其他资源和参考

请访问 www.myrampup.com 以获取更多信息。

© . All rights reserved.