跟踪AngularJS应用程序中的“登录”状态

时间:2016-02-20 20:12:44

标签: javascript angularjs

我觉得我做错了什么。我是Angular的新手,我正在编写一些代码来跟踪登录状态。代码感觉相当脆弱。

在我的应用程序中,我想记录我是否已经过身份验证。现在我使用全局变量来做到这一点。但是由于这是通过$ http.get驱动的工厂调用在顶层控制器中异步更新的,该工厂调用更新了一个普通的常规javascript变量,因此各种指令和控制器都没有得到正确的状态。

有更有棱角的方法吗?

关注登录状态的控制器/指令可能应该有监听器,然后基本控制器应该执行$ scope。$ broadcast以便他们知道状态变化?或许这是了解$ watch的好时机?

另外我在顶级控制器中跟踪这个。也许这是错误的做法?作为提供者或服务,可以更好地跟踪登录状态吗?

1 个答案:

答案 0 :(得分:2)

在角度方面,所有.service和.factory类型都是单例。这意味着您可以将身份验证逻辑添加到.service或.factory中,您在该对象上存储的数据将可供整个系统中的任何其他服务/工厂或控制器访问。因此,将auth逻辑放在服务上,如下所示:

angular.module('my.app.services', []).factory('AuthService', ['$http', function($http) {
    var authenticated = false;
    var authUrl = '/path/to/auth/handler';

    return {
        isAuthenticated: function(){
            return authenticated;
        },
        login: function(data) {
            return $http.post(authUrl, data).then(function(response) {
                authenticated = true;
                return authenticated;
            }).catch(function(err) {
                authenticated = false;
                return authenticated;
            });
        }
    };
}]);

所以,现在你可以在任何地方注入AuthService并调用AuthService.isAuthenticated()来获取布尔值。

此外,理想情况下,您希望使用类似会话cookie的内容来确保对应用程序的所有其他请求都是安全的。基本上,必须对服务器的每个请求进行身份验证。当服务器检测到未经过身份验证的请求时,您可以从服务器返回HTTP 403状态代码。现在,您将需要一种干净的方法来处理来自$ http或$ resource的任何请求的403错误。为此,您可以设置HTTP拦截器,该拦截器将处理状态代码为4XX或5XX的任何失败请求。

在您应用的配置功能中:

angular.module('yourAppName').config(function ($provide, $httpProvider) {

    //Create interceptor to intercept all $http and $resource calls
    $provide.factory('MyHttpErrorInterceptor', ['$window', '$q', function ($window, $q) {

        function notifyError(rejection) {
            console.log(rejection);

            var errorMessage = '';
            switch(rejection.status) {
                case 403:
                    //redirect to auth URL when ANY request returns a 403 - Not authorized
                    $window.location = 'some/path/to/auth/resource';
                    break;
                case 500: 
                    //here, handle any 500 error, which means the server through an exception in the code.
                    // handle rejection.data to get any server side error messages 
                    // errorMessage += rejection.data.message;
                    break;
                case 400:
                    //handle bad request params
                    // errorMessage += something from rejection.data
                    break;
                default:
                    //handle any other status code such as -1 which could occur on things like a cross origin request
                    errorMessage += 'Request to ' + rejection.config.url + ' failed.';
            }

            if(rejection.status !== 403) {
                //don't show errors on 403. Should redirect to login page.
                //perhaps pop up an error page or message here, with the
                // errorMessage attribute
            }
        }

        return {
            // handle request failure
            requestError: function (rejection) {
                //handle failed request
                notifyError(rejection);
                // important to reject the promise
                return $q.reject(rejection);
            },

            // handle response error statuses
            responseError: function (rejection) {
                //handle error status and data
                notifyError(rejection);
                //important to reject the promise
                return $q.reject(rejection);
            }
        };
    }]);

    // Add the interceptor to the $httpProvider.
    $httpProvider.interceptors.push('MyHttpErrorInterceptor');

});

注意,您也可以使用拦截器来转换请求和响应,因此如果您发现自己需要在系统中全局处理$ http请求或响应,请使用拦截器并在一个位置定义逻辑。

希望这有助于您前进:)