A Preliminary Study on the permission design and a preliminary study on the permission Design

Source: Internet
Author: User

A Preliminary Study on the permission design and a preliminary study on the permission Design

For large and small projects, we need to design permissions. We all want to design a general permission and make the permissions more complex. Now we have understood the design concept of the relevant project and think the design is very simple, however, the implementation methods and ideas are intriguing.

This article only introduces the database design of AbpPermissions. For other table structures, refer to the source code for [Name (unique Id of the resource file)] and [IsGranted (whether to authorize)]., [RoleId, UserId (authorized to a role or user)]

All the constant data of the ABP is passed when the program is started.AbpKernelModuleOne-time loading is completed, and can be directly read from the memory when used

Public override void PostInitialize () {RegisterMissingComponents (); IocManager. resolve <LocalizationManager> (). initialize (); // Initialize the resource file IocManager. resolve <NavigationManager> (). initialize (); // Initialize the IocManager permission. resolve <PermissionManager> (). initialize (); // Initialize IocManager. resolve <SettingDefinitionManager> (). initialize ();}

Permissions can be divided into front-end permission judgment and back-end permission judgment. JS judges permissions by referencing <script src = "~ /AbpScripts/GetScripts "type =" text/javascript "> </script> This script loads the relevant JS objects and methods to the JS file.

  

There are two red boxes in the left-side Navigation Pane. The MainMenu is the default property of the system, and the Test is the custom property. The following code

Public class authorization: NavigationProvider {public override void SetNavigation (INavigationProviderContext context) {SetNavigation1 (context); SetTestNavigation (context);} private void SetNavigation1 (INavigationProviderContext context) {context. manager. mainMenu // default navigation property. addItem (new MenuItemDefinition ("Questions", new LocalizableString ("Questions", ModuleZeroSampleProjectConsts. localizationSourceName), url: "#/questions", icon: "fa-question", requiredPermissionName: "Questions" // determine permissions based on variables )). addItem (new MenuItemDefinition ("Users", new LocalizableString ("Users", ModuleZeroSampleProjectConsts. localizationSourceName), url: "#/users", icon: "fa-users");} public const string TestName = "Test "; // custom navigation attribute private void SetTestNavigation (INavigationProviderContext context) {var testMenu = new MenuDefinition (TestName, new FixedLocalizableString ("Frontend menu"); context. manager. menus [TestName] = testMenu; testMenu. addItem (new MenuItemDefinition ("Questions", new LocalizableString ("Questions", ModuleZeroSampleProjectConsts. localizationSourceName), url: "#/questions", icon: "fa-question ")). addItem (new MenuItemDefinition ("Users", new LocalizableString ("Users", ModuleZeroSampleProjectConsts. localizationSourceName), url: "#/users", icon: "fa-users "));}}View Code

The JS Code is loaded by GetScriptAsync () of the NavigationScriptManager class, and the permission is judged. The obtained navigation data is obtained through the abp. nav. menus. MainMenu

Public async Task <IReadOnlyList <UserMenu> GetMenusAsync (long? UserId) // load the relevant navigation {var userMenus = new List <UserMenu> (); foreach (var menu in _ navigationManager. menus. values) // all navigation attributes initialized by default {userMenus. add (await GetMenuAsync (menu. name, userId);} return userMenus;} private async Task <int> FillUserMenuItems (long? UserId, IList <dimension> menuItemDefinitions, IList <UserMenuItem> userMenuItems) {var dimensions = 0; foreach (var values in menuItemDefinitions) {if (MenuItemDefinition. RequiresAuthentication &&! UserId. HasValue) {continue;} if (! String. IsNullOrEmpty (menuItemDefinition. RequiredPermissionName )&&(! UserId. HasValue |! (Await PermissionChecker. isGrantedAsync (userId. value, menuItemDefinition. requiredPermissionName) // determines whether the current user has the navigation permission {continue;} var userMenuItem = new UserMenuItem (menuItemDefinition) based on the current user ID and permission. if (menuItemDefinition. isLeaf | (await FillUserMenuItems (userId, menuItemDefinition. items, userMenuItem. items)> 0) // recursively load the hierarchical navigation {userMenuItems. add (userMenuItem); ++ addedMenuItemCount;} return addedMenuItemCount ;}View Code

Abp. js defines many methods and attributes, and the user judges the permission to be an ABC. auth. hasPermission (). The parameter of this method is the operation permission corresponding to the background Action. If the return value of this method is True, the current user is granted the permission.

Front-end JS loads all permissions and current user permissions through the GetScript method of the AuthorizationScriptManager class

Public async Task <string> GetScriptAsync () {var allPermissionNames = _ permissionManager. getAllPermissions (false ). select (p => p. name ). toList (); // get all permissions var grantedPermissionNames = new List <string> (); if (AbpSession. userId. hasValue) {foreach (var permissionName in allPermissionNames) {if (await PermissionChecker. isGrantedAsync (AbpSession. userId. value, permissionName) {grantedPermissionNames. add (permissionName); // obtain the permissions of the current user }}var script = new StringBuilder (); script. appendLine ("(function () {"); script. appendLine (); script. appendLine ("abp. auth = abp. auth | {}; "); script. appendLine (); AppendPermissionList (script, "allPermissions", allPermissionNames); script. appendLine (); AppendPermissionList (script, "grantedPermissions", grantedPermissionNames); script. appendLine (); script. append ("}) ();"); return script. toString ();}View Code

Permission initialization definition must be integrated with AuthorizationProvider, as shown below:

Public class ModuleZeroSampleProjectAuthorizationProvider: AuthorizationProvider {public override void SetPermissions (IPermissionDefinitionContext context) {// TODO: Localize (Change FixedLocalizableString to LocalizableString) context. createPermission ("CanCreateQuestions", new FixedLocalizableString ("Can create questions"); context. createPermission ("CanDeleteQuestions", new FixedLocalizableString ("Can delete questions"); context. createPermission ("CanDeleteAnswers", new FixedLocalizableString ("Can delete answers"); context. createPermission ("CanAnswerToQuestions", new FixedLocalizableString ("Can answer to questions"), isGrantedByDefault: true );}}View Code

All permission verification is completed through AbpUserManager. The following are several important methods:

Task <bool> IsGrantedAsync (long userId, string permissionName)

(Await UserPermissionStore. HasPermissionAsync (user, new PermissionGrantInfo (permission. Name, false) checks whether the current user is granted Permissions

Take QuestionAppService as an example to describe the permission configuration. For each Service layer, set the permission [AbpAuthorize ("Questions")]. When a request is sent, the interceptor automatically verifies the permission, each Action also intercepts [AbpAuthorize ("CanCreateQuestions")]. Permission interception is implemented by AuthorizationInterceptor.

  

Permission verification is performed using the following methods:

Internal class AuthorizeAttributeHelper: IAuthorizeAttributeHelper, ITransientDependency {public async Task AuthorizeAsync (IEnumerable <IAbpAuthorizeAttribute> authorizeAttributes) {if (! AbpSession. UserId. HasValue) {throw new AbpAuthorizationException ("No user logged in! ");} Foreach (var authorizeAttribute in authorizeAttributes) {await PermissionChecker. AuthorizeAsync (authorizeAttribute. RequireAllPermissions, authorizeAttribute. Permissions); // permission check }}}View Code

  

It is recommended that you first learn how to use the source code, debug it during use, and gradually become familiar with the source code. It is really difficult to directly study the source code without using it, as the saying goes, "Practice makes perfect" should mean this. The technical level and ability of each person are different. The suggestion is just my personal opinion.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.