在这个原型上,“Business Addin”即业务插件,是开发者需要设计的业务模块,这个业务模块将使用权限控制服务来实现权限的控制;权限服务分为契约和不同的提供商两部分,服务提供商对于业务插件来说是透明的,这些服务提供商可能是:(1)简单的权限控制服务提供商;(2)基于MemberShip的权限控制服务提供商;(3)基于角色的访问控制权限服务提供商;(4)其它服务提供商。不管开发者从插件工厂获得了哪个服务提供商,他都能够使用一致的模型来使用权限控制服务,并且这些权限控制服务能够与.NET现有的安全机制兼容。“Business Addin”使用权限服务的场景如下,我们希望尽可能使权限控制服务与开发者无关并且简单可重用。
“Business Addin”业务插件使用一般场景如下:
{
// 当前用户拥有Id为“PermissionId”的权限,因此允许执行以下操作
}
else
{
// 向用户提示,您没有此操作的权限,请联系管理员给予分配“PermissionName”权限
}
这样对于开发者的好处是显而易见的:(1)开发者也开发业务系统过程中不再需要设计任何的用户-角色-权限管理的应用模块;(2)开发者可以根据需要任意定义/扩展业务插件所需的权限,这些权限的管理最终由插件工厂里的权限服务提供商来实现。
下面我们看一下相关的项目及服务定义。
运行效果图如下。在这里,我们为应用系统安装了SimplePermissionService,那么IPermissionService的提供商就是SimplePermissionService。如果用户需要其它的实现,比如ASP.NET MemberShipe实现的权限控制,就可以下载相应的插件来提供权限服务,但这对业务插件来说是透明的,它不需要做任何的代码变更。
权限服务定义如下。
{
/// <summary>
/// 权限服务契约,需要兼容.NET安全机制,即兼容IIdentity/IPrincipal/IPermission模型。
/// </summary>
public interface IPermissionService
{
/// <summary>
/// 默认权限类型。如果用户使用AddinPermission没有指定权限类型,则使用该权限。
/// </summary>
Type DefaultPermissionType { get; }
/// <summary>
/// 当前安全实体。由用户标识和角色集合组成。
/// </summary>
IPrincipal User { get; set; }
/// <summary>
/// 创建默认的权限实例。
/// </summary>
/// <returns>每次返回一个新的权限实例。</returns>
IPermission CreateDefaultPermission();
// 判断当前用户是否拥有指定的权限。
bool Demand(string permissionId);
bool Demand(string addinId, string permissionId);
bool Demand(Addin addin, string permissionId);
bool Demand(RuntimeAddin addin, string permissionId);
}
}
[assembly: AddinPermission("Guest", "Guest Permission", typeof(CustomizedPermission))]
(2)获取权限服务并请求验证权限
Context.GetFirstOrDefaultService<IPermissionService>();
if (permissionService != null)
{
if (permissionService.Demand("MyPermissionId"))
{
Response.Write("Permission demanded successfully. <br />");
}
else
{
Response.Write("Permission demanded failed. <br />");
}
}
else
{
Response.Write("Please install a Permission Service Provider first.");
}
这个拥抱变化的思想是基于面向服务架构思想来实现的,在这里,“服务=契约 + 实现,契约=面向对象中的接口,实现=实现接口的类型”。业务插件依赖的是服务的契约,并不依赖服务的实现,服务的实现针对契约的不同提供商。我们可以根据应用系统的需要,在不更改业务插件的情况下,变更服务提供商来满足实际系统的需求。
关于权限服务提供商的实现会稍微复杂一点点,一个典型的提供商一般包括:(1)相关实体管理界面,如用户/部分/角色/权限分配;(2)权限服务实现。以下是一个典型的权限管理界面了。
在这里,权限服务提供商实现时,一般需要实现:(1)定义一个默认的权限;(2)实现IPermissionService;(3)在登录时设置IPermissionService.User。
示例服务的实现如下。
{
[Service(typeof(IPermissionService))] // 注册为IPermissionService服务契约的实现。
public class WebPermissionService : IPermissionService
{
public Type DefaultPermissionType
{
get { return typeof(DefaultPermission); }
}
public IPermission CreateDefaultPermission()
{
return new DefaultPermission();
}
public IPrincipal User // 绑定HttpContext.User安全主体。
{
get
{
if(HttpContext.Current != null)
{
return HttpContext.Current.User;
}
return null;
}
set
{
if(HttpContext.Current != null)
{
HttpContext.Current.User = value;
}
}
}
// 判断当前用户是否拥有指定权限。其它重载方法省略。
public bool Demand( string addin, string permissionId)
{
IPermission permission = PermissionRegistry.GetPermission(
addin, permissionId);
if (permission != null)
{
try
{
permission.Demand();
return true;
}
catch
{
// todo: Log here.
}
}
return false;
}
// 其它重载方法......
}
}