Abp权限系统使用IPermissionChecker去检查授权。同时你可以根据需要实现你自己的方式,在module-zero项目中已经完整实现了。如果IPermissionChecker没有被实现,NullPermissionChecker会被使用于授权所有权限给每个人。
定义权限
在使用验证权限前,我们需要为每一个操作定义唯一的权限。Abp的设计是基于模块化,所以不同的模块可以有不同的权限。为了定义权限,一个模块应该创建AuthorizationProvider的派生类。MyAuthorizationProvider继承自AuthorizationProvider,换句话说就是AuthorizationProvider派生出MyAuthorizationProvider。例子如下:
public class MyAuthorizationProvider : AuthorizationProvider { public override void SetPermissions(IPermissionDefinitionContext context) { var administration = context.CreatePermission("Administration"); var userManagement = administration.CreateChildPermission("Administration.UserManagement"); userManagement.CreateChildPermission("Administration.UserManagement.CreateUser"); var roleManagement = administration.CreateChildPermission("Administration.RoleManagement"); } }
IPermissionDefinitionContext 有方法去获取和创建权限。
一个权限有以下属性:
Name:系统范围内的唯一名字。把它定义为一个字符串常量是个不错的注意。我们倾向于将“.”分割不同的层级,但并不要求这么做。你可以设置你任何喜欢的名字。唯一的规则就是这个名字必须是唯一的。
Display Name:使用一个本地化的字符串去显示权限到UI。
Description:和Display Name类似。
IsGrantedByDefault:此权限是否授权给(已登陆)所有用户,除非显示指定。通常设置为False(默认值)。
MultiTenancySides:对租户应用程序,一个权限可以基于租户或者主机(原文:host)。这是个枚举标识,因此权限可以应用于不同方面(原文:Both Sides)。
一个权限可以有父权限和子权限。当然,这不会影响权限检查,它只是在UI层对权限归类有好处。创建authorizationprovider之后,我们应该在模块的PreIntialize方法对它进行注册。如下:
Configuration.Authorization.Providers.Add<MyAuthorizationProvider>()
authorizationprovider会自动注册到依赖注入系统中。因此,authorization provider可以注入任何依赖(像是Repository)从而使用其他资源去创建权限定义。
检查权限
1.使用AbpAuthorize特性(Using AbpAuthorize attribute)
AbpAuthorize(AbpMvcAuthorize 对应 MVC Controllers and AbpApiAuthorize 对应 Web API Controllers)特性是最简单和常用的方法去检查权限。请考虑如下application service方法:
[AbpAuthorize("Administration.UserManagement.CreateUser")] public void CreateUser(CreateUserInput input) { //A user can not execute this method if he is not granted for "Administration.UserManagement.CreateUser" permission. }
没有获得“Administration.UserManagement.CreateUser”权限的用户不能够调用CreateUser。
AbpAuthorize 特性也检查当前用户是否登录 (使用 IAbpSession.UserId)。因此,如果我们将某个方法声明为AbpAuthorize 特性,它至少会检查用户是否登录。代码如下: [AbpAuthorize]
public void SomeMethod(SomeMethodInput input) { //A user can not execute this method if he did not login. }
2.AbpAuthorize属性说明(AbpAuthorize attribute notes)
Abp使用动态方法拦截进行权限验证。因此,使用AbpAuthorize特性的方法会有些限制。如下:
不能应用于私有(private)方法
不能应用于静态(static)方法
不能应用于非注入(non-injected)类(我们必须用依赖注入)。
此外,
AbpAuthorize特性可以应用于任何的Public方法,如果此方法被接口调用(比如在Application Services中通过接口调用)
方法是虚(virtual)方法,如果此方法直接被类引用进行调用(像是ASP.NET MVC 或 Web API 的控制器)。
方式是虚(virtual)方法,如果此方法是protected。
注意:有三种AbpAuthorize 特性:
(1)在应用程序服务中(application layer),我们使用Abp.Authorization.AbpAuthorize;
(2)在MVC控制器(web layer)中,我们使用Abp.Web.Mvc.Authorization.AbpMvcAuthorize;
(3)在ASP.NET Web API,我们使用 Abp.WebApi.Authorization.AbpApiAuthorize。
这三个类继承自不同的地方。
在MVC中,它继承自MVC自己的Authorize类。
在Web API,它继承自Web API 的Authorize类。因此,它最好是继承到MVC和Web API中。
但是,在Application 层,它完全是由Abp自己实现没有扩展子任何类。
3.使用IPermissionChecker
AbpAuthorize 适用于大部分的情况,但是某些情况下,我们还是需要自己在方法体里进行权限验证。我们可以注入和使用IPermissionChecker对象。如下边的代码所示: