LightSwitch 安全性

确保访问 LightSwitch 应用程序安全

Valerie Andersen, Matt Evans, Sheel Shah, Michael Simons

让我们面对现实:确保应用程序的安全绝非易事。幸运的是,有了 Visual Studio LightSwitch,在业务线 (LOB) 应用程序中管理基于权限的访问控制就变得很轻松,您可以构建具备访问控制逻辑的应用程序,来满足业务的具体需求。

LightSwitch 应用程序在逻辑上包含三层:表示层、逻辑层和数据存储层。在每一层上,您都需要考虑对资产的访问,以便确保实现正确的访问权限级别。使用 LightSwitch,您可以在正确的级别构建应用程序的访问控制逻辑。而且,您会发现 LightSwitch 在底层技术中利用了访问控制的基本功能,并允许通过 IIS 和 ASP.NET 实现通用的访问控制配置。

本文介绍 LightSwitch 应用程序中访问控制的工作原理。首先,我们介绍 LightSwitch 在三层结构中为实现访问控制提供的功能。接下来,简要回顾与访问控制相关的部署任务,展示一些使用支持 LightSwitch 的技术进一步控制访问的方法。最后,我们讨论部署到 Windows Azure 环境时的访问控制。

访问控制基础知识

LightSwitch 应用程序中的访问控制包含两个方面。第一个方面是身份验证,也就是应用程序验证用户是否是其宣称的身份。第二个方面是授权,即定义用户可以做什么或可以看到应用程序中的什么内容。

身份验证

身份验证过程将确定用户是否是其宣称的身份。LightSwitch 中的第一层访问控制要求用户向应用程序说明自己的身份。支持的身份验证模式是 Windows 身份验证窗体身份验证。这些选项可在应用程序的应用程序属性“访问控制”选项卡中进行配置,如图 1 所示。

Defining Permissions in the Application Designer
图 1 在应用程序设计器中定义权限

如果所有用户都在 Windows 域中,并且您确信登录计算机的用户就是使用应用程序的用户,则推荐使用 Windows 身份验证。Windows 身份验证不需要额外的登录提示,应用程序不必在 Windows 之外存储或管理密码。Windows 身份验证是更安全的选项,但一般来说,只有应用程序在公司内联网环境中使用域运行时这种方法才比较实用。

如果使用第二个选项“窗体身份验证”,应用程序打开时会提示用户提供用户名和密码。在 LightSwitch 中,默认会对照数据库检查这些值。对于在 Internet 上运行的客户端以及不在 Windows 域上运行的客户端来说,窗体身份验证是不错的选择。

窗体身份验证要求,需要访问应用程序的用户必须先添加到系统中。Windows 身份验证也可以采用这种方式,但有一个选项可以在设计阶段进行设置,允许所有可以登录到域中的 Windows 用户默认即拥有访问应用程序的权限。如果应用程序中的某些部分需要具体权限,则对于未被明确添加的 Windows 用户来说,这些部分都是不可访问的。

身份验证可让您识别谁可以使用或不可以使用应用程序,对某些类型的应用程序来说,身份验证即可满足所有的访问控制需求。用户验证身份之后,您可以选择完全信任他们,允许其访问数据。如果是这样,您就实施了完整的访问控制,不再需要额外的权限或代码。您只需再考虑“访问控制的部署注意事项”一节中讨论的 IIS 选项,以便在托管服务器上确保应用程序的安全。

但是,很多应用程序还需要在用户进行身份验证之后更细致地控制用户的行为。对于这种情况,您需要进行授权。

授权

LightSwitch 针对开发业务规则提供了基于权限的授权体系,如图 2 所示。  

Implementing Authorization in LightSwitch
图 2 在 LightSwitch 中实施授权

您在应用程序设计器中定义权限(请参见图 1)。然后就可以编写代码来检查当前用户是否具有所需的权限。访问控制方法可在实体、查询和屏幕上实施,这样您就可以轻松编写逻辑来确定当前用户是否可以查看或操作具体的数据或者打开特定的屏幕。

LightSwitch 具有名为“安全管理”的内置权限,获得此权限的用户将成为安全管理员。“安全管理”权限允许登录的用户访问正在运行的 LightSwitch 客户端应用程序中的“Security Administration”(安全管理)屏幕。该屏幕会自动向被授予了此权限的用户显示。安全管理员负责创建应用程序所需的角色,为每个角色分配所需的权限,如图 3 所示。然后,就会创建用户并分配适当的角色,如图 4 所示。

Creating Roles at Run Time
图 3 在运行时创建角色

Assigning Users to Roles at Run Time
图 4 在运行时为用户分配角色

第一次部署应用程序时,必须向“安全管理”角色中添加一个安全管理员,以便实现对应用程序的初始访问。部署过程可帮助正确配置这一默认的用户。部署后的应用程序运行时,如果只剩一位具备安全管理员权限的用户,系统将不允许删除该用户,这是为了确保任意时刻都存在安全管理员。

但是,您不必通过部署应用程序来验证适当的权限行为。当您在调试模式下运行 LightSwitch 应用程序时,身份验证和角色系统会在特殊模式下运行。在此模式中,开发环境会自动尝试对特殊的测试用户进行身份验证。您可以在 LightSwitch 设计器中使用“Granted for debug”(授予调试权限)列来为测试用户授予或取消权限。然后应用程序将使用所选的权限在调试模式下运行,您就可以测试所编写的权限逻辑。这意味着,您不必配置多个测试用户和角色即可快速验证权限检查是否准确。

在哪里控制对应用程序资产的访问至关重要

现在我们来思考要保护哪些内容的安全,在哪里保护。对很多应用程序来说,有些敏感数据需要受到保护不被查看,另一些数据需要不被操作,可能还有一些数据根本无需访问保护。首先要考虑保护数据的位置应该是逻辑层。如果开发人员在逻辑层正确地控制数据,表示层通常也会自动做出正确响应。例如,如果用户未被授予对员工数据的删除权限,则显示员工数据的表格会将“删除”按钮禁用。这就是使用 LightSwitch 构建应用程序的强大以及轻松之处。

在数据层实施访问控制可以增强应用程序的安全性,让开发人员充分利用内置的智能。只在表示层保护数据安全会让数据在逻辑层面临风险。通过身份验证的恶意用户可以绕过表示层,直接访问服务以读取或操作数据。这个问题与 LightSwitch 应用程序的三层结构有关,事实上也是三层结构应用程序面临的常见问题。表示层负责正确显示数据,但是如果不在逻辑层正确实施访问控制,表示层就不是通过身份验证的用户访问数据的唯一途径。

在逻辑层保护数据安全

逻辑层包括两大组组件,可在其中实施权限检查:实体和查询。

实体 实体是访问和处理应用程序数据的一般机制。您可以对实体执行四种主要操作:读取、插入、更新和删除。LightSwitch 为开发人员提供一个挂钩点,可在执行每个操作时确认用户的权限,还提供了一个简单的 API,用来检查当前用户是否具有应用程序中定义的特定权限。以下代码显示了权限检查的示例,以及 API 提供的让开发人员检查权限的各种门方法:

partial void Employee_CanUpdate(ref bool result)
{
  result = Application.Current.User.HasPermission(Permissions.EmployeeUpdate);
}
 
partial void Employee_CanInsert...
partial void Employee_CanRead...
partial void Employee_CanDelete...
partial void SaveChanges_CanExecute...

有几个地方值得注意。 首先,这些方法(SaveChanges_CanExecute 除外)都是在整个实体集上而不是在具体的实体实例上实施的。 因此,执行的任何检查都无法与具体实体实例的数据值相关。 SaveChanges_CanExecute 方法控制对整个数据源的更改的访问,因此无法包含针对特定实体或实体集的逻辑。 其次,如果 Employee_CanRead 方法返回 false,将不会调用 Employee_CanUpdate 和 Employee_CanDelete 方法,因为它们也将返回 false。 如果用户不允许读取实体,也就不允许更新或删除实体。

“Can”方法是进行粗略安全控制的基本方法。 它们支持基本的数据访问控制策略。 但这些方法有一些限制。 如果需要更精细地控制对数据的读取,您可以在查询上实施访问控制逻辑。 要更为细致地控制数据的写入,您必须在“保存管道”中进行此操作。

查询 查询也是在逻辑层上进行安全保护。 每个查询都提供一个方法,让您控制访问。 LightSwitch 为已存在的每个实体自动生成三个查询:All 查询返回所有的实体实例,Single 和 SingleOrDefault 查询按主键返回一个实体实例。 这些内置的查询都具备 CanExecute 方法,可用来实施访问控制:

partial void Employees_All_CanExecute(ref bool result)
{
  result = Application.Current.User.HasPermission(Permissions.QueryEmployees);
}
 
partial void Employees_Single_CanExecute...
partial void Employees_SingleOrDefault_CanExecute...

务必要注意 LightSwitch 查询是可改写的,也就是说可以根据现有的查询创建新查询。 对查询应用访问控制逻辑时,原始查询的权限要求将作为改写后的查询的输入。 Single 和 SingleOrDefault 查询改写自 All 查询,如果派生的查询没有指定具体的权限,保护 All 查询的安全也就能保护这些查询的安全。 但如果需要,您可以在派生的查询上指定权限,使其比原始查询的权限少一些限制。 另外,实体集上的 CanRead 方法的应用优先于该类型实体的 CanExecute。

图 5 显示的是查询改写的示例:如果 NorthAmericaEmployees 查询在 Employee 实体上创建,此查询就是基于内置的 Employee_All 查询改写的。 因此,通过 Employee_All_CanExecute 应用的所有访问控制逻辑将也应用到 NorthAmericaEmployees 查询,因为 NorthAmericaEmployees 查询基于 Employee_All 查询(假设没有为派生的查询编写任何具体的代码)。 如果您希望只允许部分用户访问 NorthAmericanEmployees 实体中的数据,可以通过 NorthAmericaEmployees_CanExecute 方法具体限制或开放该查询的权限。

Query Composition on the Employee Entity
图 5 Employee 实体上的查询组成

控制跨关系的访问

处理跨关系的查询时,务必要了解权限会作为关系在实体上检查,从而遍历相关的实体。 这是为什么在实体上正确定义权限很重要的另一个原因。 如果您需要通过关系保护数据不被读取访问,实体上的 CanRead 方法需要正确的权限级别。 例如,让我们再次考虑 Employee 表以及相关的薪酬数据,如图 6 中的模型所示。

HR Application Model
图 6 人力资源应用程序模型

当通过查询遍历 Employee 和 Compensation 之间的关系时,将计算实体读取操作上的权限,因为遍历的是关系而不是 Compensation_All_CanExecute 上的权限。 必须正确设置 Compensation 实体的 CanRead 方法上的权限,这样在遍历实体时才能达到正确的权限级别。 您需要认识到,如果实体不加保护,就能使用查询来推论数据。 例如,如果您的查询返回薪酬最高的员工,如图 7 所示,则为了返回 Employee 数据而被访问的 Compensation 实体需要得到正确保护,以便只有拥有权限的用户可以通过查询获得此数据。

Defining a Query to Return the Top-Paid Employees
图 7 定义查询以返回薪酬最高的员工

提供自定义的表示体验

数据在逻辑层得到保护后,就需要开始设计表示层的用户体验。 如果您希望某个用户根本无法访问特定屏幕,可以通过应用程序的 <ScreenName>_CanRun 方法关闭该屏幕。 如果用户无权访问某个屏幕,该屏幕就不会显示在其导航菜单中。 您还可以使用 <CommandName>_CanExecute 方法限制屏幕上的命令。

还有几种其他方法可用在屏幕和实体上,用来隐藏、显示和控制屏幕上具体控件的可编辑状态,例如 <EntityProperty>_IsReadOnly、<ScreenControl>.IsEnabled、<ScreenControl>.IsReadOnly 和 <ScreenControl>.IsVisible。 尽管这些方法的主要目的不是访问控制,但它们在提供所需的用户体验方面很有用。 在某些情况下,最好将用户无法操作的数据隐藏起来;在另一些情况下,您可能需要显示只读的控件;还有些时候,您需要指导用户正确输入数据,并在用户出错时给出有意义的错误信息。 LightSwitch 表示层可以灵活适应这些情况。

另外您应该明确,在屏幕上提供逻辑以便隐藏、显示或控制数据的可编辑状态并不是保护数据不被用户访问,而只是控制数据如何显示。 如果不加正确保护,通过身份验证的恶意用户有可能直接访问逻辑层服务以查看或操作数据。 因此,在每个应用程序层上正确实施访问控制至关重要。

在存储层保护数据安全

您的数据就是在存储层存储到数据库中。 您可以提供对数据库只有最少必要权限的数据库登录来控制对存储层中数据的访问。 应用程序使用此登录来连接数据库,执行必要的操作。 在三层部署中,所有数据连接都通过中间层完成,最终用户从不直接访问数据或连接字符串。 在部署 LightSwitch 应用程序时,您必须指定应用程序访问数据时所用的连接字符串,如图 8 所示。 如果应用程序没有独占的数据库登录,LightSwitch 将引导应用程序管理员创建一个。 强烈建议所识别出的数据库用户仅针对该应用程序,并且只能访问该应用程序使用的相关数据。

Specifying the Database Connection Credentials for the Running Application During Deployment
图 8 在部署期间为运行的应用程序指定数据库连接凭据

需要注意的是,可以使用两层部署方案来部署安全的 LightSwitch 应用程序。 在两层部署中,表示层和逻辑层运行在用户桌面上。 这种配置可让客户端的用户访问存储了数据库连接字符串的 web.config 文件,因此并未提供表示层和逻辑层之间的隔离,而这种隔离是安全的应用程序配置所必需的。 使用连接字符串,用户可以直接访问数据库,绕过中间层上的所有访问控制逻辑。 在这种情况下,最好在中间层和数据库之间使用 Windows 身份验证。 否则,就应该使用三层部署方案来确保应用程序的安全。

访问控制的部署注意事项

第一次部署 LightSwitch 应用程序时,您需要创建一个 LightSwitch 管理员用户。 最初,这是具备管理员权限的唯一用户。 然后使用该用户来配置客户端应用程序中的角色和用户,如前文所述。 请注意,此用户是 LightSwitch 应用程序的管理员,但不一定是 Windows 管理员。 部署过程结束之后,也可以使用一款命令行工具来创建新的管理员用户。 您可以在 LightSwitch 安装目录中找到这款工具 Microsoft.LightSwitch.SecurityAdmin.exe。

利用 IIS 中的访问控制功能

现在,我们已经讨论了 LightSwitch 相关的访问控制功能,接下来我们简短了解一下应用程序管理员使用支持技术手动保护 LightSwitch 应用程序安全的其他方法。

LightSwitch 和 SSL 就像 Web 浏览器和 Web 服务器一样,LightSwitch 客户端和服务器也是通过 HTTP 协议进行通讯。 HTTP 指定数据以明文发送,也就是说网络窃听程序可以监控客户端和服务器之间交换的数据。 要保护通讯不被网络窃听程序窃听,您应该改用 HTTPS 协议。该协议将普通的 HTTP 数据隐藏在加密隧道内。

LightSwitch 应用程序可以部署为通过 HTTPS 实现客户端与服务器之间的通讯。 这不但可以保护在客户端和服务器之间交换的敏感业务数据,还可以在使用窗体身份验证时保护用户名和密码。 在将窗体身份验证与 IIS 或 Windows Azure 结合使用时,最好部署到 HTTPS 站点。 否则,攻击者可能会盗取身份验证令牌,假冒登录的用户。 使用 Windows 身份验证时,即使是使用 HTTP 而不是 HTTPS,攻击者也无法恢复用户密码或假冒用户。 但是,无论使用哪种身份验证,如果不采用 HTTPS,在客户端和服务器之间传输的业务数据始终面临被窃听的威胁。

SSL 和证书 通过 HTTPS 进行通讯的 Web 服务器依赖于服务器上安装的证书。 此证书有两个作用。 首先,证书可验证客户端连接的服务器是正确的服务器,没有被替换或篡改。 其次,服务器证书包含密钥信息,用来加密发送到客户端的数据。

要使 Web 浏览器能够信任以前从未联系过的服务器的身份,服务器证书必须由受信任的证书颁发机构 (CA) 进行签名加密。 您可以从许多提供商处(例如 verisign.com, entrust.netinstantssl.comgeocerts.com)购买证书。 由于大多数提供商会就生成或签署服务器证书收取费用,因此开发环境中常见的做法是使用自行生成的未签名(也就不受信任)的证书。

如果您通过 HTTPS 连接到 LightSwitch Web 应用程序,而服务器运行不受信任的证书,则具体行为取决于您的 Web 浏览器。 浏览器至少会通知您出现证书问题,询问您是否要继续操作。 对于 LightSwitch Web 应用程序来说,这应该是可行的。

但是,如果您使用由 IIS 托管的 LightSwitch 桌面应用程序,并通过 HTTPS 访问它,则 IIS 服务器必须使用受信任的证书。 Silverlight 不允许桌面应用程序来自不受信任的服务器证书。 如果使用不受信任的证书,应用程序看似安装成功,但一启动就会失败。 要解决此问题,可以通过在客户端的证书存储区中预先安装证书,强制您的 Web 浏览器信任服务器的证书;也可以使用由受信任的 CA 签名的证书来替换服务器的证书。 请注意,您必须在第一次从指定客户端访问应用程序之前即执行上述某种解决方法,否则该客户端就会认为证书已更改或被篡改。

IIS 要托管具有 SSL 的 LightSwitch 应用程序,无需在 IIS 服务器上对 LightSwitch 进行具体的配置。 服务器管理员应该配置 Web 服务器以启用 HTTPS 并按常规选择证书。

实际上,可以同时使用 HTTP 和 HTTPS 来托管同一个 LightSwitch 应用程序,有些情况下您可能真的需要这么做。 但需要注意到是,正如前文所述,通过 HTTP 连接的客户端不会保护用户密码信息或敏感的业务数据。

默认情况下,在最新版本的 IIS 中,“默认网站”会监听 HTTP 和 HTTPS 两种连接。 服务器管理员可以强制 LightSwitch 应用程序部署到这样的服务器上,以便要求使用 HTTPS 并将传入的 HTTP 连接重定向到 HTTPS 端点。 此设置位于 LightSwitch 应用程序的 web.config 文件中。

应用程序池配置 发布到 IIS 时,请考虑在单独的应用程序池中运行该应用程序。 应用程序池不仅能够隔离各个工作进程(因此如果一个 Web 应用程序崩溃,不会影响服务器上的其他应用程序),而且还允许应用程序以不同的身份运行。 因此您可以创建一个应用程序池,托管以特定 Windows 身份运行的 Web 应用程序或一组服务,并且只允许访问该身份运行应用程序所需的资源。 就 LightSwitch 应用程序而言,该额外的资源将是数据库。 默认情况下,部署向导将应用程序部署在以计算机帐户身份运行的 ASP.NET 4 应用程序池下。 但是,该身份不能访问应用程序数据库,因此一旦运行应用程序,将导致出现错误信息,例如“用户 'IIS APPPOOL\ASP.NET v4.0' 登录失败”。

解决方法有几种。 如果您在连接字符串中使用 SQL Server 用户名/密码,应用程序很可能就已经可以使用了(只要该用户有权访问数据库即可)。 但是,如果使用 Windows 身份验证来连接数据库,就需要独立的应用程序池,以便将其配置为以权限最少的 Windows 用户帐户运行。 该帐户必须还被授予访问应用程序数据库的相应权限。

如果您在 IIS 7 中使用 Windows 身份验证,还应该注意另一项配置设置。 当您使用自定义用户身份作为应用程序池身份时,您需要使用 Windows NT LAN Manager (NTLM) 提供程序(不是 Kerberos)或启用针对 Kerberos 身份验证的支持。 另一个选项是使用“网络服务”身份作为应用程序池的身份,并向该帐户添加对数据库的访问权限。

确保 LightSwitch Azure 应用程序安全

所有托管到 Windows Azure 中的 LightSwitch 应用程序都是可以公开访问的。 因此,这些应用程序有一组独特的访问控制要求。

SSL 加密 向 Windows Azure 发布应用程序时,LightSwitch 默认将使用 HTTPS 端点。 这是为了确保敏感业务信息得到加密,因为这些信息会通过 Internet 传递。 LightSwitch 提供了相应的选项,可以在发布期间为应用程序创建自签名的 SSL 证书。 尽管这是在 Windows Azure 中测试应用程序的好方法,但强烈建议您使用来自外部提供商的许可证书,正如前文所述。 因为桌面应用程序不会使用不受信任的证书通过 SSL 工作,您可以在应用程序成功部署后使用 Windows Azure 门户网站,将 Microsoft.LightSwitch.RequireEncryption 的部署配置值更新为 false,从而关闭 SSL 加密以进行调试。

使用自签名的 SSL 证书测试应用程序之后,您可以更新 SSL 证书,而无需通过 Windows Azure 门户网站再次发布应用程序。 要为托管的应用程序上传新的 SSL 证书,可以将 SSLCertificate 值更改为新证书的指纹并开启加密。

应用程序身份验证 建议使用窗体身份验证来阻止对 Windows Azure 托管的 LightSwitch 应用程序的未授权访问。 这样做不需要在应用程序发布之后再配置服务器。 如果应用程序需要使用 Windows 身份验证,则发布的 LightSwitch 应用程序需要加入域。 这就要求使用 Windows Azure Connect。您可以在 bit.ly/qx0Z6n 找到有关启用 Windows Azure Connect 的指导信息。

SQL Azure 数据库安全 LightSwitch 应用程序通常将 SQL Azure 数据库作为其内置数据库。 如果您在 LightSwitch 中创建了表或者使用身份验证,就需要此数据库。 SQL Azure 组合使用防火墙和用户凭据来阻止未经授权的访问。

要允许 Windows Azure 托管的 LightSwitch 应用程序连接到数据库,“Allow other Windows Azure services to access this server”(允许其他 Windows Azure 服务访问此服务器)防火墙规则必须设置为 true。 LightSwitch 还要求针对发布应用程序的计算机的 IP 地址添加一条防火墙规则。 建议在应用程序发布之后删除此防火墙规则。 这可以阻止外部计算机访问数据库。

总结

LightSwitch 帮助开发人员以简单、高效的方式构建业务应用程序,实施访问控制功能时也是如此。 通过使用身份验证,开发人员可以快速、轻松地限制对其应用程序的访问。 如果需要更细致的控制,身份验证功能也提供了强大的方法来定义权限、在应用程序的逻辑层和数据层保护资源的安全,从而有效控制用户访问。 可以利用 IIS 和 Windows Azure 中的常用功能来构建完整的访问控制解决方案。 但是任何创新都取决于您自己! 请访问 blogs.msdn.com/b/lightswitch 了解来自 LightSwitch 团队的更多信息。

 

Valerie Andersen 是 Microsoft 的 Visual Studio LightSwitch 项目经理。她的目标是推进 LightSwitch 的功能,让普通开发人员迅速构建安全、优质的应用程序,满足世界各地客户的需求。

Matt Evans 是面向 LightSwitch 的软件测试人员。他致力于确保您的 LightSwitch 应用程序的安全性达到您的预期。

Sheel Shah 是 Microsoft 的 LightSwitch 项目经理。他的团队工作重点包括设计 Windows Azure 支持、部署和 LightSwitch 客户端功能。

Michael Simons 是 Microsoft 的资深 LightSwitch 开发人员。他的团队工作重点是开发数据和安全功能。

衷心感谢以下技术专家,感谢他们审阅了本文:Dan LeeaphonJohn RivardDan SeefeldtMatt Thalman