소개
AngularJS는 등장 이후 오랫동안 사용되어 왔습니다. 단일 페이지 애플리케이션(SPA) 개발을 위한 자바스크립트 프레임워크입니다. 양방향 바인딩, 지시문 등과 같은 몇 가지 멋진 기능이 있습니다. 이 기사에서는 주로 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]); }, } }); });