构建安全的数据访问-授权(五)
如果用户能够检索和操纵特定的数据,就会建立授权过程。有两种方法:数据访问代码可以使用授权来确定是否执行请求的操作,数据库可以通过执行授权来限制应用程序所使用的 SQL 登录的功能。
在授权不足的情况下,用户也许能够看到另一个用户的数据,未授权的用户也许能够访问受限制的数据。要去除这些威胁:
•限制未授权的调用方。
•限制未授权的代码。
•
限制数据库中的应用程序。
图 14.3 概述了应该使用的授权点和技术。
图 14.3
数据访问授权、程序集和数据库
注意数据访问代码如何按照权限需求为调用用户或调用代码授权。代码标识需求是 .NET 代码访问安全性的一个特性。
要为数据库中的应用程序授权,请使用只具有执行选定存储过程权限的最小特权 SQL 服务器登录。除非有特殊理由,否则不应为应用程序授予如下权限:直接针对任何表执行创建、检索、更新、破坏/删除 (CRUD) 操作。
注意 存储过程在数据库系统的安全上下文中运行。尽管您可以通过为应用程序分配对特定存储过程的权限来限制它的逻辑操作,但不能限制存储过程所执行的操作的结果。存储过程是受信任代码。必须使用数据库权限来确保存储过程的接口安全。
限制未授权的调用方
您的代码在连接到数据库之前必须基于角色或标识为用户授权。角色检查通常用在应用程序的业务逻辑中,但是,如果您不能清楚地区分业务逻辑和数据访问逻辑,请对数据库访问方法使用主体权限需求。
以下属性确保只有作为 Manager 角色成员的用户才能调用 DisplayCustomerInfo 方法:
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="Manager")] public void DisplayCustomerInfo(int CustId) { }
如果需要其他授权粒度,并且需要在数据访问方法内部执行基于角色的逻辑,请使用命令性主体权限需求或显式的角色检查,如下面的代码片断所示:
using System.Security; using System.Security.Permissions; public void DisplayCustomerInfo(int CustId) { try { // 用来验证调用方是 manager 的命令性主体权限 // 角色检查 PrincipalPermission principalPerm = new PrincipalPermission( null, "Manager"); // 仅在调用方是“Manager”角色的成员时才执行 // 随后的代码 } catch( SecurityException ex ) { . . . } }
下面的代码片断使用显式的程序设计角色检查来确保调用方是 Manager 角色的成员:
public void DisplayCustomerInfo(int CustId) { if(!Thread.CurrentPrincipal.IsInRole("Manager")) { . . . } }
限制未授权的代码
通过使用 .NET Framework 代码访问安全性(特别是代码标识需求),可以限制能够访问数据访问类和方法的程序集。
例如,如果您只希望由公司或特定开发组织编写的代码能够使用您的数据访问组件,请使用 StrongNameIdentityPermission ,并要求调用程序集具有一个带有指定公钥的强名称,如下面的代码片断所示:
using System.Security.Permissions; . . . [StrongNameIdentityPermission(SecurityAction.LinkDemand, PublicKey="002...4c6")] public void GetCustomerInfo(int CustId) { }
要提取给定程序集的公钥的文本表示形式,请使用下面的命令:
sn -Tp assembly.dll
注意 在 –Tp 开关中使用大写的“T”。
因为 Web 应用程序的程序集是动态编译的,所以对于这些程序集不能使用强名称。这使得很难将数据访问程序集的使用限制在特定的 Web 应用程序上。最佳方法是开发一个自定义权限,并要求该权限来自数据访问组件。完全信任 Web 应用程序(或任何完全受信任代码)可以调用您的组件。但是,部分信任代码只有在被授予了自定义权限之后,才能调用您的数据访问组件。
有关自定义权限的示例实现,请参阅本指南“如何”部分中的如何:创建自定义加密权限。
限制数据库中的应用程序
首选方法是为应用程序用来连接到数据库的 Windows 帐户创建一个 SQL Server 登录权限,然后将 SQL Server 登录映射到数据库中的某个数据库用户。将该数据库用户放在用户定义的数据库角色中,并授予该角色相应的权限。理想情况下,应该只为该角色授予对应用程序所使用的存储过程的执行访问权限。
有关如何配置此方法的详细信息,请参阅模块 19 确保 ASP.NET 应用程序和 Web 服务的安全中的“为 ASP.NET 应用程序配置数据访问权限”。