使用自定义安全模块扩展 ASP.NET 基于角色的安全性(基于权限,页面级授权)
本项目旨在扩展默认的 ASP.NET 基于角色的安全性,以包含基于权限/页面级的授权层。同时适用于 ASP.NET 和 ASP.NET MVC。允许/拒绝访问网站资源(如“Folder/File.aspx”或“Controller/Action”)的权限规则存储在数据库中。
引言
本项目旨在扩展默认的 ASP.NET 基于角色的安全性,以包含基于权限/页面级的授权。允许/拒绝访问网站资源(如“Folder/File.aspx”)的权限规则将存储在数据库中。我们的“
”模块将根据这些权限规则验证每个请求。ADHPermissions
Module
一个基本的 ASP.NET MVC 版本(AadhaarMVC.zip)现已包含(请原谅我验证不足)。自定义安全模块的名称(包含在 MVC 项目的 Controllers 目录中)是“ADHPermissionsModuleMVC
”。我已尽量保持两个模块的版本较低,以确保更好的兼容性。Aadhaar.Data
项目使用 .NET 版本 2.0。NHibernate 版本 2.0 已用于数据库持久层。Aadhaar.MVC
使用 .NET v3.5 MVC。
背景
ASP.NET 为我们提供了非常好的默认基于角色的安全性,用于控制和授权对我们网站的访问。由于安全性是基于提供程序的,我们可以重写自己的 membership 和 role providers,并决定如何存储数据。
尽管在小型 Web 应用程序中,我们已经知道网站的结构和所需的角色,因此可以通过修改(手动或以编程方式)web.config 来直接配置访问规则,以允许/限制对各种资源/页面的访问。(例如 <allow users="user1,user2" />
<allow roles="superadmin">
)。我之前尝试过的其中一种方法是 **这里**,通过将不同位置的web.config 文件作为普通 XML 进行修改。
但是,如果我们不想修改不同位置的web.config 文件,而是希望将权限规则存储在数据库中呢?(这将为我们提供更大的灵活性来为特定位置{"Folder/File.aspx"} 创建/删除/修改权限规则)。我们的 HTTP 模块在每次请求时会检查“Request.Location
”,并根据数据库中指定的权限规则进行验证。
在此,我们提出第二种方法来扩展现有的 ASP.NET 基于角色的安全模型,通过一个 HTTPmodule
,它会捕获 Web 应用程序在请求生命周期中通知的事件。我们的 HTTPModule
应该能够在运行时验证并允许/拒绝访问任何位置。(我们将捕获 HTTPApplication.AuthorizeRequest
事件,并将我们的自定义验证逻辑注入其中)。有关 ASP.NET 应用程序页面生命周期事件以及如何通过 HTTPmodules 将自定义逻辑注入页面生命周期的更多信息,请参阅 **此处**。这样,默认的基于角色的安全性将继续工作,但我们增加了另一层自定义安全性。
另一篇解释使用 HTTPmodule
控制身份验证的优秀文章 **在此**。然而,我们的 HTTPModule
是扩展现有的 ASP.NET 基于角色的安全性,并为我们网站上的每个资源(aspx 文件)添加基于角色的权限。
本项目是原始 ASP.NET MVC 项目的精简版本。我们使用 NHibernate 进行数据持久化,因此数据库的可移植性应该不是问题,可以迁移到大多数数据库。但我们此处使用的是 MSSqlServer
数据库。如果将架构导出到其他数据库,此模块也应该能够与其他数据库一起工作。但这可能也取决于您的“角色”和“用户”信息是如何存储的。本项目使用了默认的 ASP.NET SQL Membership、Role 和 Profile 提供程序。
Using the Code
此模块基于“仅当”原则工作。(即:只有当配置了特定位置的权限规则时,此模块才会执行其验证。否则,将按正常的 ASP.NET 页面生命周期进行处理。
要添加特定位置以创建权限,请先使用权限页面底部的以下表单将位置添加到 Actions 表中。
在上例中,文件夹名称“SuperAdmin”以及相应的“Permissions.aspx”和“UserDetails.aspx”文件名已添加到现有的 actions 表中。一旦位置已按上述方式添加,就可以在权限页面顶部的以下表单的下拉列表中选择它。
GetRolesForControllerAction
方法检查特定 UserId
是否对特定资源有独占访问权限,并将布尔输出参数 HasUserPermission
设置为 true
。如果用户已经对特定资源(Controller+Action {Folder\File.aspx 在我们的例子中})拥有用户级别权限,则不再进行进一步验证,请求将正常处理。
但是,如果没有为特定 UserId
创建独占的用户级别权限,则会将指定资源的允许角色与用户的角色进行比较。
string[] permissions = Aadhaar.Data.ADHSecurityHelper.GetRolesForControllerAction
(HttpContext.Current.User.Identity.Name, out HasUserPermission,reqFolder, reqFile);
//If neither the user has a User Level Permission to the resource
//And also the Configured Permissions for the resource are not empty.
//Then check for Role Level Access
if ((!HasUserPermission) && (permissions.Length != 0))
if (!((permissions.Length == 1) && (string.IsNullOrEmpty
(permissions[0])))) //Sometimes a singular string with
//blank value was returned.
{
//If User has none of the Allowed Roles for a particular resource.
// Access will be denied.
if (!MatchUserRolesToPermissions(HttpContext.Current.User,
permissions))
{
string message = string.Format("User {0}
does not have permission to access file {1} located at {2}"
, HttpContext.Current.User.Identity.Name, reqFile,
reqFolder);
System.Diagnostics.Trace.TraceInformation(message);
Utilities.TextLog(message);
throw new System.Security.SecurityException(message);
}
}
//
用于权限的数据库表如图所示。权限存储在 aspnet_roleactions
表中,要么对应 RoleId
,要么对应 UserId
。RoleId
和 UserId
列映射到 ASP.NET Roles and Users tables
,如下所示。
关注点
如上所述,此模块是 ASP.NET MVC 模块的精简版本,因此显然也可以与 ASP.NET MVC 解决方案一起使用。NHibernatehelper
类取自此处一个关于 ASP.NET Nhibernate
提供程序(在提及的解决方案中主要使用 Mysql)的优秀教程。
本项目使用了默认的 ASP.NET Membership、Role 和 Profile 提供程序来持久化用户的 Membership、Authorization 和 Profile 信息,因为此模块旨在扩展现有的 ASP.NET 基于角色的安全性。当然,该代码也可以配置为与任何其他自定义 Membership 和 Role 提供程序一起工作。
历史
- 发布日期:2011 年 11 月 9 日
- 添加
AadhaarMVC
:2011 年 11 月 12 日
重要链接
- ASP.NET 应用程序和页面生命周期
- 使用 HTTPModule 自定义身份验证提供程序
- NHibernate .NET 提供程序
- 我之前在这个方向上的尝试,通过将不同位置的web.config 编辑为 XML:编写自己的 Membership/Role Provider & 基于角色的文件访问