使用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 相关文章推荐
jQuery AJAX回调函数this指向问题
Feb 08 Javascript
Javascript 实现的数独解题算法网页实例
Oct 15 Javascript
jQuery中odd选择器的定义和用法
Dec 23 Javascript
运行Node.js的IIS扩展iisnode安装配置笔记
Mar 02 Javascript
js控制页面的全屏展示和退出全屏显示的方法
Mar 10 Javascript
Websocket协议详解及简单实例代码
Dec 12 Javascript
[js高手之路]从原型链开始图解继承到组合继承的产生详解
Aug 28 Javascript
js Dom实现换肤效果
Oct 21 Javascript
jQuery实现的鼠标响应缓冲动画效果示例
Feb 13 jQuery
vue实现城市列表选择功能
Jul 16 Javascript
微信小程序实现跑马灯效果
Oct 21 Javascript
JS实现轮播图效果
Jan 11 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
PHP中simplexml_load_string函数使用说明
2011/01/01 PHP
在项目中寻找代码的坏命名
2012/07/14 PHP
md5 16位二进制与32位字符串相互转换示例
2013/12/30 PHP
php实现cc攻击防御和防止快速刷新页面示例
2014/02/13 PHP
PHP 配置后台登录以及模板引入
2017/01/24 PHP
php判断某个方法是否存在函数function_exists (),method_exists()与is_callable()区别与用法解析
2020/04/20 PHP
jQuery中与toggleClass等价的程序段 以及未来学习的方向
2010/03/18 Javascript
解析js原生方法创建表格效率测试
2013/07/08 Javascript
利用CSS、JavaScript及Ajax实现高效的图片预加载
2013/10/16 Javascript
jQuery+CSS实现一个侧滑导航菜单代码
2016/05/09 Javascript
20分钟打造属于你的Bootstrap站点
2016/07/27 Javascript
js实现的页面加载完毕之前loading提示效果完整示例【附demo源码下载】
2016/08/02 Javascript
JS中获取 DOM 元素的绝对位置实例详解
2018/04/23 Javascript
nodejs中各种加密算法的实现详解
2019/07/11 NodeJs
在Vue项目中使用Typescript的实现
2019/12/19 Javascript
js实现上下左右键盘控制div移动
2020/01/16 Javascript
使用wxPython获取系统剪贴板中的数据的教程
2015/05/06 Python
将Python代码打包为jar软件的简单方法
2015/08/04 Python
python实现FTP服务器服务的方法
2017/04/11 Python
Python使用QRCode模块生成二维码实例详解
2017/06/14 Python
python中安装Scrapy模块依赖包汇总
2017/07/02 Python
Python矩阵常见运算操作实例总结
2017/09/29 Python
python如何修改装饰器中参数
2018/03/20 Python
详解一种用django_cache实现分布式锁的方式
2019/09/01 Python
TensorFlow设置日志级别的几种方式小结
2020/02/04 Python
怎样让char类型的东西转换成int类型
2013/12/09 面试题
优秀班集体获奖感言
2014/02/03 职场文书
幼儿园教师工作感言
2014/02/15 职场文书
五好家庭申报材料
2014/12/20 职场文书
庆六一开幕词
2015/01/29 职场文书
浅谈Python项目的服务器部署
2021/04/25 Python
用Python爬取某乎手机APP数据
2021/06/15 Python
自从在 IDEA 中用了热部署神器 JRebel 之后,开发效率提升了 10(真棒)
2021/06/26 Java/Android
详细介绍MySQL中limit和offset的用法
2022/05/06 MySQL
Java实现添加条码或二维码到Word文档
2022/06/01 Java/Android
windows server 2016 域环境搭建的方法步骤(图文)
2022/06/25 Servers