Secure routing using AngularJS

  • 2020-06-15 07:49:32
  • OfStack

Introduction to the

AngularJS has been in use for a long time since its inception. It is an javascript framework for developing single-page applications (SPA). It has some nice features, such as two-way binding, instructions, etc. This article focuses on the Angular routing security policy. It is a client-side security framework that can be implemented with Angular development. I have tested it. In addition to securing client-side routing, you also need to secure server-side access. Client-side security policies help reduce additional access to the server. However, if someone is spoofing the browser to access the server, the server-side security policy should be able to deny unauthorized access. In this article, I will only discuss client-side security policies.

Define global variables at the application module level

Define roles for applications:


var roles = {
  superUser: 0,
  admin: 1,
  user: 2
};

Define unauthorized access routes for applications:


var routeForUnauthorizedAccess = '/SomeAngularRouteForUnauthorizedAccess';

Define authorization services


appModule.factory('authorizationService', function ($resource, $q, $rootScope, $location) {
  return {
    //  Cache permissions to  Session To avoid subsequent requests to the server 
    permissionModel: { permission: {}, isPermissionLoaded: false },
 
    permissionCheck: function (roleCollection) {
      //  return 1 A promise (promise).
      var deferred = $q.defer();
 
      //  This is saved only in the scope of the commitment 1 A pointer to the upper scope. 
      var parentPointer = this;
 
      //  Check whether the permission object has been obtained from the service ( A list of roles for the logged in user )
      if (this.permissionModel.isPermissionLoaded) {
 
        //  Checks whether the current user has permission to access the current route 
        this.getPermission(this.permissionModel, roleCollection, deferred);
      } else {
        //  If we don't have permission objects yet, we'll go to the server and get them. 
        // 'api/permissionService'  In this example  web  Service address. 
 
        $resource('/api/permissionService').get().$promise.then(function (response) {
          //  When the server returns, we start populating the permission object 
          parentPointer.permissionModel.permission = response;
 
          //  Sets the mark for completion of permission object processing to  true  And stored in a  Session . 
          // Session  The permissions object can be reused in subsequent routing requests 
          parentPointer.permissionModel.isPermissionLoaded = true;
 
          //  Checks whether the current user has a mandatory role to access the route 
          parentPointer.getPermission(parentPointer.permissionModel, roleCollection, deferred);
        }
        );
      }
      return deferred.promise;
    },
 
    // methods : Checks whether the current user has a mandatory role to access the route 
    //'permissionModel'  The role information of the current user returned from the server is saved 
    //'roleCollection'  A list of roles that have access to the current route is saved 
    //'deferred'  Is the object used to process the promise 
    getPermission: function (permissionModel, roleCollection, deferred) {
      var ifPermissionPassed = false;
 
      angular.forEach(roleCollection, function (role) {
        switch (role) {
          case roles.superUser:
            if (permissionModel.permission.isSuperUser) {
              ifPermissionPassed = true;
            }
            break;
          case roles.admin:
            if (permissionModel.permission.isAdministrator) {
              ifPermissionPassed = true;
            }
            break;
          case roles.user:
            if (permissionModel.permission.isUser) {
              ifPermissionPassed = true;
            }
            break;
          default:
            ifPermissionPassed = false;
        }
      });
      if (!ifPermissionPassed) {
        //  If the user does not have the necessary permissions, we direct the user to a page where he does not have access 
        $location.path(routeForUnauthorizedAccess);
        //  Since there is a delay in this process, during which time the page position may change,  
        //  We will be 1 Direct monitoring  $locationChangeSuccess  The event 
        //  And when the event occurs, the promise is resolved. 
        $rootScope.$on('$locationChangeSuccess', function (next, current) {
          deferred.resolve();
        });
      } else {
        deferred.resolve();
      }
    }
  };
});

3 Encrypted routing

Then let's use our efforts to encrypt the route:


var appModule = angular.module("appModule", ['ngRoute', 'ngResource'])
  .config(function ($routeProvider, $locationProvider) {
    $routeProvider
      .when('/superUserSpecificRoute', {
        templateUrl: '/templates/superUser.html', //  The routing  view/template  The path 
        caseInsensitiveMatch: true,
        controller: 'superUserController', //  The routing  angular  The controller 
        resolve: {
          //  Here we will use our efforts above to invoke the authorization service 
          // resolve  is  angular  In the 1 A great feature to make sure 
          //  Only after the commitments mentioned below have been processed 
          //  Before the controller ( In this case, yes  superUserController) Apply to routing. 
          permission: function (authorizationService, $route) {
            return authorizationService.permissionCheck([roles.superUser]);
          },
        }
      })
      .when('/userSpecificRoute', {
        templateUrl: '/templates/user.html',
        caseInsensitiveMatch: true,
        controller: 'userController',
        resolve: {
          permission: function (authorizationService, $route) {
            return authorizationService.permissionCheck([roles.user]);
          },
        }
      })
      .when('/adminSpecificRoute', {
        templateUrl: '/templates/admin.html',
        caseInsensitiveMatch: true,
        controller: 'adminController',
        resolve: {
          permission: function (authorizationService, $route) {
            return authorizationService.permissionCheck([roles.admin]);
          },
        }
      })
      .when('/adminSuperUserSpecificRoute', {
        templateUrl: '/templates/adminSuperUser.html',
        caseInsensitiveMatch: true,
        controller: 'adminSuperUserController',
        resolve: {
          permission: function (authorizationService, $route) {
            return authorizationService.permissionCheck([roles.admin, roles.superUser]);
          },
        }
      });
  });


Related articles: