Autenticação
A maneira mais comum no design das permissões é o controle de acesso baseado em papéis da RBAC. A idéia básica é que várias permissões para operações do sistema não sejam diretamente concedidas a usuários específicos, mas para estabelecer uma coleta de função entre o conjunto de usuários e o conjunto de permissão. Cada função corresponde a um conjunto correspondente de permissões.
Depois que o usuário tiver atribuído a função apropriada, o usuário possui todas as permissões operacionais para a função. A vantagem disso é que não há necessidade de atribuir permissões sempre que um usuário for criado, basta atribuir a função correspondente do usuário e as alterações de permissão da função são muito menores que as alterações de permissão do usuário, o que simplificará o gerenciamento de permissão do usuário e reduzirá a sobrecarga do sistema.
Em um aplicativo de uma página criada pela Angular, precisamos fazer algumas coisas extras para implementar essa arquitetura. Do ponto de vista geral do projeto, existem cerca de três lugares com os quais os engenheiros de front-end precisam lidar.
1. Processamento da interface do usuário (julgando se algum conteúdo da página é exibido com base nas permissões de propriedade do usuário)
2. Processamento de roteamento (quando o usuário acessa um URL que não tem permissão para acessar, ele salta para uma página com uma mensagem de erro)
3. Processamento de solicitação HTTP (quando enviamos uma solicitação de dados, se o status retornado for 401 ou 403, geralmente será redirecionado para uma página com uma mensagem de erro)
Implementação do controle de identidade de acesso
Primeiro, você precisa obter todas as permissões do usuário atual antes do início do Angular e, em seguida, a maneira mais elegante é armazenar esse relacionamento de mapeamento por meio de um serviço. Para se o conteúdo em uma página é exibido de acordo com as permissões pela interface do usuário. Depois de processá -los, precisamos adicionar um atributo adicional de "permissão" para adicionar uma rota ao adicionar uma rota e atribuir um valor para indicar quais funções com permissões podem pular para este URL e, em seguida, ouvir o evento RouteChanGestart através do Angular para verificar se o usuário atual tem acesso a este URL. Finalmente, é necessário um interceptador HTTP para monitorar quando o status retornado por uma solicitação for 401 ou 403, pule para a página para uma página de prompt de erro. Aproximadamente é isso que é, parece um pouco demais, mas é realmente muito fácil de lidar.
Retorne 401, execute loginctrl, retornar 403, executar permissãoctrl.
Obtenha a relação de mapeamento da permissão antes das corridas angulares
O projeto angular é iniciado através do NG-APP, mas em alguns casos esperamos que o projeto angular esteja sob nosso controle. Por exemplo, nesse caso, espero obter todos os relacionamentos de mapeamento de permissão do usuário atualmente conectado e iniciar o aplicativo Angular. Felizmente, o próprio Angular fornece esse método, isto é, angular.Pootstrap ().
VAR PermissionList; angular.Element (document) .ready (function () {$ .get ('/api/userPermission', function (data) {permissionList = data; angular.bootstrap (document, ['app']);});});Aqueles que lêem cuidadosamente podem perceber que o uso de $ .get () é usado aqui e não há erro usando o jQuery em vez do recurso $ do Angular ou $ http, porque neste momento, o Angular ainda não começou e não podemos usar sua função.
Use ainda mais o código acima para colocar o relacionamento de mapeamento obtido em um serviço como uma variável global.
// app.js var app = angular.module ('myApp', []), PermissionList; App.run (function (permissões) {permissions.setPermissions (PermissionList)}); angular.Element (document) .ready (function () {$ .get ('/api/userPermission', function (data) {permissionList = data; angular.bootstrap (document, ['app']);});}); // Common_service.js angular.module ('MyApp') .Factory ('Permissões', função ($ RootsCope) {var PermissionList; return {SetPermissions: function (Permissões) {permissionList = permissões; $ Roots.Depois de obter o conjunto de permissões do usuário atual, arquivamos esse conjunto no serviço correspondente e depois fizemos mais 2 coisas:
(1) Armazene as permissões em variáveis de fábrica para que estejam sempre na memória, percebendo o papel das variáveis globais, mas não poluindo o espaço para nome.
(2) Evento de transmissão por meio de $ Broadcast, quando as permissões mudarem.
1. Como determinar o poder visível e oculto do componente da interface do usuário com base em permissões
Aqui, precisamos escrever uma diretiva, que exibirá ou ocultará elementos com base nos relacionamentos de permissão.
<!-Se o usuário tiver permissão editar o show um link-> <div has-permission = 'edit'> <a href = "/#/courses/{{id}}/edit"> {{name}}} "</a> </dit> <!-se o usuário não tiver editar a permissão de edição somente (nota}}"! has-permission = '! Edit'> {{name}} </div>Aqui, vejo uma situação ideal que você pode passar no nome da permissão de verificação de propriedades de permissão e, se o usuário atual o tiver, ele será exibido e, se não houver, será oculto.
angular.module ('myApp'). Diretiva ('haspermission', function (permissões) {return {link: function (scope, elemento, atts) {if (! _. isstring (atts.haspermission)) lança "haspermission valor deve ser um string"; var value = attrs.haspermission.Trim (); Notpermissionflag) {value = Value.slice (1) .Trim (); ToggleVisableBasedonPermission ();Expanda a fábrica anterior:
Angular.Module ('MyApp') .Factory ('Permissões', função ($ RootScope) {var PermissionList; return {SetPerMissions: function (Permissões) {PermissionList = Permissões; $ RootsCope. $ transmitido ('Permissões'); _.2. Acesso baseado em permissão na rota
A idéia desta parte da implementação é a seguinte: Quando definimos uma rota, adicionamos um atributo de permissão e o valor do atributo é quais permissões temos para acessar o URL atual. Em seguida, continuamos ouvindo as mudanças de URL durante o evento RouteChanGestart. Cada vez que alteramos o URL, verifique se o URL a ser redirecionado atende às condições e, em seguida, decida se será redirecionado com sucesso ou para a página prompt de erro.
App.config (function ($ routeProvider) {$ routeProvider .when ('/', {templateurl: 'Views/viewCourses.html', controlador: 'ViewCourSesctrl'}) .when ('unauthorized', {modplateurl: 'views/error.htmmml (' unauthorized ', {modplateurl:' views/error.htmmmmml ('/unauthorized', {modelurl: 'views/error.htmmml (' .When ('/Cursos/: id/edit', {templateurl: 'Views/editCourses.html', controlador: 'editCours', permissão: 'edit'});MainController.js ou indexController.js (em resumo, é o controlador de camada pai)
App.Controller ('MainAppCtrl', função ($ escopo, $ localização, permissões) {$ scope. $ on ('$ routechangestart', função (escopo, próximo, atual) {var permissão = a próxima. });A hassais escrita antes ainda é usada aqui, e essas coisas são altamente reutilizáveis. Isso é feito. Antes de cada pular de rota de visualização, apenas julgue se tem permissão para pular no controlador do contêiner pai.
3. Processamento de solicitação HTTP
Isso deve ser relativamente fácil de lidar, e a ideia é muito simples. Como as aplicações angulares recomendam desculpas de estilo RESTful, o uso do protocolo HTTP é muito claro. Se o código de status retornado pela solicitação for 401 ou 403, significa que não há permissão, para que você possa simplesmente pular para a página de prompt de erro correspondente.
Obviamente, não podemos verificar e encaminhar manualmente cada solicitação uma vez, por isso devemos definitivamente precisar de um filtro total. O código é o seguinte:
Angular.module ('myApp') .config (function ($ httpprovider) {$ httpprovider.ResponseInterceptores.push ('securityInterceptor');}) .Provider ('securionIntercetor', function () {this. if (Response.Status === 403 ||Ao escrever isso, você quase pode perceber o gerenciamento de permissão e o controle da parte front-end neste modo de separação front-end.
Verificação de formulário
Diretiva de verificação de front-end AngularJS
var rcSubmitDirection = {'rcsubMit': function ($ parse) {return {restrtrin: "a", requer: ["rcsubMit", "? form"], controlador: function () {this.attempt = false; var formController = null; this.setAtTattEd = function () {this.AttemptEd = true; }; this.setFormController = function (controlador) {formcontroller = controlador; }; this.needsattion = function (fieldmodelController) {if (! formcontroller) return false; if (fieldmodelController) {return fieldmodelcontroller. $ inválido && (fieldmodelcontroller. $ Dirty || this.attempt); } else {return formcontroller && formcontroller. $ inválido && (formcontroller. }}; }, compilação: function () {return {pre: function (escopo, formElement, atributos, controladores) {var submitController = controladores [0]; var formController = controladores.Length> 1? Controladores [1]: nulo; submitController.SetFormController (FormController); scope.rc = scope.rc || {}; scope.rc [attributes.name] = submitController; }, post: function (escopo, formseLement, atributos, controladores) {var submitController = controladores [0]; var formController = controladores.Length> 1? Controladores [1]: nulo; var fn = $ parse (atributes.rcsubmit); formElement.bind ("submeter", function (event) {submitController.SetAttEmted (); if (! scope. $$ fase) scope. $ Aplicar (); if (! formcontroller. $ válido) return; scope. $ Aplicar (function () {fn (scope, {$ event: event:});});}); }}; }}; }}; }}; }}; }}; }}; }}; }};Verificação passada
<forma name = "loginform" ng-app = "LoginApp" ng-controller = "Logincontroller" rc-submit = "login ()"> <div ng-class = "{'has-error': rc.loginform.needsattion (loginform.USername)" espaço reservado = "nome de usuário" necessário ng-model = "session.UserName"/> <span ng-show = "rc.form.needsattion (loginform.username) && loginform.username. rc.loginform.needsattion (loginform.password)} "> <input name =" senha "type =" senha "spromeholder =" senha "necessária ng-model =" session.password "/> <span ng-show =" rc.form.needsattion (loginform.password) && Login.pass.pass.pass. type = "submeter" value = "login"> <pan> login </span> </butut> </div> </morm>O estilo é o seguinte
Login () será chamado após a verificação do front-end passar.