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


Posted in Javascript onJune 18, 2015

 简介

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

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

为应用定义角色:
 

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

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

var routeForUnauthorizedAccess = '/SomeAngularRouteForUnauthorizedAccess';

2 定义授权服务
 

appModule.factory('authorizationService', function ($resource, $q, $rootScope, $location) {
  return {
    // 将权限缓存到 Session,以避免后续请求不停的访问服务器
    permissionModel: { permission: {}, isPermissionLoaded: false },
 
    permissionCheck: function (roleCollection) {
      // 返回一个承诺(promise).
      var deferred = $q.defer();
 
      // 这里只是在承诺的作用域中保存一个指向上层作用域的指针。
      var parentPointer = this;
 
      // 检查是否已从服务获取到权限对象(已登录用户的角色列表)
      if (this.permissionModel.isPermissionLoaded) {
 
        // 检查当前用户是否有权限访问当前路由
        this.getPermission(this.permissionModel, roleCollection, deferred);
      } else {
        // 如果还没权限对象,我们会去服务端获取。
        // 'api/permissionService' 是本例子中的 web 服务地址。
 
        $resource('/api/permissionService').get().$promise.then(function (response) {
          // 当服务器返回之后,我们开始填充权限对象
          parentPointer.permissionModel.permission = response;
 
          // 将权限对象处理完成的标记设为 true 并保存在 Session,
          // Session 中的用户,在后续的路由请求中可以重用该权限对象
          parentPointer.permissionModel.isPermissionLoaded = true;
 
          // 检查当前用户是否有必须角色访问该路由
          parentPointer.getPermission(parentPointer.permissionModel, roleCollection, deferred);
        }
        );
      }
      return deferred.promise;
    },
 
    //方法:检查当前用户是否有必须角色访问该路由
    //'permissionModel' 保存了从服务端返回的当前用户的角色信息
    //'roleCollection' 保存了可访问当前路由的角色列表
    //'deferred' 是用来处理承诺的对象
    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) {
        // 如果用户没有必须的权限,我们把用户引导到无权访问页面
        $location.path(routeForUnauthorizedAccess);
        // 由于这个处理会有延时,而这期间页面位置可能发生改变, 
        // 我们会一直监视 $locationChangeSuccess 事件
        // 并且当该事件发生的时,就把掉承诺解决掉。
        $rootScope.$on('$locationChangeSuccess', function (next, current) {
          deferred.resolve();
        });
      } else {
        deferred.resolve();
      }
    }
  };
});

3 加密路由

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

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',
        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]);
          },
        }
      });
  });
Javascript 相关文章推荐
javascript中substr,substring,slice.splice的区别说明
Nov 25 Javascript
Jquery 绑定时间实现代码
May 03 Javascript
setTimeout的延时为0时多个浏览器的区别
May 23 Javascript
Javascript中string转date示例代码
Nov 01 Javascript
JavaScript中遍历对象的property的3种方法介绍
Dec 30 Javascript
jQuery中prevAll()方法用法实例
Jan 08 Javascript
JavaScript数据库TaffyDB用法实例分析
Jul 27 Javascript
微信小程序中input标签详解及简单实例
May 18 Javascript
vue-cli下的vuex的简单Demo图解(实现加1减1操作)
Feb 26 Javascript
详解Chart.js轻量级图表库的使用经验
May 22 Javascript
React性能优化系列之减少props改变的实现方法
Jan 17 Javascript
jQuery轮播图功能制作方法详解
Dec 03 jQuery
浅谈Node.js中的定时器
Jun 18 #Javascript
浅析AngularJS中的生命周期和延迟处理
Jun 18 #Javascript
Node.js事件驱动
Jun 18 #Javascript
详解AngularJS的通信机制
Jun 18 #Javascript
javascript背景时钟实现方法
Jun 18 #Javascript
移动Web中图片自适应的两种JavaScript解决方法
Jun 18 #Javascript
javascript随机显示背景图片的方法
Jun 18 #Javascript
You might like
JS控制显示隐藏兼容问题(IE6、IE7、IE8)
2010/04/01 Javascript
在javascript中实现函数数组的方法
2013/12/25 Javascript
js对象内部访问this修饰的成员函数示例
2014/04/27 Javascript
浅谈JavaScript 框架分类
2014/11/10 Javascript
Javascript 正则表达式实现为数字添加千位分隔符
2015/03/10 Javascript
jQuery实现提交按钮点击后变成正在处理字样并禁止点击的方法
2015/03/24 Javascript
纯HTML5制作围住神经猫游戏-附源码下载
2015/08/23 Javascript
jQuery使用$.ajax进行即时验证实例详解
2015/12/11 Javascript
jquery获取select选中值的方法分析
2015/12/22 Javascript
浏览器检测JS代码(兼容目前各大主流浏览器)
2016/02/21 Javascript
浅析AMD CMD CommonJS规范--javascript模块化加载学习心得总结
2016/03/16 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
2017/01/10 Javascript
从零开始学习Node.js系列教程一:http get和post用法分析
2017/04/13 Javascript
基于vue2实现上拉加载功能
2017/11/28 Javascript
小程序实现列表点赞功能
2018/11/02 Javascript
java实现单链表增删改查的实例代码详解
2019/08/30 Javascript
js实现全选和全不选
2020/07/28 Javascript
在vue项目中封装echarts的步骤
2020/12/25 Vue.js
Python中的装饰器用法详解
2015/01/14 Python
用Python制作检测Linux运行信息的工具的教程
2015/04/01 Python
Ubuntu安装Jupyter Notebook教程
2017/10/18 Python
python 猴子补丁(monkey patch)
2019/06/26 Python
Python Django基础二之URL路由系统
2019/07/18 Python
Python3常见函数range()用法详解
2019/12/30 Python
Python3.7下安装pyqt5的方法步骤(图文)
2020/05/12 Python
最新Python idle下载、安装与使用教程图文详解
2020/11/28 Python
python matplotlib工具栏源码探析三之添加、删除自定义工具项的案例详解
2021/02/25 Python
HTML5 背景的显示区域实现
2020/07/09 HTML / CSS
澳大利亚新奇小玩意网站:Yellow Octopus
2017/12/28 全球购物
斯洛伐克最大的婴儿食品和用品网上商店:Feedo.sk
2020/12/21 全球购物
大学生职业生涯规划书范文
2014/01/14 职场文书
假面舞会策划方案
2014/05/29 职场文书
乡党政领导班子群众路线教育实践活动个人对照检查材料
2014/09/20 职场文书
酒店辞职书范文
2015/02/26 职场文书
2016年大学生社区服务活动总结
2016/04/06 职场文书
励志语录:你若不勇敢,谁替你坚强
2019/11/08 职场文书