angular.module('myApp') .factory('permissions', function ($rootScope) { var permissionList; return { setPermissions: function(permissions) { permissionList = permissions; $rootScope.$broadcast('permissionsChanged') }, hasPermission: function (permission) { permission = permission.trim(); return _.some(permissionList, function(item) { if(_.isString(item.Name)) return item.Name.trim() === permission }); } }; });
2.路由上的依权限访问
这一部分的实现的思路是这样: 当我们定义一个路由的时候增加一个permission的属性,属性的值就是有哪些权限才能访问当前url.然后通过routeChangeStart事 件一直监听url变化.每次变化url的时候,去校验当前要跳转的url是否符合条件,然后决定是跳转成功还是跳转到错误的提示页面.
app.config(function ($routeProvider) { $routeProvider .when('https://www.jb51.net/', { templateUrl: 'views/viewCourses.html', controller: 'viewCoursesCtrl' }) .when('/unauthorized', { templateUrl: 'views/error.html', controller: 'ErrorCtrl' }) .when('/courses/:id/edit', { templateUrl: 'views/editCourses.html', controller: 'editCourses', permission: 'Edit' }); });
mainController.js 或者 indexController.js (总之是父层Controller)
app.controller('mainAppCtrl', function($scope, $location, permissions) { $scope.$on('$routeChangeStart', function(scope, next, current) { var permission = next.$$route.permission; if(_.isString(permission) && !permissions.hasPermission(permission)) $location.path('/unauthorized'); }); });
这里依然用到了之前写的hasPermission,这些东西都是高度可复用的.这样就搞定了,在每次view的route跳转前,在父容器的Controller中判断一些它到底有没有跳转的权限即可.
3.HTTP请求处理
这个应该相对来说好处理一点,思想的思路也很简单.因为Angular应用推荐的是RESTful风格的借口,所以对于HTTP协议的使用很清晰.对于请求返回的status code如果是401或者403则表示没有权限,就跳转到对应的错误提示页面即可.
当然我们不可能每个请求都去手动校验转发一次,所以肯定需要一个总的filter.代码如下:
angular.module('myApp') .config(function($httpProvider) { $httpProvider.responseInterceptors.push('securityInterceptor'); }) .provider('securityInterceptor', function() { this.$get = function($location, $q) { return function(promise) { return promise.then(null, function(response) { if(response.status === 403 || response.status === 401) { $location.path('/unauthorized'); } return $q.reject(response); }); }; }; });
写到这里就差不多可以实现在这种前后端分离模式下,前端部分的权限管理和控制了。
表单验证
AngularJS 前端验证指令
var rcSubmitDirective = { 'rcSubmit': function ($parse) { return { restrict: "A", require: [ "rcSubmit", "?form" ], controller: function() { this.attempted = false; var formController = null; this.setAttempted = function() { this.attempted = true; }; this.setFormController = function(controller) { formController = controller; }; this.needsAttention = function(fieldModelController) { if (!formController) return false; if (fieldModelController) { return fieldModelController.$invalid && (fieldModelController.$dirty || this.attempted); } else { return formController && formController.$invalid && (formController.$dirty || this.attempted); } }; }, compile: function() { return { pre: function(scope, formElement, attributes, controllers) { var submitController = controllers[0]; var formController = controllers.length > 1 ? controllers[1] : null; submitController.setFormController(formController); scope.rc = scope.rc || {}; scope.rc[attributes.name] = submitController; }, post: function(scope, formElement, attributes, controllers) { var submitController = controllers[0]; var formController = controllers.length > 1 ? controllers[1] : null; var fn = $parse(attributes.rcSubmit); formElement.bind("submit", function(event) { submitController.setAttempted(); if (!scope.$$phase) scope.$apply(); if (!formController.$valid) return; scope.$apply(function() { fn(scope, { $event: event }); }); }); } }; } }; } };
验证通过