web-dev-qa-db-ja.com

AngularJS:シングルページアプリケーションで認証を使用する基本的な例

私は AngularJS が初めてで、彼らのチュートリアルを最後まで経験し、感じました。

RESTエンドポイントのそれぞれを認証する必要があるプロジェクトのバックエンドが用意されています。

やりたいこと
a。)プロジェクトhttp://myproject.comに単一のページを作成したい。
b。)ユーザーがブラウザでURLにアクセスすると、ユーザーがログインしているかどうかに基づいて、同じURL http://myproject.comでホームページ/ビューまたはログインページ/ビューが表示されます。
c。)ユーザーがログインしていない場合、フォームに記入し、サーバーがセッションでUSER_TOKENを設定するため、エンドポイントへの以降のすべてのリクエストはUSER_TOKENに基づいて認証されます

私の混乱
a。)AngularJSを使用してクライアント側の認証を処理するにはどうすればよいですか? here および here を見ましたが、それらの使用方法がわかりませんでした
b。)ユーザーが同じURLでログインしているかどうかに基づいて、異なるビューをユーザーに表示するにはどうすればよいですかhttp://myproject.com

私は初めてangle.jsを使用していますが、開始方法について本当に混乱しています。アドバイスやリソースを歓迎します。

99
daydreamer

私はこのアプローチが好きで、フロントエンドで認証関連のことを何もせずにサーバー側に実装しました

私の最新アプリでの私の「テクニック」は..クライアントはAuthを気にしません。アプリ内のすべての要素は最初にログインを必要とするため、セッションで既存のユーザーが検出されない限り、サーバーは常にログインページを提供します。 session.userが見つかった場合、サーバーは単にindex.htmlを送信します。バム:-o

「アンドリュー・ジョスリン」によるコメントを探してください。

https://groups.google.com/forum/?fromgroups=#!searchin/angular/authentication/angular/POXLTi_JUgg/VwStpoWCPUQJ

25
daydreamer

基本的にこの記事を要約したgithubリポジトリを作成しました: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

ng-login Githubリポジトリ

Plunker

できる限り良い説明をしようと思いますが、皆さんの助けになることを願っています。

(1)app.js:アプリ定義での認証定数の作成

var loginApp = angular.module('loginApp', ['ui.router', 'ui.bootstrap'])
/*Constants regarding user login defined here*/
.constant('USER_ROLES', {
    all : '*',
    admin : 'admin',
    editor : 'editor',
    guest : 'guest'
}).constant('AUTH_EVENTS', {
    loginSuccess : 'auth-login-success',
    loginFailed : 'auth-login-failed',
    logoutSuccess : 'auth-logout-success',
    sessionTimeout : 'auth-session-timeout',
    notAuthenticated : 'auth-not-authenticated',
    notAuthorized : 'auth-not-authorized'
})

(2)認証サービス:以下のすべての機能がauth.jsサービスに実装されています。 $ httpサービスは、認証手順のためにサーバーと通信するために使用されます。認可に関する機能も含まれます。つまり、ユーザーが特定のアクションを実行できる場合です。

angular.module('loginApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS', 
function($http, $rootScope, $window, Session, AUTH_EVENTS) {

authService.login() = [...]
authService.isAuthenticated() = [...]
authService.isAuthorized() = [...]
authService.logout() = [...]

return authService;
} ]);

(3)Session:ユーザーデータを保持するシングルトン。ここでの実装はあなた次第です。

angular.module('loginApp').service('Session', function($rootScope, USER_ROLES) {

    this.create = function(user) {
        this.user = user;
        this.userRole = user.userRole;
    };
    this.destroy = function() {
        this.user = null;
        this.userRole = null;
    };
    return this;
});

(4)親コントローラー:これをアプリケーションの「メイン」機能と見なし、すべてのコントローラーはこのコントローラーから継承し、認証のバックボーンですこのアプリの。

<body ng-controller="ParentController">
[...]
</body>

(5)アクセス制御:特定のルートでアクセスを拒否するには、2つのステップを実装する必要があります。

a)以下に示すように、UIルーターの$ stateProviderサービスで、各ルートへのアクセスを許可されたロールのデータを追加します(ngRouteでも同様に機能します)。

.config(function ($stateProvider, USER_ROLES) {
  $stateProvider.state('dashboard', {
    url: '/dashboard',
    templateUrl: 'dashboard/index.html',
    data: {
      authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
    }
  });
})

b)$ rootScope。$ on( '$ stateChangeStart')で、ユーザーが承認されていない場合に状態が変更されないようにする関数を追加します。

$rootScope.$on('$stateChangeStart', function (event, next) {
    var authorizedRoles = next.data.authorizedRoles;
    if (!Auth.isAuthorized(authorizedRoles)) {
      event.preventDefault();
      if (Auth.isAuthenticated()) {
        // user is not allowed
        $rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
      } else {
        // user is not logged in
        $rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
      }
    }
});

(6)認証インターセプター:これは実装されていますが、このコードのスコープで確認することはできません。各$ httpリクエストの後、このインターセプターはステータスコードをチェックし、以下のいずれかが返された場合、ユーザーに再度ログインするよう強制するイベントをブロードキャストします。

angular.module('loginApp')
.factory('AuthInterceptor', [ '$rootScope', '$q', 'Session', 'AUTH_EVENTS',
function($rootScope, $q, Session, AUTH_EVENTS) {
    return {
        responseError : function(response) {
            $rootScope.$broadcast({
                401 : AUTH_EVENTS.notAuthenticated,
                403 : AUTH_EVENTS.notAuthorized,
                419 : AUTH_EVENTS.sessionTimeout,
                440 : AUTH_EVENTS.sessionTimeout
            }[response.status], response);
            return $q.reject(response);
        }
    };
} ]);

P.S。第1回の記事で述べたフォームデータの自動入力のバグは、directives.jsに含まれるディレクティブを追加することで簡単に回避できます。

P.S.2このコードは、さまざまなルートを表示したり、表示することを意図していないコンテンツを表示したりするために、ユーザーが簡単に調整できます。ロジックはサーバー側で実装する必要があります。これは、ng-appで適切に表示するための方法にすぎません。

48

ここで同様の質問に答えました: AngularJS Authentication + RESTful API


AngularJSモジュール for serApp を記述しました。これは、保護/パブリックルート、ログイン/ログアウトの再ルーティング、ステータスチェックのハートビート、セッショントークンのCookieへの保存、イベントをサポートしますなど.

次のいずれかが可能です。

  1. モジュールを変更して独自のAPIに添付するか、または
  2. serApp (クラウドベースのユーザー管理API)と一緒にモジュールを使用します

https://github.com/userapp-io/userapp-angular

UserAppを使用する場合、ユーザースタッフ用のサーバー側コードを記述する必要はありません(トークンの検証以上)。 Codecademyのコース を試してみてください。

仕組みの例を次に示します。

  • パブリックにする必要があるルートと、ログインフォームであるルートを指定する方法:

    $routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true});
    $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true});
    $routeProvider.when('/home', {templateUrl: 'partials/home.html'});
    

    .otherwise()ルートは、ログイン後にユーザーをリダイレクトする場所に設定する必要があります。例:

    $routeProvider.otherwise({redirectTo: '/home'});

  • エラー処理を伴うログインフォーム:

    <form ua-login ua-error="error-msg">
        <input name="login" placeholder="Username"><br>
        <input name="password" placeholder="Password" type="password"><br>
        <button type="submit">Log in</button>
        <p id="error-msg"></p>
    </form>
    
  • エラー処理を伴う登録フォーム:

    <form ua-signup ua-error="error-msg">
      <input name="first_name" placeholder="Your name"><br>
      <input name="login" ua-is-email placeholder="Email"><br>
      <input name="password" placeholder="Password" type="password"><br>
      <button type="submit">Create account</button>
      <p id="error-msg"></p>
    </form>
    
  • ログアウトリンク:

    <a href="#" ua-logout>Log Out</a>

    (セッションを終了し、ログインルートにリダイレクトします)

  • ユーザープロパティへのアクセス:

    ユーザープロパティには、userサービスを使用してアクセスします。例:user.current.email

    またはテンプレートで:<span>{{ user.email }}</span>

  • ログイン時にのみ表示される要素を非表示にします:

    <div ng-show="user.authorized">Welcome {{ user.first_name }}!</div>

  • 許可に基づいて要素を表示する:

    <div ua-has-permission="admin">You are an admin</div>

バックエンドサービスに対して認証するには、user.token()を使用してセッショントークンを取得し、AJAXリクエストで送信します。バックエンドで、 serApp API (UserAppを使用する場合)を使用して、トークンが有効かどうかを確認します。

助けが必要な場合は、私に知らせてください!

14

Angularjsでは、UIパーツ、サービス、ディレクティブ、およびUIを表すangularjsのすべての部分を作成できます。取り組むべき素晴らしい技術です。

この技術を初めて使い、「ユーザー」を認証したい人は誰でも、C#web apiの力でそれを行うことをお勧めします。そのため、OAuth仕様を使用して、ユーザーを認証する強力なセキュリティメカニズムを構築できます。 OAuthを使用してWebApiを構築したら、トークンのAPIを呼び出す必要があります。

var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 

トークンを取得したら、Tokenを使用して、angularjsにリソースを要求し、OAuth仕様を使用してWeb Apiで保護されたリソースにアクセスします。

さらにヘルプが必要な場合は、以下の記事をご覧ください。

http://bitoftech.net/2014/06/09/angularjs-token-authentication-using-asp-net-web-api-2-owin-asp-net-identity/

2
Gurupreet

すべてのJSON応答にはプロパティ({authenticated:false}など)を含める必要があり、クライアントは毎回それをテストする必要があると思います。falseの場合、Angularコントローラー/サービスはログインページに「リダイレクト」します。

そして、ユーザーがde JSONをキャッチし、boolをTrueに変更するとどうなりますか?

このようなことをクライアント側に頼るべきではないと思います。ユーザーが認証されない場合、サーバーはログイン/エラーページにリダイレクトするだけです。

1
Doum
var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 
0
Nver Abgaryan