使用本地存储来存储AngularJS数据

时间:2016-11-15 20:30:52

标签: javascript angularjs node.js

我目前正在使用$rootScope来存储用户信息以及用户是否已登录。我尝试使用$window.localStorage,但没有成功。我的目标是在用户登录后通过ng-show显示导航栏中的项目,用户名显示在导航栏中,个人用户个人资料视图,所有用户视图等等。我需要持久登录。我让导航栏使用$rootscope,但每当我尝试转换到$window.localStorage时,它都会失败。以下是使用$rootScope的代码:

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');
            }
        });
    }]);

Auth Factory

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);
            });
    };
}

Auth Factory

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 个答案:

答案 0 :(得分: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

答案 1 :(得分: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);
}());

执行此操作,您只需检查visitor.loggedIn中的ng-show并将所有内容集中在一起即可。如:

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

更好的是,将只有经过身份验证的用户可见的元素放在div标记中,然后隐藏/显示它们。