2016-09-09 24 views
1

私は、ユーザー識別機能付きのSpring + AngularJS RestFulアプリケーションを持っています。AngularJS Controllerでイベントの優先度を指定する方法は?

とすぐに、私は次のようにこのデータを保存するには、ユーザーがログインしているとおり、私は私が私のメインコントローラに実装されている他のタブでこのsessionStorageを持ちたいので

$window.sessionStorage.user 

をここに提案される解決策: https://stackoverflow.com/a/32766809/1281500

また、このコントローラでは、ユーザがログインしているかどうかを確認するために、$stateChangeStartイベントを聞きます。ユーザーがログインしていない場合、私は彼を対応するログインページにリダイレクトします。

エクスプローラで新しいタブを開くと問題が発生します。あなたは以下のコードでわかるように、私はこのような新しいタブに古いタブから$window.sessionStorage.user変数を取得:

else if (event.key == 'sessionStorage' && !$window.sessionStorage.length) { 
     // another tab sent data <- get it 
     var data = JSON.parse(event.newValue); 
     for (var key in data) { 
      $window.sessionStorage.setItem(key, data[key]); 
     } 

しかし$stateChangeStartのコードがそう$window.sessionStorage.user上記のスニペットの前に実行されるではありません利用はまだありませんし、ユーザーは常に彼はすでに(元のタブに少なくとも)に記録されていても、ログインページにリダイレクトされ

$rootScope.$on('$stateChangeStart', function (event, toState, toParams) { 
     // if the user tries to access a restricted page an is not logged in, he is redirected to the login view 
     var restrictedPage = $.inArray(toState.name, ['login', 'sign-up']) === -1; 
     // "$window.sessionStorage.user" IS ALWAYS "UNDEFINED" just after a new tab is opened 
     if (restrictedPage && $window.sessionStorage.user === undefined) { 
      // Go to login page 
     } 
    }); 

完全なコントローラのコードは以下の通りです。 $stateChangeStartブロックでユーザーの資格情報を利用するにはどうすればよいですか?

(function() { 
    'use strict'; 

    angular 
    .module('app.core') 
    .controller('CoreController', CoreController); 

    CoreController.$inject = ['$q', '$scope', '$rootScope', '$state', '$location', '$cookies', 'LoginService', '$window']; 

    function CoreController($q, $scope, $rootScope, $state, $location, $cookies, LoginService, $window) { 
    var vm = this; 

    var sessionStorage_transfer = function(event) { 
     if(!event) { event = $window.event; } // ie suq 
     if(!event.newValue) return;   // do nothing if no value to work with 
     if (event.key == 'getSessionStorage') { 
     // another tab asked for the sessionStorage -> send it 
     $window.localStorage.setItem('sessionStorage', JSON.stringify(sessionStorage)); 
     // the other tab should now have it, so we're done with it. 
     $window.localStorage.removeItem('sessionStorage'); // <- could do short timeout as well. 
     } else if (event.key == 'sessionStorage' && !$window.sessionStorage.length) { 
     // another tab sent data <- get it 
     var data = JSON.parse(event.newValue); 
     for (var key in data) { 
      $window.sessionStorage.setItem(key, data[key]); 
     } 
     } 
    }; 

    // listen for changes to localStorage 
    if($window.addEventListener) { 
     $window.addEventListener("storage", sessionStorage_transfer); 
    } else { 
     $window.attachEvent("onstorage", sessionStorage_transfer); 
    }; 

    // ask other tabs for session storage (this is ONLY to trigger event) 
    if (!$window.sessionStorage.length) { 
     $window.localStorage.setItem('getSessionStorage', 'user'); 
     $window.localStorage.removeItem('getSessionStorage', 'user'); 
    }; 

    $rootScope.$on('$stateChangeStart', function (event, toState, toParams) { 
     // if the user tries to access a restricted page an is not logged in, he is redirected to the login view 
     var restrictedPage = $.inArray(toState.name, ['login', 'sign-up']) === -1; 
     if (restrictedPage && $window.sessionStorage.user === undefined) { 
      // Go to login page 
     } 
    }); 

    } 
})(); 

UPDATE

私のアプリケーションは、それは次のように動作しますステートレスです:

  • 初めてのアプリケーションへのユーザーアクセス私は、ユーザー名とパスワードを確認しています正しい(Spring Restサービスへの呼び出し)、その時点でユーザーのトークンを生成します。このトークンとユーザーデータは、ともに$window.sessionStorage.authToken$window.sessionStorage.authTokenのようにsessionStorageに格納されます。私はRESTfulなアプリケーションへのすべての要求にこのトークンを送る今から
function login(valid) { 
     if(!valid) return; 

     LoginService.authenticate(vm.user) 
     .then(
       function(user) { 
        var authToken = user.token; 
        $window.sessionStorage.authToken = authToken; 
        vm.authError = false; 
        if (vm.rememberMe) { 
         var now = new Date(); 
         var expireDate = new Date(now.getFullYear(), now.getMonth() + 1, now.getDate()); 
         $cookies.put(AUTH_TOKEN_COOKIE, authToken, {'expires': expireDate}); 
        } 
        LoginService.getUser() 
        .then(
         function(user) { 
          $window.sessionStorage.user = user 
          $state.go('installations'); 
         } 
        ); 
       }, 
       function(errAuthentication) { 
        vm.authError = true; 
        $window.sessionStorage.user = null; 
       } 
     ); 
    } 
  • と私はトークンをチェック春でフィルタを持っている: 私は別のAngularJSコントローラ(LoginController)からこれを管理しますユーザー資格情報が正しい。このトークンが存在しないか、もう有効でない場合、Spring Securityは対応する例外をスローし、この例外をキャッチしてログインページにリダイレクトします(このコードは現在の質問では重要ではないと思いますが、必要であれば)。

だから、基本的に私のユーザーは、現在sessionStorageオブジェクトに住んでいる、私はちょうど私がプロセスの最初のログイン時に格納された変数をチェックし、ユーザーがログインされているかどうかをチェックするサービスを持っていません。

私はこれがプロセスを少しはっきりさせるのに役立つことを願っています。

ありがとうございました。

+0

このログインはSpringをまったく経由していませんか? – ChiefTwoPencils

+0

私の更新をもう少し詳しくチェックしてください。ありがとうございました。 – rocotocloc

答えて

0

コントローラが他のモジュールより先に動作することを保証することは本当に困難です。

このチェックを他のものより先に実行する場合は、run moduleでそれを行う必要があります。

angular 
.module('myApp') 
.run(runBlock) 
.run(['mySessionChecker', '$rootScope', function (mySessionChecker, $rootScope) { 

    $rootScope.$on("$locationChangeStart", function() { 
     //Service that checks if the user is logged or not 
     mySessionChecker.checkSession().then(function (auth) { 
     //Auth tells you if the user is logged in or not 
     console.log('User is '+auth); 
     doSomething(); 
     }) 
    }); 

}]); 

function runBlock($log) { 
    $log.log('Angular's running'); 
} 

Run ModuleApp Module直後にブートストラップします。

たとえば、emit an event$rootScopeとするか、またはPostal.jsを使用して、その情報で何かを行うことができます。

私はeventを傍受するParent Controllerを作成し、ユーザーがログに記録されているかどうかを確認するためにチェックを行う必要があるコントローラを拡張します。

at this Q/Aをご覧ください。

私は役に立ちました。

+0

ありがとうございます。提案されたソリューションを正確に取得していないので、私のUPDATEを確認してください。 – rocotocloc

+0

私はこのアップデートを読んだが、あなたの問題点を正しく理解していない。これらの制御を早期に行うには、実行モジュールの中で実行する必要があります。 'stateChangeStart'の前にスニペットを実行することはできません。なぜなら、' run.config'の後にブートストラップされ実行されるコントローラの中でこれらのコントロールを行っているからです。 – AndreaM16

+0

私はあなたの意見を理解していますが、私の場合はこれをどのように実装するのか分かりません。上記のスニペットでは、runブロック内にユーザーのチェックを入れましたが、別のイベント(別のタブから 'sessionStorage'を取得するイベント)に依存しているため、私はそこに私を置くことができません。私はAngularJSから始めていますので、 '$ rootScope。$ on(" $ locationChangeStart ")'イベントの前に、新しいオープニングタブからデータを転送する方法を少し詳しく説明できますか? – rocotocloc

関連する問題