使用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编程起步(第四课)
Feb 27 Javascript
javascript preload&lazy load
May 13 Javascript
js中获取事件对象的方法小结
Mar 13 Javascript
jQuery 常见操作实现方式和常用函数方法总结
May 06 Javascript
常用jQuery选择器总结
Jul 11 Javascript
AngularJS入门心得之directive和controller通信过程
Jan 25 Javascript
JavaScript数组合并的多种方法
May 22 Javascript
js图片上传前预览功能(兼容所有浏览器)
Aug 24 Javascript
javascript入门之window对象【新手必看】
Nov 22 Javascript
解决Vue页面固定滚动位置的处理办法
Jul 13 Javascript
jQuery实现的图片点击放大缩小功能案例
Jan 02 jQuery
Typescript3.9 常用新特性一览(推荐)
May 14 Javascript
浅谈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
phpmail类发送邮件函数代码
2012/02/20 PHP
php表单加入Token防止重复提交的方法分析
2016/10/10 PHP
PHP中遍历数组的三种常用方法实例分析
2019/06/24 PHP
如何在PHP中生成随机数
2020/06/04 PHP
javascript获得CheckBoxList选中的数量
2009/10/27 Javascript
javascript 面向对象全新理练之数据的封装
2009/12/03 Javascript
jquery 插件开发备注
2010/08/27 Javascript
Javasipt:操作radio标签详解
2013/12/30 Javascript
jquery库或JS文件在eclipse下报错问题解决方法
2014/04/17 Javascript
node.js中的fs.readSync方法使用说明
2014/12/17 Javascript
JavaScript中的操作符==与===介绍
2014/12/31 Javascript
可以浮动某个物体的jquery控件用法实例
2015/07/24 Javascript
jquery实现鼠标点击后展开列表内容的导航栏效果
2015/09/14 Javascript
JQuery遍历元素的父辈和祖先的方法
2016/09/18 Javascript
详解JS异步加载的三种方式
2017/03/07 Javascript
关于Angular2 + node接口调试的解决方案
2017/05/28 Javascript
Three.js中矩阵和向量的使用教程
2019/03/19 Javascript
Angular+Ionic使用queryParams实现跳转页传值的方法
2020/09/05 Javascript
vue穿梭框实现上下移动
2021/01/29 Vue.js
讲解Python中for循环下的索引变量的作用域
2015/04/15 Python
python3序列化与反序列化用法实例
2015/05/26 Python
python实现爬虫统计学校BBS男女比例之数据处理(三)
2015/12/31 Python
python使用matplotlib画饼状图
2018/09/25 Python
Python3操作读写CSV文件使用包过程解析
2020/04/10 Python
使用Python三角函数公式计算三角形的夹角案例
2020/04/15 Python
python 通过exifread读取照片信息
2020/12/24 Python
网页布局中CSS样式无效的十个重要原因详解
2017/08/10 HTML / CSS
日本土著品牌,综合型购物网站:Cecile
2016/08/23 全球购物
Under Armour安德玛荷兰官网:美国高端运动科技品牌
2019/07/10 全球购物
linux面试题参考答案(9)
2015/01/07 面试题
25岁生日感言
2014/01/13 职场文书
简单的辞职信范文
2014/01/18 职场文书
干部鉴定材料
2014/05/18 职场文书
中学生运动会通讯稿大全
2014/09/18 职场文书
2014年卫生院工作总结
2014/12/03 职场文书
MySQL数据库实验之 触发器和存储过程
2022/06/21 MySQL