9

この質問は、angular-appプロジェクトと、それがユーザーを認証する方法について言及しています。

元の実装では、ルーターで resolve 句を使用して、一部の URL へのアクセスを保護していました。これは次のようになります。

$routeProvider.when('/projects', {
templateUrl:'projects/projects-list.tpl.html',
controller:'ProjectsViewCtrl',
resolve:{
  projects:['Projects', function (Projects) {
    //TODO: fetch only for the current user
    return Projects.all();
  }],
  authenticatedUser: securityAuthorizationProvider.requireAuthenticatedUser
}

});

ユーザーが認証され、プロジェクトがフェッチされるまで、ビューはレンダリングされません (UI のちらつきを防ぐため)。ユーザーが認証されていない場合、ログイン ポップアップがポップアップ表示され、ユーザーがそれを送信すると、promise が解決され、要求されたページが表示されます。Projects.all() 呼び出しで認証が必要ない場合、これはうまく機能します。

サーバー呼び出しのログは次のとおりです。

127.0.0.1 - - [Mon, 28 Oct 2013 11:15:47 GMT] "GET /projects HTTP/1.1" 200 739 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0"
Unauthenticated
127.0.0.1 - - [Mon, 28 Oct 2013 11:15:47 GMT] "GET /current-user HTTP/1.1" 200 24 "http://localhost:3000/projects" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0"
Unauthenticated
Unauthenticated
127.0.0.1 - - [Mon, 28 Oct 2013 11:15:47 GMT] "GET /current-user HTTP/1.1" 200 24 "http://localhost:3000/projects" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0"
127.0.0.1 - - [Mon, 28 Oct 2013 11:15:47 GMT] "GET /databases/angular_app/collections/projects?q=%7B%7D HTTP/1.1" 200 10 "http://localhost:3000/projects" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0"
Unauthenticated
127.0.0.1 - - [Mon, 28 Oct 2013 11:15:59 GMT] "POST /login HTTP/1.1" 200 161 "http://localhost:3000/projects" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0"

angular_app/collections/projects への呼び出しは、認証されていないユーザーに対しても有効です。

私の場合、次のコードがあります。

$stateProvider
    .state('root.tickets', {
        url: '/tickets',
        views: {
            'container@': {
                templateUrl: 'tickets/tickets-list.tpl.html',
                controller:'TicketsViewCtrl',
                resolve:{
                  ticketsy: ['Restangular', function (Restangular) {
                    //Call to tickets must be authenticated
                    return Restangular.all('tickets').getList();
                  }],
                  authenticatedUser: securityAuthorizationProvider.requireAuthenticatedUser
                }
            }
        }

違いは (私が ui-router と Restangular を使用することを除いて) API 呼び出しを認証する必要があることです。サーバーログは次のようになります。

[28/Oct/2013 05:50:15] "GET /api/tickets/ HTTP/1.1" 403 59
[28/Oct/2013 05:50:15] "GET / HTTP/1.1" 200 963
[28/Oct/2013 05:50:16] "GET /api/current-user/ HTTP/1.1" 200 14
[28/Oct/2013 05:50:16] "GET /api/tickets HTTP/1.1" 301 0
[28/Oct/2013 05:50:16] "GET /api/tickets/ HTTP/1.1" 403 59
[28/Oct/2013 05:50:22] "POST /api/login/ HTTP/1.1" 200 120

ここで 403 ステータス コードに注意してください。その結果、ユーザーにはログイン ポップアップが表示され、認証されますが、空のページが表示されます。これは、データ取得の約束の失敗が原因だと思います。

私の質問は、約束の順序を強制することは何とか可能ですか? 最初にユーザーが認証されているかどうかを確認してから、バックエンドなどに呼び出しを発行したいのですが、ここで使用できる他の解決策はありますか? 私はAngularを学んでいるので、簡単な解決策があってもそれは私には明らかではありません.

4

2 に答える 2

15

私はリゾルバー パターンを使用するのが大好きですが、Angular ui ルーターでこのようなことを行うのは非常に難しいと感じています。

1 つの解決策は、次のように、authenticatedUser リゾルバーの結果を、保護する API 呼び出しリゾルバーに依存性注入することです。

$stateProvider
    .state('root.tickets', {
        url: '/tickets',
        views: {
            'container@': {
                templateUrl: 'tickets/tickets-list.tpl.html',
                controller:'TicketsViewCtrl',
                resolve:{
                  authenticatedUser: securityAuthorizationProvider.requireAuthenticatedUser,
                  ticketsy: function (Restangular, authenticatedUser) {
                    //Call to tickets must be authenticated
                    return Restangular.all('tickets').getList();
                  }
                }
            }
        }

このようにして、リゾルバーは一度にすべて非同期ではなく、チェーン (authenticatedUser -> tickety) で実行されます。

これが役に立てば幸いです..もっと良い方法があればいいのに..それが、スタックオーバーフローを検索する理由です。

于 2014-01-08T19:52:05.663 に答える