Аутентификация
Наиболее распространенным способом в разработке разрешений является контроль доступа RBAC на основе ролей. Основная идея состоит в том, что различные разрешения для системных операций напрямую предоставляются не конкретным пользователям, а скорее для создания сбора ролей между набором пользователя и набором разрешений. Каждая роль соответствует соответствующему набору разрешений.
После того, как пользователю будет назначена соответствующая роль, пользователь имеет все разрешения на работу для этой роли. Преимущество этого заключается в том, что нет необходимости назначать разрешения каждый раз, когда создается пользователь, просто назначайте соответствующую роль пользователя, а изменения разрешения роли намного меньше, чем изменения в изменениях разрешения пользователя, что упростит управление разрешениями пользователя и уменьшит системные накладные расходы.
В одностраничном приложении, созданном Angular, нам нужно сделать несколько дополнительных вещей для реализации такой архитектуры. С общей точки зрения проекта, есть около 3 мест, с которыми должны иметь дело фронт-инженеры.
1. Обработка пользовательского интерфейса (оценивая, отображается ли какой -то контент на странице на основе разрешений, принадлежащих пользователю)
2. Обработка маршрутизации (когда пользователь обращается к URL -адресу, что у него нет разрешения на доступ, она прыгает на страницу с сообщением об ошибке)
3. Обработка HTTP -запроса (когда мы отправляем запрос данных, если возвращенный статус составляет 401 или 403, он обычно перенаправляется на страницу с сообщением об ошибке)
Реализация управления идентификацией доступа
Во -первых, вам необходимо получить все разрешения текущего пользователя до начала угла, и тогда более элегантным способом является хранение этих отношений сопоставления через сервис. Для того, отображается ли контент на странице в соответствии с разрешениями пользовательского интерфейса. После обработки их, нам необходимо добавить дополнительный атрибут «разрешения», чтобы добавить маршрут при добавлении маршрута, и назначить ему значение, чтобы указать, какие роли с разрешениями могут перейти к этому URL, а затем прослушать событие Routechangestart через Angular, чтобы проверить, имеет ли текущий пользователь доступ к этому URL. Наконец, для контроля необходимо контролировать перехватчик HTTP, когда статус, возвращаемый запросом, составляет 401 или 403, перейдите на страницу на страницу «Подсказка ошибки». Примерно это то, что есть, это кажется слишком многими, но на самом деле с этим очень легко иметь дело.
Return 401, выполнить loginctrl, return 403, выполнить разрешение.
Получите отношение картирования разрешения перед угловыми пробежками
Угловой проект начинается через NG-APP, но в некоторых случаях мы надеемся, что Angular Project будет под нашим контролем. Например, в этом случае я надеюсь получить все отношения со картинами разрешений в настоящее время, зарегистрированное в пользователе, а затем запустить Angular App. К счастью, сама угловалась, что обеспечивает этот метод, то есть Angular.bootstrap ().
var rescissionList; Angular.Element (Document) .ready (function () {$ .get ('/api/userpermission', function (data) {resmissionList = data; angular.bootstrap (документ, ['app']);});});Те, кто внимательно читает, могут заметить, что использование $ .get () используется здесь, и нет ошибки, используя jQuery вместо ресурса $ algular или $ http, потому что в настоящее время Angular еще не начался, и мы не можем использовать ее функцию.
Далее использовать приведенный выше код, чтобы поместить полученные отношения отображения в сервис в качестве глобальной переменной.
// app.js var app = angular.module ('myApp', []), rescissionList; app.run (function (permissions) {permissions.setpermissions (rescissionList)}); Angular.Element (Document) .ready (function () {$ .get ('/api/userpermission', function (data) {resmissionList = data; angular.bootstrap (документ, ['app']);});}); // common_service.js angular.module ('myApp') .factory ('performions', function ($ ourtscope) {var rescisionlist; return {setpermissions: function (permissions) {rescissionList = resmissions; $ ourtscope. $ broadcast ('resmissionsched')};};});После получения набора разрешений нынешнего пользователя мы архивируем этот набор в соответствующую службу, а затем сделали еще 2 вещи:
(1) хранить разрешения в заводских переменных, чтобы они всегда находились в памяти, осознавая роль глобальных переменных, но не загрязняя пространство имен.
(2) Трансляционное событие через $ Broadcast, при изменении разрешений.
1. Как определить видимую и скрытую мощность компонента пользовательского интерфейса на основе разрешений
Здесь нам нужно написать директиву сами, которая будет отображать или скрывать элементы на основе отношений с разрешением.
<!-Если пользователь имеет разрешение на редактирование Show a Link-> <div has has-permission = 'edit'> <a href = "/#/courses/{{id}}/edit"> {{name}} </a> </div> <! has-permission = '! edit'> {{name}} </div>Здесь я вижу идеальную ситуацию, в которой вы можете передать имя разрешения на свойство HAS-выполнения, и если текущий пользователь имеет его, оно будет отображаться, и если нет, оно будет скрыто.
Angular.Module ('myApp'). Directive ('haspermission', function (permissions) {return {link: function (scope, element, attrs) {if (! _. Isstring (attrs.haspermission)) throw "haspermission value должна быть строкой"; var value = attrs.haspermission.trim (); if (notpermissionflag) {value = value.slice (1) .trim (); TogglevissionBasedOnpermission ();Расширить предыдущую фабрику:
Angular.Module ('myApp') .Factory ('разрешения', функция ($ rootscope) {var resmissionList; return {setPermissions: function (разрешения) {разрешение stust = resmissions; $ rootscope. $ broadcast ('resmissionschanged')}, haspermission: function (permission = versission.mismed ')}, haspermission: function (permission upermis. function (item) {if (_. Isstring (item.name)) return item.name.trim () ===2. Доступ на основе разрешений по маршруту
Идея этой части реализации заключается в следующем: когда мы определяем маршрут, мы добавляем атрибут разрешения, и значение атрибута - это то, какие разрешения мы должны получить доступ к текущему URL. Затем мы продолжаем слушать изменения URL -адреса через событие Routechangestart. Каждый раз, когда мы меняем URL -адрес, проверяем, соответствует ли URL -образованию, соответствует условиям, а затем решаем, будет ли он перенаправлен успешно или на страницу с помощью ошибки.
app.config (function ($ routeprovider) {$ routeprovider .when ('/', {templateurl: 'views/viewcourses.html', controller: 'viewcoursesctrl'}). . When ('/courses/: id/edit', {templateurl: 'views/editcourses.html', контроллер: 'editcourses', разрешение: 'edit'});maincontroller.js или indexcontroller.js (вкратце, это родительский контроллер слоя)
app.controller ('mainappctrl', function ($ scope, $ location, разрешения) {$ scope. $ on ('$ routechangestart', function (сфера, следующий, текущий) {var ormission = next. $$ route.permission; if (_. Issstring (разрешение) &&! });Хэспермиссия, написанная ранее, все еще используется здесь, и эти вещи очень используются. Это сделано. Перед каждым прыжком с маршрутом просмотра просто судите, есть ли у него разрешение прыгать в контроллере родительского контейнера.
3. HTTP -обработка запросов
С этим должно быть относительно легко иметь дело, и идея очень проста. Поскольку угловые приложения рекомендуют оправдания в стиле RESTFUL, использование протокола HTTP очень ясно. Если код состояния, возвращаемый запросом, составляет 401 или 403, это означает, что разрешения нет, поэтому вы можете просто перейти на соответствующую страницу запроса ошибки.
Конечно, мы не можем вручную проверить и пересылать каждый запрос один раз, поэтому нам определенно нужен полный фильтр. Код заключается в следующем:
Angular.Module ('myApp') .config (function ($ httpprovider) {$ httpprovider.responseInterceptors.push ('securityInterceptor');}) .provider ('SecurityInterceptor', function () {this. $ function ($ location, $ q). if (response.status === 403 ||Написав это, вы можете почти реализовать управление разрешениями и контроль передней части в этом режиме разделения передней части.
Проверка формы
Angularjs Front-End Verification Directive
var rcsubmitdirective = {'rcsubmit': function ($ parse) {return {ограничить: "a", reft: ["rcsubmit", "? form"], controller: function () {this.attempted = false; var formcontroller = null; this.setattempted = function () {this.attempted = true; }; this.setformcontroller = function (controller) {formController = controller; }; this.needsattionlination = function (FieldModelController) {if (! formController) вернуть false; if (FieldModelController) {return FieldModelController. $ Invalid && (FieldModelController. $ Dirty || this.atempted); } else {return formController && formController. $ Invalid && (formController. $ Dirty || this.atempted); }}; }, compile: function () {return {pre: function (scope, formElement, attributes, controllers) {var opportcontroller = controllers [0]; var formcontroller = controllers.length> 1? контроллеры [1]: null; OpportController.SetFormController (FormController); scope.rc = scope.rc || {}; scope.rc [attributes.name] = отправить Controller; }, post: function (racope, formElement, attributes, controllers) {var opportcontroller = controllers [0]; var formcontroller = controllers.length> 1? контроллеры [1]: null; var fn = $ parse (attributes.rcsubmit); formelement.bind ("отправить", function (event) {oppercontroller.setAttempted (); if (! scope. $$ phase) scope. $ Apply (); if (! formController. $ valid) return; scope. $ Apply (function () {fn (scope, $ event: event});});}); }}; }}; }}; }}; }}; }}; }}; }}; }};Проверка прошла
<form name = "loginform" novalidate ng-app = "loginapp" ng-controller = "logincontroller" rc-submit = "login ()"> <div ng-class = "{'has-error': rc.loginform.needsatture (loginform.userme). ng-model = "session.username"/> <span ng-shef = "rc.form.needsattionlention (loginform.username) && loginform.username. $ error.required"> reding </span> </div> <div ng-class = "{'has-error': rc.loginform.needsattent type = "Пароль" Placeholder = "пароль" требуется ng-model = "session.password"/> <span ng-shef = "rc.form.needsattunition (loginform.password) && loginform.password. $ error.required"> требуется </span> </div> <div> <tood> type = "varuice =" valuin> <pran> </span> </div> <div> <tood> <//login </span> </span> </div> <div> <futton> </value = "> <pran> </span> </div> <div> <futton> <//кнопСтиль следующим образом
Login () будет вызвана после проходов проверки переднего дня.