可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm banging my head on a wall with this - I'm relatively new to working with APIs and have yet to do anything that requires authentication.
I'm stuck with sending a POST request to the API. The endpoint for creating a piece of content is:
/entity/node
I can send a successful POST request if I send the following:
headers: {
"Authorization": "Basic YWRtaW46MTIzcXdl", //admin:123qwe
},
The problem I am having is with Authorization. I'm specifying Basic and then an encoded string here, which is my admin login. So when hardcoded, I can post.
My question - when the user logs in correctly, I need the headers to be set so that all future post requests work. How can I do this in AngularJS?
I have tried passing a dynamically generated code:
"Authorization": "Basic " + auth,
where auth is a base64 encoded user:pass, but this does not work. My thinking is that this value needs to be stored somewhere for retrieval whenever a POST request is made. But how?
回答1:
Call this once you have a token:
$httpProvider.defaults.transformRequest.push(function (data, headersGetter) {
if (authToken !== null) {
var headers = headersGetter();
angular.extend(headers, 'Authorization: basic ' + authToken);
}
return data;
});
EDIT:
Have not tested it, but it should be something like:
myApp.provider('authService', function() {
var authToken = null;
this.$get = ['$httpProvider', function($httpProvider) {
return {
configure: configure,
setAuthToken: setAuthToken
}
};
function configure() {
$httpProvider.defaults.transformRequest.push(function (data, headersGetter) {
if (authToken !== null) {
var headers = headersGetter();
angular.extend(headers, 'Authorization: basic ' + authToken);
}
return data;
});
}
function setAuthToken(token) {
authToken = token;
}
});
and then inject authService
to your app config and call authService.configure()
回答2:
In such cases what I usually have been doing is store any login token or such credentials(not passwords) in cookies and then access it via an angular service. Since angular services are singletons the value is retained throughout the app unless the page reloads which is where the cookie comes into play.
An example service that might look something like this
(function(){
function Factory($resource, $q, $window, User, $cookie){
var Resource = $resource(
// your resource config
),
res = Resource,
proto = res.prototype;
res.currentToken = null;
res.currentUser = null;
res.unsetAuthProperties = function() {
delete $cookie.authToken;
res.currentToken = null;
res.currentUser = null;
};
// call this method after you retrieve the credentials
res.setAuthProperties = function(response) {
if(!response.id) {
res.unsetAuthProperties();
} else {
res.currentToken = {
id: response.id,
value: response.value
};
// set the current user
res.currentUser = User.getInstance(response.jw_tokenable);
// set the token in the cookie
$cookie.authToken = res.currentToken.value;
}
};
res.resolveCurrentUser = function () {
var defered = $q.defer();
// if the user is already signed in
// resolve the promise
// if not do a manual resolve
res.isSignedIn() ? defered.resolve() : resolve();
// get the current user from the server
// and resolve the promise
function resolve () {
res.current().$promise
.then(function(response) {
res.setAuthProperties(response);
})
.finally(function() {
res.isSignedIn() ? defered.resolve() : defered.reject();
});
};
return defered.promise;
};
return res;
};
Once you have such a service ready use an angular interceptor to intercept the requests to which you want to add the auth headers to.
https://docs.angularjs.org/api/ng/service/$http
回答3:
Use angular-local-storage
to store your token in client's local browser when user get successful login.
angular-local-storage
$http.post('/token', data).success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token,});
});
once you set token in local-storage, you are able to get it for that user.
like this : localStorageService.get('authorizationData');
Now use authInterceptorService
to set header for each request
var _request = function (config) {
config.headers = config.headers || {};
var authData = localStorageService.get('authorizationData');
if (authData) {
config.headers.Authorization = 'Basic' + authData.token;
}
return config;
}
here you get all details : AngularJS Token Authentication using ASP.NET Web API 2, Owin, and Identity
回答4:
angular js is simply javascript
first you need to store your token in local storage
after you retrieve your token then you will store it in local storage
window.localStorage.setItem('auth_token', token);
then you will add it to $httpProvider.interceptors so every request will have your basic authorization
myapp.factory("AuthI", function ($location, $q) {
return {
request: function (config) {
config.headers = config.headers || {};
if (window.localStorage.getItem('auth_token')) {
config.headers.Authorization = 'basic ' + window.localStorage.getItem('auth_token');
}
return config;
}
};
});
myapp.config(function ($httpProvider) {
$httpProvider.interceptors.push("AuthI");
});
回答5:
Currently I am working on a project which deals with the same problem as yours. As well, being new to Angular framework myself, I usually try to find a solution created by others and adapt it to my needs.
angular-basicauth
To deal with the basic authorization I have found an Angular module hosted here: https://github.com/iandotkelly/angular-basicauth.
It describes the configuration clearly, so I am not going to rewrite it all here. I think it serves all the purposes you would require it to. However, when using some already made solution you have to accept it's drawbacks. The one I really do not like is:
Please note this module stores unencypted username & password in local-storage or cookies, so is susceptible to attack from code from the same domain
Since the module I have posted is based on MIT license you are free to grab the source code and play with it as you like. The solution is fairly simple and I believe modifying it is not a big deal. For instance, because I have found the cookie part unacceptable, I do not use cookies at all.
With this approach you have to modify it in a way you keep all the credentials stored in the angular service/factory (ie. authService
) in a variable and read its' value when needed.
On the other hand, this modification brings a certain issue of manual reload of a page. In such case, since you reinitialize angular states, the user will be asked again to log in to your application. Unfortunately, there is no way (that I know of) that deals with basic-auth and lets you store the credentials safe. And since there is no session you could try to restore, you are basically choosing between unsafe local storage or in-memory variable (which seems safe enough for me).
warning
By using basic-authentication you are of course accepting all the limitations it has and obviously the biggest one would be the base64
encoding of your credentials which is easily decipherable. Without using a secured protocol you are actually exposing the user data nearly in the same way as you would be by sending it as a plain text.