2016-11-15 157 views
2

我目前使用$rootScope存儲用戶信息以及用戶是否登錄。我嘗試過使用$window.localStorage,但沒有成功。我的目標是一旦用戶登錄,讓他們的用戶名出現在導航欄,個人用戶配置文件視圖,所有用戶視圖等中,我的導航欄中的項目通過ng-show顯示。我需要持久登錄。我有導航欄$rootscope,但每當我嘗試轉換到$window.localStorage時,它都會失敗。下面是使用$rootScope代碼:使用本地存儲來存儲AngularJS數據

mainModule

angular.module('mainModule', [ 
     'ui.router', 
     ... 
    ]) 
    .config(configFunction) 
    .run(['$rootScope', '$state', 'Auth', function($rootScope, $state, Auth) { 
     $rootScope.$on('$stateChangeStart', function(event, next) { 
      if (next.requireAuth && !Auth.getAuthStatus()) { 
       console.log('DENY'); 
       event.preventDefault(); 
       $state.go('login'); 
      } else if (Auth.getAuthStatus() || !Auth.getAuthStatus()) { 
       console.log('ALLOW'); 
      } 
     }); 
    }]); 

驗證廠

angular.module('authModule').factory('Auth', ['$http', '$state', function authFactory($http, $state) { 
     var factory = {}; 

     var loggedIn = false; 
     var userData = {}; 

     factory.getAuthStatus = function() { 
      $http.get('/api/v1/auth') 
       .success(function(data) { 
        if (data.status == true) { 
         loggedIn = true; 
        } else { 
         loggedIn = false; 
        } 
       }) 
       .error(function(error) { 
        console.log(error); 
        loggedIn = false; 
       }); 
      return loggedIn; 
     } 

     return factory; 
    }]); 

登錄控制器

function SigninController($scope, $rootScope, $http, $state) { 
    $scope.userData = {}; 

    $scope.loginUser = function() { 
     $http.post('api/v1/login', $scope.userData) 
      .success((data) => { 
       $scope.userData = data.data; 
       $rootScope.loggedIn = true; 
       $rootScope.userData = data; 
       $state.go('home'); 
      }) 
      .error((error) => { 
       console.log('Error: ' + error); 
      }); 
    }; 
} 

導航控制器

function NavbarController($scope, Auth) { 
    $scope.loggedIn = Auth.getAuthStatus(); 
} 

編輯編輯編輯

這裏是我如何使用本地存儲。這些是唯一改變的東西。

登錄控制器

function SigninController($scope, $window, $http, $state) { 
    $scope.userData = {}; 

    $scope.loginUser = function() { 
     $http.post('api/v1/login', $scope.userData) 
      .success((data) => { 
       $scope.userData = data.data; 
       $window.localStorage.setItem('userData', angular.toJson(data)); 
       $window.localStorage.setItem('loggedIn', true); 
       $state.go('home'); 
      }) 
      .error((error) => { 
       console.log('Error: ' + error); 
      }); 
    }; 
} 

驗證廠

angular 
    .module('authModule') 
    .factory('Auth', ['$http', '$window', '$state', function authFactory($http, $window, $state) { 
     var factory = {}; 

     factory.getAuthStatus = function() { 
      $http.get('/api/v1/auth') 
       .success(function(data) { 
        if (data.status == true) { 
         $window.localStorage.setItem('loggedIn', true); 
        } else { 
         $window.localStorage.setItem('loggedIn', false); 
        } 
       }) 
       .error(function(error) { 
        console.log(error); 
        $window.localStorage.setItem('loggedIn', false); 
       }); 
      return $window.localStorage.getItem('loggedIn'); 
     } 

     return factory; 
    }]); 
+2

你可以顯示你的嘗試不工作嗎?另外,使用localStorage,而不是$ window.localStorage。此外,localStorage只存儲字符串,所以你會希望使用JSON.stringify()和JSON.parse()來存儲/檢索你的對象在localStorage – holtc

+0

@holtc是的,給我幾分鐘!謝謝! – 2b2a

+0

@holtc它已經結束了!你能否提供一個解釋,爲什麼不使用$ window.localStorage?我的例子使用它,因爲這是我以前使用過的。 – 2b2a

回答

2

我看到與您使用的localStorage.getItem('loggedIn')一個潛在的問題。

因爲localStorage的只存儲字符串,返回給你實際上是你把布爾值的字符串化版本。如果字符串'false'被退回,你的主模塊中的!Auth.getAuthStatus()檢查例如將始終評估爲布爾false因爲JavaScript中的任何非空字符串都是「truthy」。

!'false' === false(同!true === false

您可以通過在localStorage的值使用JSON.parse克服這一點。例如JSON.parse(localStorage.getItem('loggedIn'))會將字符串'false'解析爲布爾型false

+0

關於真值問題的好處。 +1 – MBielski

1

只需將$window.localStorage替換爲window.localStorage,您應該沒問題。

例如:

function SigninController($scope, $window, $http, $state) { 
    $scope.userData = {}; 

    $scope.loginUser = function() { 
     $http.post('api/v1/login', $scope.userData) 
      .success((data) => { 
       $scope.userData = data.data; 
       window.localStorage.setItem('userData', angular.toJson(data)); 
       window.localStorage.setItem('loggedIn', true); 
       $state.go('home'); 
      }) 
      .error((error) => { 
       console.log('Error: ' + error); 
      }); 
    }; 
} 

這就是說,存儲的localStorage(或sessionStorage的)認證狀態不下去的好路徑。這兩個鍵/值對都可以在開發人員窗格中讀取,然後通過控制檯更改(又名欺騙)。更好的解決方案是在成功登錄後返回一個唯一值(GUID),並將其存儲在cookie中(設置爲在很短的時間內過期,例如20分鐘),以便在服務器上讀取並在那裏驗證。您可以並應該使用$cookie。您的用戶登錄狀態應該由服務器端控制,而不是客戶端。客戶應始終必須證明其已通過身份驗證。

要堅持登錄,請創建一個服務來處理您的訪問者,並讓該服務處理登錄/註銷並提供登錄證明。登錄證明應該始終是由內部保存的私有值該服務並且無法在其外部訪問。

(function() { 
    'use strict'; 

    var visitorModelService = ['$http', function ($http) { 
      var loggedIn = false, 
       visitorModel = { 
        login:function(){ 
         //do login stuff with $http here 
         //set loggedIn to true upon success 
        }, 
        loggedIn:function(){ 
         return loggedIn; 
        }, 
        logout:function(){ 
         //do logout stuff with $http here 
         //no matter what, set loggedIn to false 
        } 
      }; 
      return visitorModel; 
     }]; 

    var module = angular.module('models.VisitorModel', []); 
    module.factory('VisitorModel', visitorModelService); 
}()); 

這樣做,你可以簡單地在你的ng-show檢查visitor.loggedIn和擁有一切集中。如:

<a ng-click='visitor.logout' ng-show='visitor.loggedIn'>Log Out</a> 

更重要的是,把那些只有通過認證的用戶可見的div標籤的元素和隱藏/顯示他們EN-質量。