AngularJS の ng Http リクエストとレスポンスの形式変換方法

高洛峰
リリース: 2016-12-07 14:47:50
オリジナル
1761 人が閲覧しました

ID 認証は Web に適用されることがよくあります。この記事では、AngularJS で ID 認証を使用するスキルを紹介します。早速、読み進めてみましょう。

ID 認証

最も一般的な ID 認証方法は、ユーザー名 (または電子メール) とパスワードを使用してログインすることです。これは、ユーザーが個人情報を使用してログインできるようにログイン フォームを実装することを意味します。フォームは次のようになります。

<form name="loginForm" ng-controller="LoginController"
   ng-submit="login(credentials)" novalidate>
 <label for="username">Username:</label>
 <input type="text" id="username"
     ng-model="credentials.username">
 <label for="password">Password:</label>
 <input type="password" id="password"
     ng-model="credentials.password">
 <button type="submit">Login</button>
</form>
ログイン後にコピー

これは Angular を使用したフォームであるため、フォームのアップロード時に ngSubmit ディレクティブを使用して関数をトリガーします。注意すべき点の 1 つは、$scope.credentials オブジェクトを直接使用するのではなく、個人情報をアップロード フォーム関数に渡すことです。これにより、関数の単体テストが容易になり、現在のコントローラー スコープへの関数の結合が軽減されます。このコントローラーは次のようになります:

.controller(&#39;LoginController&#39;, function ($scope, $rootScope, AUTH_EVENTS, AuthService) {
 $scope.credentials = {
  username: &#39;&#39;,
  password: &#39;&#39;
 };
 $scope.login = function (credentials) {
  AuthService.login(credentials).then(function (user) {
   $rootScope.$broadcast(AUTH_EVENTS.loginSuccess);
   $scope.setCurrentUser(user);
  }, function () {
   $rootScope.$broadcast(AUTH_EVENTS.loginFailed);
  });
 };javascript:void(0);
})
ログイン後にコピー

ここで実際のロジックが欠如していることに気付きました。このコントローラーは、認証ロジックをフォームから切り離すためにこのように作成されています。コントローラーからできるだけ多くのロジックを抽出し、それをすべてサービスに配置することをお勧めします。 AngularJS のコントローラーは、過度に重いタスクを引き受けるのではなく、(監視または手動操作を使用して) $scope 内のオブジェクトのみを管理する必要があります。

セッションの変更を通知する

ID 認証は、アプリケーション全体の状態に影響を与えます。このため、私はイベント ($broadcast を使用) を使用してユーザー セッションの変更を通知することを好みます。考えられるすべてのイベント コードを中間点で定義することをお勧めします。私はこれを行うために定数を使用するのが好きです:

.constant(&#39;AUTH_EVENTS&#39;, {
 loginSuccess: &#39;auth-login-success&#39;,
 loginFailed: &#39;auth-login-failed&#39;,
 logoutSuccess: &#39;auth-logout-success&#39;,
 sessionTimeout: &#39;auth-session-timeout&#39;,
 notAuthenticated: &#39;auth-not-authenticated&#39;,
 notAuthorized: &#39;auth-not-authorized&#39;
})
ログイン後にコピー

定数の優れた特徴の 1 つは、サービスと同じように、自由に他の場所に注入できることです。これにより、単体テストで定数を簡単に呼び出すことができるようになります。定数を使用すると、大量のファイルを変更しなくても、後で簡単に名前を変更できます。同じトリックがユーザーの役割でも機能します:

.constant(&#39;USER_ROLES&#39;, {
 all: &#39;*&#39;,
 admin: &#39;admin&#39;,
 editor: &#39;editor&#39;,
 guest: &#39;guest&#39;
})
ログイン後にコピー

編集者と管理者に同じ権限を与えたい場合は、単に「editor」を「admin」に変更するだけです。

認証と認可 (アクセス制御) に関連する AuthService

ロジックは、同じサービスに配置するのが最適です:

.factory(&#39;AuthService&#39;, function ($http, Session) {
 var authService = {};
 
 authService.login = function (credentials) {
  return $http
   .post(&#39;/login&#39;, credentials)
   .then(function (res) {
    Session.create(res.data.id, res.data.user.id,
            res.data.user.role);
    return res.data.user;
   });
 };
 
 authService.isAuthenticated = function () {
  return !!Session.userId;
 };
 
 authService.isAuthorized = function (authorizedRoles) {
  if (!angular.isArray(authorizedRoles)) {
   authorizedRoles = [authorizedRoles];
  }
  return (authService.isAuthenticated() &&
   authorizedRoles.indexOf(Session.userRole) !== -1);
 };
 return authService;
})
ログイン後にコピー

認証の問題からさらに距離を置くために、私は別のサービス (シングルトン オブジェクト、サービス スタイル) を使用して、ユーザーのセッション情報を保存します。セッション情報の詳細はバックエンドの実装によって異なりますが、より一般的な例を示します。

.service(&#39;Session&#39;, function () {
 this.create = function (sessionId, userId, userRole) {
  this.id = sessionId;
  this.userId = userId;
  this.userRole = userRole;
 };
 this.destroy = function () {
  this.id = null;
  this.userId = null;
  this.userRole = null;
 };
 return this;
})
ログイン後にコピー

ユーザーがログインすると、その情報は特定の場所 (右上隅など) に表示されます。アバターか何か)。これを実現するには、ユーザー オブジェクトが $scope オブジェクトによって参照される必要があり、できればグローバルに呼び出すことができるオブジェクトを参照する必要があります。 $rootScope が最初の選択肢であることは明らかですが、私は $rootScope を使いすぎないよう自制しています (実際には $rootScope はグローバル イベント ブロードキャストにのみ使用しています)。私がこれを行う方法は、アプリケーションのルート ノード、または少なくとも DOM ツリーより上位のどこかにコントローラーを定義することです。 タグは良い選択です:

<body ng-controller="ApplicationController">
 ...
</body>
ログイン後にコピー

ApplicationController は、アプリケーションのグローバル ロジックのコンテナーであり、Angular の run メソッドを実行するためのオプションです。したがって、これは $scope ツリーのルートにあり、他のすべてのスコープはそこから継承します (分離スコープを除く)。ここは、currentUser オブジェクトを定義するのに適した場所です:

.controller(&#39;ApplicationController&#39;, function ($scope,
                        USER_ROLES,
                        AuthService) {
 $scope.currentUser = null;
 $scope.userRoles = USER_ROLES;
 $scope.isAuthorized = AuthService.isAuthorized;
 
 $scope.setCurrentUser = function (user) {
  $scope.currentUser = user;
 };
})
ログイン後にコピー

currentUser オブジェクトを実際に割り当てるのではなく、後で currentUser にアクセスできるようにスコープ付きプロパティを初期化するだけです。残念ながら、シャドウ プロパティが作成されるため、子スコープの currentUser に単純に新しい値を割り当てることはできません。これは、プリミティブ型 (文字列、数値、ブール値、未定義、null) を参照ではなく値で渡した結果です。シャドウプロパティを防ぐには、セッター関数を使用する必要があります。 Angular スコープとプロトタイプの継承について詳しく知りたい場合は、「スコープについて」を参照してください。

アクセス制御

ID認証、つまりアクセス制御は、実はAngularJSには存在しません。私たちはクライアント アプリケーションであるため、すべてのソース コードはユーザーの手にあります。ユーザーがコードを改ざんして認証されたインターフェイスを取得することを防ぐ方法はありません。私たちにできることは、コントロールを表示することだけです。真の認証が必要な場合は、サーバー側で認証を行う必要がありますが、それはこの記事の範囲外です。

要素の表示を制限する

AngularJS には、スコープまたは式に基づいて要素の表示または非表示を制御するディレクティブ (ngShow、ngHide、ngIf、ngSwitch) があります。最初の 2 つは