在上篇讲Asp.net MVC权限设计的文章中,利用了微软企业库的安全模块。该设计可以适用于其他winform,asp.net程序。
http://www.cnblogs.com/huyq2002/archive/2012/01/17/2324609.html
但是它有一个问题,所有规则都保存在配置文件 - web.config或app.config中。在生产环境中,系统需要从数据库中加载规则,并允许在运行时修改安全规则。
下面详细绍如何扩展安全模块 Microsoft Enterprise Library Security Application Block,从SQL Server数据库加载权限规则。
要运行示例代码,需要安装VS2010+ ASP.NET MVC3和SQLSERVER 2000及以上数据库。
1) 创建规则表 - AuthorizationRule和插入3条规则。
数据库脚本如下 (需要修改数据库名)
USE [VehicleMDM]
GO
/****** Object: Table [dbo].[AuthorizationRule] Script Date: 03/20/2012 11:34:41 ******/
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[AuthorizationRule]') AND type in (N'U'))
DROP TABLE [dbo].[AuthorizationRule]
GO
USE [VehicleMDM]
GO
/****** Object: Table [dbo].[AuthorizationRule] Script Date: 03/20/2012 11:34:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AuthorizationRule](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NULL,
[Description] [nvarchar](200) NULL,
[Expression] [nvarchar](100) NULL,
[Parent] [int] NULL,
CONSTRAINT [PK_AuthorizationRule] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT INTO [AuthorizationRule]
([Name]
,[Description]
,[Expression]
,[Parent])
VALUES
('IsAdministrator','Is Administrator Check','R:Administrator',null)
INSERT INTO [AuthorizationRule]
([Name]
,[Description]
,[Expression]
,[Parent])
VALUES
('IsDataSteward','Is DataSteward Check','R:Administrator OR R:DataSteward',null)
INSERT INTO [AuthorizationRule]
([Name]
,[Description]
,[Expression]
,[Parent])
VALUES
('IsUser','Is User Check','R:User OR R:DataSteward OR R:Administrator',null)
GO
2)组件设计
类图
![](http://code.msdn.microsoft.com/site/view/file/54458/1/class.bmp)
- IAuthorizationRepository: 接口,描述rule repository, 包含属性 Name, Connectionstring
- SqlAuthorizationData: IAuthorizationRepository接口针对SQL Server的实现.
- SqlAuthorizationProviderData:该类扩展了原组件里面的AuthorizationProviderData类的方法GetRegistrations,并且会保存一组iSqlAuthorizationData 类的实例
- IAuthorizationRule: 规则的主要接口,包含属性Name, Expression
- SqlAuthorizationRule: 规则接口的SQL Server的实现
- SqlAuthorizationRuleProvider:扩展了原组件的AuthorizationProvider类, 它从配置文件中读取SqlAuthorizationProviderData,获得数据库连接串,利用 ADO.net 实例化SqlAuthorizationRule数组,并且利用Cache Application Block实现规则的缓存来提高性能。
代码示例
/// <summary>
/// Evaluates the specified authority against the specified context.
/// </summary>
/// <param name="principal">Must be an <see cref="IPrincipal"/> object.</param>
/// <param name="ruleName">The name of the rule to evaluate.</param>
/// <returns><c>true</c> if the expression evaluates to true,
/// otherwise <c>false</c>.</returns>
public override bool Authorize(IPrincipal principal, string ruleName)
{
if (principal == null) throw new ArgumentNullException("principal");
if (ruleName == null || ruleName.Length == 0) throw new ArgumentNullException("ruleName");
//get the rules from the cache
if (m_CacheManager.ContainsKey(CACHEKEY))
{
GetAuthorizationRulesFromCache();
}
else
{
GetAuthorizationRules();
}
InstrumentationProvider.FireAuthorizationCheckPerformed(principal.Identity.Name, ruleName);
BooleanExpression booleanExpression = GetParsedExpression(ruleName);
if (booleanExpression == null)
{
throw new InvalidOperationException(string.Format("Authorization Rule Not Found", ruleName));
}
bool result = booleanExpression.Evaluate(principal);
if (result == false)
{
InstrumentationProvider.FireAuthorizationCheckFailed(principal.Identity.Name, ruleName);
}
return result;
}
3)部署
(1)修改App.config/Web.config中的权限模块的配置,类似于下( 修改数据库连接)
<securityConfiguration defaultAuthorizationInstance="RulesProvider" defaultSecurityCacheInstance="">
<authorizationProviders>
<add type="VehicleMaster.Infrastructure.Common.Utilities.Security.SqlAuthorizationRuleProvider, Utilities" name="RulesProvider">
<repositories>
<add name="default" connectionstring="Data Source=10.234.58.172\SQL_DEV;Initial Catalog=VehicleMDM;User Id=sa;Password=Passw0rd;"/>
</repositories>
</add>
</authorizationProviders>
</securityConfiguration>
(2) 修改NHibernate.config的数据库连接
(3) 要模拟不同的客户权限访问, 修改代码中UserService类的下面代码(示例程序利用域帐号模拟不同的角色)
else
{
//user.AddRole(new UserRole(UserRoleConstants.Administrator));
user.AddRole(new UserRole(UserRoleConstants.DataSteward));
user.AddRole(new UserRole(UserRoleConstants.User));
user.CurrentUserRoleIndex = 0;
}
return user;
(4) 基于规则的
权限设置于MVC controller层, 下面设置保证只有administrator才可以访问about页面.
[RuleAuthorize("IsAdministrator")]
public ActionResult About()
{
return View();
}
如果用户无该角色,访问About页面会得到以下信息
(5)Cache的配置也保存在Web.Config/App.config中
<cachingConfiguration defaultCacheManager="CacheManager">
<cacheManagers>
<add name="CacheManager" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
numberToRemoveWhenScavenging="10" backingStoreName="Cache" />
</cacheManagers>
<backingStores>
<add name="Cache" type="Microsoft.Practices.EnterpriseLibrary.Caching.Database.DataBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching.Database, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
encryptionProviderName="" databaseInstanceName="CacheDB" partitionName="AuthorizationCache" />
</backingStores>
</cachingConfiguration>
<connectionStrings>
<add name="CacheDB" connectionString="Data Source=10.234.58.172\SQL_DEV;Initial Catalog=VehicleMDM;Persist Security Info=True;User ID=sa;Password=Passw0rd;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
<add name="ApplicationServices" connectionString="Data Source=10.234.58.172\SQL_DEV;Initial Catalog=VehicleMDM;User Id=sa;Password=Passw0rd;" providerName="System.Data.SqlClient" />
</connectionStrings>
该版本未实现对规则的增删改功能,读者可以自己实现。
代码从下面的链接下载(抱歉原文是英文的)