使用AngularJS对路由进行安全性处理的方法

简介

自从出现以后,AngularJS已经被使用很长时间了。 它是一个用于开发单页应用(SPA)的javascript框架。 它有一些很好的特性,如双向绑定、指令等。 这篇文章主要介绍Angular路由安全性策略。 它是一个可用Angular开发实现的客户端安全性框架。 我已经对它进行了测试。 除了保证客户端路由安全性外,你也需要保证服务器端访问的安全性。 客户端安全性策略有助于减少对服务器进行额外的访问。 然而,如果一些人采用欺骗浏览器的手段访问服务器,那么服务器端安全性策略应当能够拒绝未授权的访问。 在这文章中,我仅对客户端安全性策略进行讨论。

1 在应用模块层面定义全局变量

为应用定义角色:

rush:js;"> var roles = { superUser: 0,admin: 1,user: 2 };

为应用定义未授权访问的路由:

rush:js;"> var routeForUnauthorizedAccess = '/SomeAngularRouteForUnauthorizedAccess';

2 定义授权服务

rush:js;"> appModule.factory('authorizationService',function ($resource,$q,$rootScope,$location) { return { // 将权限缓存到 Session,以避免后续请求不停的访问服务器 permissionModel: { permission: {},isPermissionLoaded: false },permissionCheck: function (roleCollection) { // 返回一个承诺(promise). var deferred = $q.defer();
  // 这里只是在承诺的作用域中保存<a href="https://www.jb51.cc/tag/yige/" target="_blank" class="keywords">一个</a>指向上层作用域的指针。
  var parentPointer = this;

  // 检查是否已从服务<a href="https://www.jb51.cc/tag/huoqu/" target="_blank" class="keywords">获取</a>到权限对象(已<a href="https://www.jb51.cc/tag/denglu/" target="_blank" class="keywords">登录</a><a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>的角色列表)
  if (this.permissionModel.isPermissionLoaded) {

    // 检查当前<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>是否有权限访问当前路由
    this.getPermission(this.permissionModel,roleCollection,deferred);
  } else {
    // 如果还没权限对象,我们会去服务端<a href="https://www.jb51.cc/tag/huoqu/" target="_blank" class="keywords">获取</a>。
    // 'api/permissionService' 是本例子中的 web 服务地址。

    $resource('/api/permissionService').get().$promise.then(function (response) {
      // 当服务器返回之后,我们开始填充权限对象
      parentPointer.permissionModel.permission = response;

      // 将权限对象处理完成的<a href="https://www.jb51.cc/tag/biaoji/" target="_blank" class="keywords">标记</a>设为 true 并保存在 Session,
      // Session 中的<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>,在后续的路由请求中可以重用该权限对象
      parentPointer.permissionModel.isPermissionLoaded = true;

      // 检查当前<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>是否有必须角色访问该路由
      parentPointer.getPermission(parentPointer.permissionModel,deferred);
    }
    );
  }
  return deferred.promise;
},//<a href="https://www.jb51.cc/tag/fangfa/" target="_blank" class="keywords">方法</a>:检查当前<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>是否有必须角色访问该路由
//'permissionModel' 保存了从服务端返回的当前<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>的角色信息
//'roleCollection' 保存了可访问当前路由的角色列表
//'deferred' 是用来处理承诺的对象
getPermission: function (permissionModel,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) {
    // 如果<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>没有必须的权限,我们把<a href="https://www.jb51.cc/tag/yonghu/" target="_blank" class="keywords">用户</a>引导到无权访问<a href="https://www.jb51.cc/tag/yemian/" target="_blank" class="keywords">页面</a>
    $location.path(routeForUnauthorizedAccess);
    // 由于这个处理会有延时,而这期间<a href="https://www.jb51.cc/tag/yemian/" target="_blank" class="keywords">页面</a>位置可能发生改变, 
    // 我们会一直监视 $locationChangeSuccess 事件
    // 并且当该事件发生的时,就把掉承诺<a href="https://www.jb51.cc/tag/jiejue/" target="_blank" class="keywords">解决</a>掉。
    $rootS<a href="https://www.jb51.cc/tag/cop/" target="_blank" class="keywords">cop</a>e.$on('$locationChangeSuccess',function (next,current) {
      deferred.resolve();
    });
  } else {
    deferred.resolve();
  }
}

};
});

3 加密路由

然后让我们用我们的努力成果来加密路由:

rush:js;"> var appModule = angular.module("appModule",['ngRoute','ngResource']) .config(function ($routeProvider,$locationProvider) { $routeProvider .when('/superUserSpecificRoute',{ templateUrl: '/templates/superUser.html',// 路由的 view/template 路径 caseInsensitiveMatch: true,controller: 'superUserController',// 路由的 angular 控制器 resolve: { // 在这我们将使用我们上面的努力成果,调用授权服务 // resolve 是 angular 中一个非常赞的特性,可以确保 // 只有当它下面提到的承诺被处理之后 // 才将控制器(在本例中是 superUserController)应用到路由。 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',controller: 'adminController',$route) { return authorizationService.permissionCheck([roles.admin]); },} }) .when('/adminSuperUserSpecificRoute',{ templateUrl: '/templates/adminSuperUser.html',controller: 'adminSuperUserController',$route) { return authorizationService.permissionCheck([roles.admin,roles.superUser]); },} }); });

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...