認証
権限の設計における最も一般的な方法は、RBACのロールベースのアクセス制御です。基本的なアイデアは、システム操作のさまざまな許可が特定のユーザーに直接許可されるのではなく、ユーザーセットと許可セットの間にロールコレクションを確立するために付与されるということです。各役割は、対応する許可セットに対応します。
ユーザーに適切な役割が割り当てられたら、ユーザーはその役割のすべての運用権限を持っています。これの利点は、ユーザーが作成されるたびにアクセス許可を割り当てる必要がないこと、ユーザーの対応する役割を割り当てるだけであり、ロールの許可変更の変更はユーザーの許可変更の変更よりもはるかに少ないことです。
Angularによって構築された単一ページのアプリケーションでは、そのようなアーキテクチャを実装するためにいくつかの追加のことをする必要があります。プロジェクト全体の観点からは、フロントエンジニアが対処する必要がある約3つの場所があります。
1。UI処理(ページ上の一部のコンテンツがユーザーが所有する権限に基づいて表示されるかどうかを判断)
2。ルーティング処理(ユーザーがアクセスする許可がないというURLにアクセスすると、エラーメッセージでページにジャンプします)
3。HTTPリクエスト処理(データ要求を送信するとき、返されたステータスが401または403の場合、通常、エラーメッセージが付いたページにリダイレクトされます)
アクセスIDコントロールの実装
まず、Angularが開始する前に現在のユーザーのすべての権限を取得する必要があります。次に、このマッピング関係をサービスで保存することです。ページ上のコンテンツがUIの権限に従って表示されるかどうか。これらを処理した後、ルートを追加するときにルートを追加するために追加の「許可」属性を追加し、許可を持つ役割をこのURLにジャンプできる値を示す値を割り当て、Angularを介してRegeChangestartイベントを聞いて、現在のユーザーがこのURLにアクセスできるかどうかを確認します。最後に、リクエストによって返されるステータスが401または403の場合に監視するには、HTTPインターセプターが必要です。エラープロンプトページにページにジャンプします。大まかにこれがそれが何であるか、それは少し多すぎるように見えますが、実際には非常に簡単に対処できます。
return 401、execute loginctrl、return 403、execute permissionctrl。
Angularが実行される前に、許可のマッピング関係を取得します
Angular ProjectはNG-APPを通じて開始されますが、場合によってはAngularプロジェクトが私たちの管理下にあることを願っています。たとえば、この場合、現在ログインしているユーザーの関係をすべての許可マッピング関係を取得してから、Angularアプリを開始したいと考えています。幸いなことに、Angular自体はこの方法、つまりAngular.bootstrap()を提供します。
var permissionList; angular.element(document).ready(function(){$ .get( '/api/userpermission'、function(data){perminderlist = data; angular.bootstrap(document、['app']);});});慎重に読む人は、$ .get()の使用がここで使用されていることに気付くかもしれません。また、Angularの$リソースまたは$ httpの代わりにjQueryを使用するエラーはありません。この時点でAngularはまだ開始しておらず、その機能を使用できません。
さらに、上記のコードを使用して、取得したマッピング関係をグローバル変数としてサービスに配置します。
// app.js var app = angular.module( 'myApp'、[])、permissionList; app.run(function(permissions){permissions.setpermissions(perminderlist)}); angular.element(document).ready(function(){$ .get( '/api/userpermission'、function(data){perminderlist = data; angular.bootstrap(document、['app']);});}); // common_service.js angular.module( 'myApp').factory( 'permissions'、function($ rotscope){var permissionlist; return {setpermissions:functions(permissions){permissionlist = permissions; $ rotscope。$ broadcast( 'permissions')}};};現在のユーザーの権限セットを取得した後、このセットを対応するサービスにアーカイブしてから、さらに2つのことを行いました。
(1)工場変数に許可を保存して、それらが常にメモリにあるように、グローバル変数の役割を実現しますが、名前空間を汚染しません。
(2)許可が変更された場合、$ブロードキャストを通じて放送イベント。
1.権限に基づいてUIコンポーネントの可視性と隠されたパワーを決定する方法
ここでは、許可関係に基づいて要素を表示または非表示にするディレクティブを自分で作成する必要があります。
<! - ユーザーが編集許可を編集している場合、リンクを編集します - > <div has-permission = 'edit'> <a href = "/#/courses/{{id}}/edit"> {{name}} </a> </div> <! - ユーザーが編集していない場合、テキストを編集していない{{name}} </div>ここでは、Has-Permissionプロパティ検証許可名を渡すことができる理想的な状況を見ています。現在のユーザーがそれを持っている場合、それは表示されます。
angular.module( 'myApp')。ディレクティブ( 'haspermission'、function(permissions){return {link(scope、element、attrs){if(!_。isstring(attrs.haspermission))スロー{value.slice(1).trim(); scope。以前の工場を拡張します:
angular.module( 'myApp').Factory( 'Permissions'、function($ rotscope){var permissionlist; return {setPermissions:function(permissions){perminderlist = rootscope; $ broadcast( 'permissionsChanged')}、haspermission:perismiss(permission( 'permissionschanged')} {perismiss( 'permissionschanged')}; _。2。ルート上の許可ベースのアクセス
実装のこの部分のアイデアは次のとおりです。ルートを定義する場合、許可属性を追加します。属性の値は、現在のURLにアクセスするためのアクセス許可です。次に、RegeChangestartイベントを通じてURLの変更を聴き続けます。 URLを変更するたびに、リダイレクトされるURLが条件を満たしているかどうかを確認し、それが正常にリダイレクトされるか、エラープロンプトページに合わせるかを決定します。
app.config(function($ routeprovider){$ routeprovider .when( '/'、{templateurl: 'views/viewcourses.html'、コントローラー: 'ViewCoursesctrl'})。 .when( '/courses/:id/edit'、{templateurl: 'views/editcourses.html'、コントローラー: 'editcourses'、許可: 'edit'});MainController.jsまたはindexController.js(要するに、それは親レイヤーコントローラーです)
app.Controller( 'mainAppctrl'、function($ scope、$ location、permissions){$ scope。$ on( '$ routechangestart'、function(scope、next、current){var permission = next。$$ルート。 });以前に書かれたHasPermissionはまだここで使用されており、これらのことは非常に再利用可能です。これは行われます。各ビュールートジャンプの前に、親コンテナのコントローラーにジャンプする許可があるかどうかを判断してください。
3。HTTP要求処理
これは比較的簡単に対処できるはずであり、アイデアは非常に簡単です。 AngularアプリケーションはRestful Styleの言い訳を推奨するため、HTTPプロトコルの使用は非常に明確です。リクエストによって返されるステータスコードが401または403の場合、許可がないことを意味するため、対応するエラープロンプトページにジャンプすることができます。
もちろん、各リクエストを手動で検証して1回転送することはできないため、間違いなく完全なフィルターが必要です。コードは次のとおりです。
angular.module( 'myApp').config(function($ httpprovider){$ httpprovider.responseInterceptors.push( 'securityinterceptor');}).provider '(' security interceptor '、function(){this。 if(status ====== 401){'/unauthorized')これを書くことで、このフロントエンド分離モードのフロントエンドパーツの許可管理と制御をほぼ実現できます。
フォーム検証
AngularJSフロントエンド検証指令
var rcsubmitdirective = {'rcsubmit':function($ parse){return {restrict: "a"、require:["rcsubmit"、 "?form"]、controller:function(){this.attemped = fals; 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、astributes、controllers){var submitcontroller = controllers [0]; var formcontroller = controllers.length> 1?コントローラー[1]:null; submitcontroller.setformController(formcontroller); scope.rc = scope.rc || {}; scope.rc [attributes.name] = submitcontroller; }、post:function(scope、formelement、属性、コントローラー){var submitcontroller = controllers [0]; var formcontroller = controllers.length> 1?コントローラー[1]:null; var fn = $ parse(astributes.rcsubmit); formelement.bind( "submit"、function(event){submit controller.setattemped(); if(!scope。$$ phase)scope。$ apply(); if(!formcontroller。$ valid)return; scope。 }}; }}; }}; }}; }}; }}; }}; }}; }};検証が合格しました
<form name = "loginform" novalidate ng-app = "loginapp" ng-controller = "logincontroller" rc-submit = "login()"> <div ng-class = "{'has-error':rc.loginform.needsattention(loginform.username)}" "uesername" "> <入力=" username ""> <入力= "u.ername"タイプ " ng-model = "session.username"/> <span ng-show = "rc.form.needsattention(loginform.username)&& loginform.username。$ error.required"> div> <div ng-class = "{'has-error':rc.loginform.loginsattention(<input.lignform.pass name = "password" type = "password" placeholder = "password"必須ng-model = "session.password"/> <span ng-show = "rc.form.needsattention(loginform.password)&& login.password.password。 </div> </form>スタイルは次のとおりです
ログイン()は、フロントエンド検証が通過した後に呼び出されます。