我觉得我做错了什么。我是Angular的新手,我正在编写一些代码来跟踪登录状态。代码感觉相当脆弱。
在我的应用程序中,我想记录我是否已经过身份验证。现在我使用全局变量来做到这一点。但是由于这是通过$ http.get驱动的工厂调用在顶层控制器中异步更新的,该工厂调用更新了一个普通的常规javascript变量,因此各种指令和控制器都没有得到正确的状态。
有更有棱角的方法吗?
关注登录状态的控制器/指令可能应该有监听器,然后基本控制器应该执行$ scope。$ broadcast以便他们知道状态变化?或许这是了解$ watch的好时机?
另外我在顶级控制器中跟踪这个。也许这是错误的做法?作为提供者或服务,可以更好地跟踪登录状态吗?
答案 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请求或响应,请使用拦截器并在一个位置定义逻辑。
希望这有助于您前进:)