As a full stack of Ajax MVVM framework, ANGULARJS can be described in full swing, the real stack Ajax, the first problem is user authentication.
This article's authentication does not adopt the cookie, but uses the HTTP authorize request header to authenticate the user, this way can do forever only one user simultaneously on-line (the service side will accept only one legal token request at the same time, the other request returns 401)
Here I use service to save user information, service as follows
. Factory (' Authorize ', function () {return
{
uid: ',
token: ',
logout:function () {
This.uid = ';
This.token = ';
Localstorage.removeitem (' Authorize.uid ');
Localstorage.removeitem (' Authorize.token ');
}
}
})
Because the service is a single example. Save in the service is very appropriate, and then look at login detection.
Verification process
The app runtime proactively reads the Authorize.uid and Authorize.token fields in Localstorage, sending these two fields to back-end interface validation, which returns an HTTP 401 error (not authorized) if the validation succeeds in returning user information.
If Localstorage does not have these two fields, then detect if there are any in the URL, and if so, send to back-end validation after writing to the local localstorage, if not, jump to the back-end server's OAuth interface for authorization, Write OpenID and token to the QueryString and callback to the app page with the following code:
Authorize.uid = $ location.search (). Uid || localStorage.getItem ('authorize.uid');
Authorize.token = $ location.search (). Token || localStorage.getItem ('authorize.token');
if (! Authorize.uid ||! Authorize.token) {
if (! Platform.isWechat) {
Authorize.uid = 1001;
Authorize.token = '2ddha3nry8';
}
else {
location.href = CONFIG.api + '/ auth / oauth? callback =' + encodeURIComponent ($ location.protocol () + ": //" + $ location.host () + ":" + $ location.port () + "/ #" + $ location.path ());
return;
}
}
// write to local
localStorage.setItem ('authorize.uid', Authorize.uid);
localStorage.setItem ('authorize.token', Authorize.token);
// Read user data
var user = User.get ({uid: Authorize.uid}, function () {
$ rootScope.user = user;
});
Read the user data this side, the use of $resource service encapsulation, here is not said.
Authorization processing in the request process
Next is a more important point, how to inject authorize information into each request header after landing, using interceptors.
There is a problem, if because of the refresh too fast, detect user callback has not finished, this time access to all interfaces are 401, where the need to inject the interceptor on the $httpprovider to request recovery. The code is as follows:
.factory ('AuthInjector', function ($ q, Authorize, $ injector, CONFIG) {
return {
request: function (config) {
if (Authorize.token) {
config.headers.Authorization = 'Bearer' + Authorize.token;
}
return config;
},
response: function (response) {
var defer = $ q.defer ();
defer.resolve (response);
return defer.promise;
},
requestError: function (error) {
},
responseError: function (error) {
// If 401 and uid exists locally, refresh accessToken
if (error.status == 401) {
// Refresh request
var $ http = $ injector.get ("$ http");
$ http ({
method: 'GET',
url: CONFIG.api + '/ auth / token',
params: {
uid: Authorize.uid
}
}). success (function (data) {
Authorize.token = data.token;
// write to local
localStorage.setItem ('authorize.token', data.token);
return $ http (error.config);
});
}
else if (error.status == 422) {
var resp;
angular.forEach (error.data, function (item) {
if (resp == undefined) {
resp = item;
}
});
return $ q.reject (resp);
}
return $ q.reject ({
message: 'Request failed'
});
}
}
})
The principle is that all HTTP requests, once returned 401, are logged in again, and the last sentence
Return $http (Error.config);
That's a lot of it, to sum up.
Detection login in App.run
Authorize service saves user information
Httpprovider of injection interceptor to realize automatic adding of authorize headers and request recovery of 401 results