Welcome 微信登录

首页 / 脚本样式 / JavaScript / 使用AngularJS对路由进行安全性处理的方法

 简介
自从出现以后,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]);},}});});