如何为不同的请求(URL)拆分拦截器?
How to split interceptor for different requests (URLs)?
起初我有 configAuth
和 headers,包括每个控制器的 JWT 令牌。
var configAuth = {
headers: {
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('token')
}
};
但现在当我拥有大量控制器时,我意识到我需要为此做点什么。我听说过 interceptors
并试图得到它们。
我知道我不能只为每个请求添加令牌,因为有些页面和请求(例如 /login
根本不应该有 Authorization
令牌。使用 Authorization header
获取 html 文件不知何故给了我一个例外。所以我试过这样拆分请求:
angular.module('App')
.factory('sessionInjector',['$injector', function ($injector) {
var sessionInjector = {
request: function (config) {
if (config.url == "/one" || config.url == "/two"){
config.headers['Content-Type'] = 'application/json;charset=utf-8;';
config.headers['Authorization'] = localStorage.getItem('token');
} else {
config.headers['Content-Type'] = 'application/json;charset=utf-8;';
}
return config;
},
response: function(response) {
if (response.status === 401) {
var stateService = $injector.get('$state');
stateService.go('login');
}
return response || $q.when(response);
}
};
return sessionInjector;
}]);
但它不适用于 /one/{one_id}
之类的请求,而且我无法对所有可能性进行硬编码。那么最佳做法是什么?
有更好的方法可以做到这一点。登录后将身份验证令牌设置到 $http 服务的 header 中。这样你就不需要在每次调用时都传递配置object。
登录:
function Login(credentials){
$http.post(apiPath, credentials).then(function (data) {
$http.defaults.headers.common['Authorization'] = data['token'];
});
}
在此之后的所有 HTTP 调用都将设置授权 header。
但是有些调用不需要授权,在这些情况下你可以编写一个函数,它有自己的配置 object 在 header.
中未经授权传递
未经授权的功能:
function Without_Auth(url, data) {
var deferred = $q.defer();
var responsePromise = $http({
method: 'post',
url: url,
data: data,
headers: {
'Content-Type': 'application/json;charset=utf-8;'
}
})
responsePromise.success(function (data) {
deferred.resolve(data);
});
responsePromise.error(function (err) {
deferred.reject();
});
return deferred.promise;
}
希望这能解决您的问题!
你现在拥有的是一个很好的起点。我假设您的大多数 API 都需要身份验证令牌,因此设置哪些端点不需要身份验证可能是更快的途径。我还没有测试过这个,但它可能会让你走上正轨。我将你的注入器设置为提供者,这样你就可以在配置文件中配置匿名路由规则。
angular.module('App')
.provider('sessionInjector',[function () {
var _anonymousRouteRules;
this.$get = ['$injector', getSessionInjector];
this.setupAnonymousRouteRules = setupAnonymousRouteRules;
function getSessionInjector($injector) {
var service = {
request: requestTransform,
response: responseTransform
};
function requestTransform(config) {
if (!isAnonymousRoute(config.url)){
config.headers['Authorization'] = localStorage.getItem('token');
}
config.headers['Content-Type'] = 'application/json;charset=utf-8;';
return config;
}
function responseTransform(response) {
if (response.status === 401) {
var stateService = $injector.get('$state');
stateService.go('login');
}
return response || $q.when(response);
}
return service;
}
function isAnonymousRoute(url) {
var isAnonymous = false;
angular.forEach(_anonymousRouteRules, function(rule) {
if(rule.test(url)) {
isAnonymous = true;
}
});
return isAnonymous;
}
function setupAnonymousRouteRules(anonymousRouteRules) {
_anonymousRouteRules = anonymousRouteRules;
}
}]);
有了这个,您可以通过为您的网址传入一组正则表达式来配置规则:
angular.module('App').config(['sessionInjectorProvider', config]);
function config(sessionInjectorProvider) {
sessionInjectorProvider.setupAnonymousRouteRules([
/.*\.html$/,
/^\/login$/
]);
}
起初我有 configAuth
和 headers,包括每个控制器的 JWT 令牌。
var configAuth = {
headers: {
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('token')
}
};
但现在当我拥有大量控制器时,我意识到我需要为此做点什么。我听说过 interceptors
并试图得到它们。
我知道我不能只为每个请求添加令牌,因为有些页面和请求(例如 /login
根本不应该有 Authorization
令牌。使用 Authorization header
获取 html 文件不知何故给了我一个例外。所以我试过这样拆分请求:
angular.module('App')
.factory('sessionInjector',['$injector', function ($injector) {
var sessionInjector = {
request: function (config) {
if (config.url == "/one" || config.url == "/two"){
config.headers['Content-Type'] = 'application/json;charset=utf-8;';
config.headers['Authorization'] = localStorage.getItem('token');
} else {
config.headers['Content-Type'] = 'application/json;charset=utf-8;';
}
return config;
},
response: function(response) {
if (response.status === 401) {
var stateService = $injector.get('$state');
stateService.go('login');
}
return response || $q.when(response);
}
};
return sessionInjector;
}]);
但它不适用于 /one/{one_id}
之类的请求,而且我无法对所有可能性进行硬编码。那么最佳做法是什么?
有更好的方法可以做到这一点。登录后将身份验证令牌设置到 $http 服务的 header 中。这样你就不需要在每次调用时都传递配置object。
登录:
function Login(credentials){
$http.post(apiPath, credentials).then(function (data) {
$http.defaults.headers.common['Authorization'] = data['token'];
});
}
在此之后的所有 HTTP 调用都将设置授权 header。
但是有些调用不需要授权,在这些情况下你可以编写一个函数,它有自己的配置 object 在 header.
中未经授权传递未经授权的功能:
function Without_Auth(url, data) {
var deferred = $q.defer();
var responsePromise = $http({
method: 'post',
url: url,
data: data,
headers: {
'Content-Type': 'application/json;charset=utf-8;'
}
})
responsePromise.success(function (data) {
deferred.resolve(data);
});
responsePromise.error(function (err) {
deferred.reject();
});
return deferred.promise;
}
希望这能解决您的问题!
你现在拥有的是一个很好的起点。我假设您的大多数 API 都需要身份验证令牌,因此设置哪些端点不需要身份验证可能是更快的途径。我还没有测试过这个,但它可能会让你走上正轨。我将你的注入器设置为提供者,这样你就可以在配置文件中配置匿名路由规则。
angular.module('App')
.provider('sessionInjector',[function () {
var _anonymousRouteRules;
this.$get = ['$injector', getSessionInjector];
this.setupAnonymousRouteRules = setupAnonymousRouteRules;
function getSessionInjector($injector) {
var service = {
request: requestTransform,
response: responseTransform
};
function requestTransform(config) {
if (!isAnonymousRoute(config.url)){
config.headers['Authorization'] = localStorage.getItem('token');
}
config.headers['Content-Type'] = 'application/json;charset=utf-8;';
return config;
}
function responseTransform(response) {
if (response.status === 401) {
var stateService = $injector.get('$state');
stateService.go('login');
}
return response || $q.when(response);
}
return service;
}
function isAnonymousRoute(url) {
var isAnonymous = false;
angular.forEach(_anonymousRouteRules, function(rule) {
if(rule.test(url)) {
isAnonymous = true;
}
});
return isAnonymous;
}
function setupAnonymousRouteRules(anonymousRouteRules) {
_anonymousRouteRules = anonymousRouteRules;
}
}]);
有了这个,您可以通过为您的网址传入一组正则表达式来配置规则:
angular.module('App').config(['sessionInjectorProvider', config]);
function config(sessionInjectorProvider) {
sessionInjectorProvider.setupAnonymousRouteRules([
/.*\.html$/,
/^\/login$/
]);
}