Introduction
Almost all enterprise applications use authorization in some level. Authorization is used to check if a user is allowed to perform some specific operation in the application. ASP.NET Boilerplate defines a permission basedinfrastructure to implement authorization.
几乎所有的企业应用程序使用授权
授权被用来检查用户是否被允许一些具体操作中的应用。
ASP.NET的模板定义实现授权许可基础的接口。
About IPermissionChecker
Authorization system uses IPermissionChecker to check permissions. While you can implement it in your own way, it's fully implemented in module-zero project. If it's not implemented, NullPermissionChecker is used which grants all permissions to everyone.
授权系统使用ipermissionchecker to检查权限。当你实现它自己的方式,这是完全implemented in模块零的项目。
如果不实现,nullpermissionchecker被用来定义所有人的权限。
Defining Permissions
A unique permission is defined for each operation needed to be authorized. We should define a permission before use it. ASP.NET Boilerplate is designed to be modular. So, different modules can have different permissions. A module should create a class derived from AuthorizationProvider in order to define it's permissions. An example authorization provider is shown below:
为每个需要授权的操作定义唯一的权限。在使用许可之前,我们应该定义它。ASP.NET样板的设计是模块化的。因此,不同的模块可以有不同的权限。一个模块应该创建一个派生类从AuthorizationProvider来定义它的权限。下面给出一个示例授权提供者:
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 has methods to get and create permissions.
A permission have some properties to define it:
- Name: a system-wide unique name. It's good idea to define a const string for a permission name instead of a magic string. We prefer to use . (dot) notation for hierarchical names but it's not required. You can set any name you like. Only rule is that it must be unique.
- 系统范围唯一名称。为一个权限名称而不是一个字符串定义一个const字符串是个好主意。我们更喜欢使用。层次结构名称的(点)符号,但不是必需的。您可以设置任何您喜欢的名称。唯一的规则是它必须是唯一的。
- Display name: A localizable string that can be used to show permission, later in UI.
- 可本地化的字符串,可以用来显示权限,后来在UI。
- Description: A localizable string that can be used to show definition of the permission, later in UI.
- 可本地化的字符串,可以用来显示权限定义,在以后的UI。
- MultiTenancySides: For multi-tenant application, a permission can be used by tenants or the host. This is a Flags enumeration and thus a permission can be used in both sides.
- 对于多租户应用程序,租户或主机可以使用权限。这是一个枚举标记,因此可以在两边使用权限。
- featureDependency: Can be used to declare a dependency to features. Thus, this permission can be granted only if feature dependency is satisfied. It waits for an object implements IFeatureDependency. Default implementation is the SimpleFeatureDependency class. Example usage:
new SimpleFeatureDependency("MyFeatureName")
- 可以用来声明对特性的依赖关系。因此,只有在满足特性依赖时才能授予此权限。它在等待一个对象实现ifeaturedependency。默认的实现是simplefeaturedependency类。使用示例:新simplefeaturedependency(“myfeaturename”)
A permission can have a parent and child permissions. While this does not effect permission checking, it may help to group permissions in UI.
After creating an authorization provider, we should register it in PreInitialize method of our module:
权限可以具有父级和子级权限。虽然这不影响权限检查,但它可能有助于在用户界面中分组权限。
在创建一个授权商,我们应该登记在分发我们的模块的方法:
Configuration.Authorization.Providers.Add<MyAuthorizationProvider>();
Authorization providers are registered to dependency injection automatically. So, an authorization provider can inject any dependency (like a repository) to build permission definitions using some other sources.
授权提供者自动注册到依赖注入。因此,授权提供者可以注入任何依赖项(如存储库)以使用其他来源构建权限定义。
Checking Permissions(检查权限)
Using AbpAuthorize Attribute
AbpAuthorize (AbpMvcAuthorize for MVC Controllers and AbpApiAuthorize for Web API Controllers) attribute is the easiest and most common way of checking permissions. Consider the application service method shown below:
abpauthorize(abpmvcauthorize用于Web API控制器MVC控制器和abpapiauthorize)检查权限属性是最简单、最常用的方式。考虑下面所示的应用程序服务方法:
[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. }
CreateUser method can not be called by a user who is not granted for permission "Administration.UserManagement.CreateUser".
AbpAuthorize attribute also checks if current user is logged in (using IAbpSession.UserId). So, if we declare an AbpAuthorize for a method, it only checks for login:
[AbpAuthorize] public void SomeMethod(SomeMethodInput input) { //A user can not execute this method if he did not login. }
AbpAuthorize attribute notes
ASP.NET Boilerplate uses power of dynamic method interception for authorization. So, there is some restrictions for the methods use AbpAuthorize attribute.
ASP.NET样板使用授权的动态方法拦截能力。所以,有一些限制使用的方法abpauthorize属性。
- Can not use it for private methods.
- Can not use it for static methods.
- Can not use it for methods of a non-injected class (We must use dependency injection).
Also,
- Can use it for any public method if the method is called over an interface (like Application Services used over interface).
- A method should be virtual if it's called directly from class reference (like ASP.NET MVC or Web API Controllers).
- A method should be virtual if it's protected.
Notice: There are four types of authorize attributes:
- In an application service (application layer), we use Abp.Authorization.AbpAuthorize attribute.
- In an MVC controller (web layer), we use Abp.Web.Mvc.Authorization.AbpMvcAuthorize attribute.
- In ASP.NET Web API, we use Abp.WebApi.Authorization.AbpApiAuthorize attribute.
- In ASP.NET Core, we use Abp.AspNetCore.Mvc.Authorization.AbpMvcAuthorize attribute.
This difference comes from inheritance. In application layer it's completely ASP.NET Boilerplate's implementation and does not extend any class. But, int MVC and Web API, it inherits from Authorize attributes of those frameworks.
这种差异来自于继承。在应用层,它是完全ASP.NET样板的实施并没有扩展任何类。但是,MVC和Web API继承了这些框架的授权属性。
Suppress Authorization(禁止授权)
You can disable authorization for a method/class by adding AbpAllowAnonymous attribute to aplication services. Use AllowAnonymous for MVC, Web API and ASP.NET Core Controllers, which are native attributes of these frameworks.
您可以通过添加abpallowanonymous属性应用服务禁用方法/类授权。使用allowanonymous MVC,Web API和ASP.NET的核心控制器,这是这些框架固有的属性。
Using IPermissionChecker
While AbpAuthorize attribute pretty enough for most cases, there must be situations we should check for a permission in a method body. We can inject and use IPermissionChecker for that as shown in the example below:
而abpauthorize属性多数情况下不够漂亮,必须有情况我们应该检查在方法体的权限。我们可以注入用IPermissionChecker,如以下示例所示:
public void CreateUser(CreateOrUpdateUserInput input) { if (!PermissionChecker.IsGranted("Administration.UserManagement.CreateUser")) { throw new AbpAuthorizationException("You are not authorized to create user!"); } //A user can not reach this point if he is not granted for "Administration.UserManagement.CreateUser" permission. }
Surely, you can code any logic since IsGranted simply returns true or false (It has Async version also). If you simply check a permission and throw an exception as shown above, you can use the Authorize method:
当然,你可以从任何代码逻辑简单得返回TRUE或FALSE(具有异步版本)。如果只检查权限并抛出一个异常,如上所示,您可以使用授权方法:
public void CreateUser(CreateOrUpdateUserInput input) { PermissionChecker.Authorize("Administration.UserManagement.CreateUser"); //A user can not reach this point if he is not granted for "Administration.UserManagement.CreateUser" permission. }
Since authorization is widely used, ApplicationService and some common base classes inject and define PermissionChecker property. Thus, permission checker can be used without injecting in application service classes.
由于授权的应用非常广泛,应用服务和一些常见的基类定义属性注入和PermissionChecker。因此,可以在不注入应用程序服务类的情况下使用权限检查器。
In Razor Views
Base view class defines IsGranted method to check if current user has a permission. Thus, we can conditionally render the view. Example:
View基类定义检查当前用户有权限的权限的方法。因此,我们可以有条件地呈现视图。例子:
@if (IsGranted("Administration.UserManagement.CreateUser")) { <button id="CreateNewUserButton" class="btn btn-primary"><i class="fa fa-plus"></i> @L("CreateNewUser")</button> }
Client Side (Javascript)(客户端)
In the client side, we can use API defined in abp.auth namespace. In most case, we need to check if current user has a specific permission (with permission name). Example:
在客户端,我们可以使用API在abp.auth命名空间定义。在大多数情况下,我们需要检查当前用户是否有特定的权限(使用权限名称)。例子:
abp.auth.isGranted('Administration.UserManagement.CreateUser');
You can also use abp.auth.grantedPermissions to get all granted permissions or abp.auth.allPermissions to get all available permission names in the application. Check abp.auth namespace on runtime for others.
你也可以使用abp.auth.grantedpermissions得到所有授予的权限或abp.auth.allpermissions中获得所有可用的权限名称。检查abp.auth命名空间在运行时为他人。
Permission Manager(权限管理)
We may need to definitions of permission. IPermissionManager can be injected and used in that case.