angular 拦截器
介绍:$http service
在Angular中用于简化与后台的交互过程,其本质上使用XMLHttpRequest或JSONP进行与后台的数据交互。在与后台的交互过程中,可能会对每条请求发送到Server之前进行预处理(如加入token),或者是在Server返回数据到达客户端还未被处理之前进行预处理(如将非JSON格式数据进行转换);当然还有可能对在请求和响应过程过发生的问题进行捕获处理。所有这些需求在开发中都非常常见,所以Angular为我们提供了$http拦截器,用来实现上述需求。
Angular的$http拦截器是通过$httpProvider.interceptors
数组定义的一组拦截器,每个拦截器都是实现了某些特定方法的Factory:
实现:
http拦截器一般通过定义factory的方式实现:
myApp.factory('MyInterceptor', function($q) {return {
// 可选,拦截成功的请求
request: function(config) {// 进行预处理// ...return config || $q.when(config);
},
// 可选,拦截失败的请求
requestError: function(rejection) {// 对失败的请求进行处理// ...if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
},
// 可选,拦截成功的响应
response: function(response) {// 进行预处理// ....return response || $q.when(reponse);
},
// 可选,拦截失败的响应
responseError: function(rejection) {// 对失败的响应进行处理// ...if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
}
};
});
随后,我们需要将实现的拦截器加入到$httpProvider.interceptors
数组中,此操作一般在config方法中进行:
myApp.config(function($httpProvider) {
$httpProvider.interceptors.push(MyInterceptor);
});
当然,我们也可以通过匿名factroy的方式实现:
$httpProvider.interceptors.push(function($q) {return {
request: function(config) {// bala
},
response: function(response) {// bala
},
// bala
};
});
可以看到,每个拦截器都可以实现4个可选的处理函数,分别对应请求(成功/失败)和响应(成功/失败)的拦截:
request
:此函数在$http向Server发送请求之前被调用,在此函数中可以对成功的http请求进行处理,其包含一个http config对象作为参数,这里对config对象具有完全的处理权限,甚至可以重新构造,然后直接返回此对象或返回包含此对象的promise即可。如果返回有误,会造成$http请求失败。如开发中经常需要在请求头中加入token以便验证身份,我们可以作如下处理:
request: function(config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers['X-Access-Token'] = $window.sessionStorage.token;
}
return config || $q.when(config);
}
requestError
:此方法会在前一个拦截器抛出异常或进行了reject操作时被调用,在这里可以进行恢复请求的操作,或者进行一些对于请求时发起动作的处理(如取消loading等);response
:此函数在$http从Server接收到响应时被调用,在此函数中可以对成功的http响应进行处理,这里具有对响应的完全处理权限,甚至可以重新构造,然后直接返回响应或返回包含响应的promise即可。如果返回有误,会造成$http接收响应失败;responseError
:此方法会在前一个拦截器抛出异常或进行了reject操作时被调用,在这里可以进行恢复响应的操作,进行一些针对错误的处理
使用用例
利用request拦截器模拟实现Angular的XSRF(即CSRF)防御
CSRF,即“跨站请求伪造”,不过不知道为什么Angular将其称为XSRF。当处理与后台交互时,Angular的$http会尝试从客户端cookie中读取一个token,其默认的key为XSRF-TOKEN
,并构造一个名为X-XSRF-TOKEN
的http头部,与http请求一起发送到后台。Server端就可以根据此token识别出请求来源于同域,当然跨域的请求$http不会加入X-XSRF-TOKEN
头部。那我们可以利用request拦截器通过如下方式在同域请求头部中加入此头部以达到模拟Angular的XSRF(即CSRF)防御机制的实现效果:
/**
* 正式开发中Angular会主动进行XSRF防御(只要cookie中存在key为`XSRF-TOKEN`的token),
* 一般不需要手动进行,除非cookie中不存在key为`XSRF-TOKEN`的token,这里只是模拟实现
*/
request: function(config) {
if(config.url.indexOf('SAME_DOMAIN_API_URL') > -1) {
config.headers['X-XSRF-TOKEN'] = $cookies.get('XSRF-TOKEN');
}
return config;
}
如果初始http请求头部类似于:
"headers": {
"Accept": "application/json, text/plain, */*"
}
那么经过上述的拦截器后,其http请求头部就变成了:
"headers": {
"Accept": "application/json, text/plain, */*",
"X-XSRF-TOKEN": X-XSRF-TOKEN-VALUE
}
利用response拦截器模拟实现Angular JSON易损性(JSON vulnerability)防御
Angular在$http请求安全性方面不仅为我们设计了XSRF(CSRF)防御,而且针对请求JSON数据的Url可能通过类似于<script>
标签加载的方式被恶意网站获取到我们的JSON数据的情况,设计了Angular JSON易损性(JSON vulnerability)防御,即Server端返回的JSON数据头部可以添加")]}',\n"
字符串,得到包含此前缀的响应数据后,Angular会将此前缀删去,将响应还原成正式的JSON数据。此时我们就可以通过response拦截器模拟此过程:
response: function(response) {
var data = examineJSONResponse(response); // 假设存在这样一个方法
if(!data) {
response = validateJSONResponse(response); // 假设存在这样一个方法
}
return response || $q.when(reponse);
}
利用request拦截器和response拦截器计算http请求耗时
这个需求可能在开发中并不常用,这里只是作为同时使用request拦截器和response拦截器的例子,我们可以在request拦截器和response拦截器中分别计时,然后求得其差值即可:
myApp.factory('timestampMarker', [function() {
return {
request: function(config) {
config.requestTimestamp = new Date().getTime();
return config;
},
response: function(response) {
response.config.responseTimestamp = new Date().getTime();
return response;
}
};
}]);
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('timestampMarker');
}]);
这样我们在每次请求后台时,就能够计算出相应请求的耗时了,如:
$http.get('https://api.github.com/users/liuwenzhuang/repos').then(function(response) {
var time = response.config.responseTimestamp - response.config.requestTimestamp;
console.log('The request took ' + (time / 1000) + ' seconds.');
});
http拦截器一般通过定义factory的方式实现:
myApp.factory('MyInterceptor', function($q) {
return {
// 可选,拦截成功的请求
request: function(config) {
// 进行预处理
// ...
return config || $q.when(config);
},
// 可选,拦截失败的请求
requestError: function(rejection) {
// 对失败的请求进行处理
// ...
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
},
// 可选,拦截成功的响应
response: function(response) {
// 进行预处理
// ....
return response || $q.when(reponse);
},
// 可选,拦截失败的响应
responseError: function(rejection) {
// 对失败的响应进行处理
// ...
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
}
};
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
随后,我们需要将实现的拦截器加入到$httpProvider.interceptors
数组中,此操作一般在config方法中进行:
myApp.config(function($httpProvider) {
$httpProvider.interceptors.push(MyInterceptor);
});
- 1
- 2
- 3
- 1
- 2
- 3
当然,我们也可以通过匿名factroy的方式实现:
$httpProvider.interceptors.push(function($q) {
return {
request: function(config) {
// bala
},
response: function(response) {
// bala
},
// bala
};
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
可以看到,每个拦截器都可以实现4个可选的处理函数,分别对应请求(成功/失败)和响应(成功/失败)的拦截:
request
:此函数在$http向Server发送请求之前被调用,在此函数中可以对成功的http请求进行处理,其包含一个http config对象作为参数,这里对config对象具有完全的处理权限,甚至可以重新构造,然后直接返回此对象或返回包含此对象的promise即可。如果返回有误,会造成$http请求失败。如开发中经常需要在请求头中加入token以便验证身份,我们可以作如下处理:
request: function(config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers['X-Access-Token'] = $window.sessionStorage.token;
}
return config || $q.when(config);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
requestError
:此方法会在前一个拦截器抛出异常或进行了reject操作时被调用,在这里可以进行恢复请求的操作,或者进行一些对于请求时发起动作的处理(如取消loading等);response
:此函数在$http从Server接收到响应时被调用,在此函数中可以对成功的http响应进行处理,这里具有对响应的完全处理权限,甚至可以重新构造,然后直接返回响应或返回包含响应的promise即可。如果返回有误,会造成$http接收响应失败;responseError
:此方法会在前一个拦截器抛出异常或进行了reject操作时被调用,在这里可以进行恢复响应的操作,进行一些针对错误的处理。
使用用例
为演示Angular $http拦截器的使用方法,下面通过几个常用的用例来说明:
利用request拦截器模拟实现Angular的XSRF(即CSRF)防御
CSRF,即“跨站请求伪造”,不过不知道为什么Angular将其称为XSRF。当处理与后台交互时,Angular的$http会尝试从客户端cookie中读取一个token,其默认的key为XSRF-TOKEN
,并构造一个名为X-XSRF-TOKEN
的http头部,与http请求一起发送到后台。Server端就可以根据此token识别出请求来源于同域,当然跨域的请求$http不会加入X-XSRF-TOKEN
头部。那我们可以利用request拦截器通过如下方式在同域请求头部中加入此头部以达到模拟Angular的XSRF(即CSRF)防御机制的实现效果:
/**
* 正式开发中Angular会主动进行XSRF防御(只要cookie中存在key为`XSRF-TOKEN`的token),
* 一般不需要手动进行,除非cookie中不存在key为`XSRF-TOKEN`的token,这里只是模拟实现
*/
request: function(config) {
if(config.url.indexOf('SAME_DOMAIN_API_URL') > -1) {
config.headers['X-XSRF-TOKEN'] = $cookies.get('XSRF-TOKEN');
}
return config;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
如果初始http请求头部类似于:
"headers": {
"Accept": "application/json, text/plain, */*"
}
- 1
- 2
- 3
- 1
- 2
- 3
那么经过上述的拦截器后,其http请求头部就变成了:
"headers": {
"Accept": "application/json, text/plain, */*",
"X-XSRF-TOKEN": X-XSRF-TOKEN-VALUE
}
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
利用response拦截器模拟实现Angular JSON易损性(JSON vulnerability)防御
Angular在$http请求安全性方面不仅为我们设计了XSRF(CSRF)防御,而且针对请求JSON数据的Url可能通过类似于<script>
标签加载的方式被恶意网站获取到我们的JSON数据的情况,设计了Angular JSON易损性(JSON vulnerability)防御,即Server端返回的JSON数据头部可以添加")]}',\n"
字符串,得到包含此前缀的响应数据后,Angular会将此前缀删去,将响应还原成正式的JSON数据。此时我们就可以通过response拦截器模拟此过程:
response: function(response) {
var data = examineJSONResponse(response); // 假设存在这样一个方法
if(!data) {
response = validateJSONResponse(response); // 假设存在这样一个方法
}
return response || $q.when(reponse);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
利用request拦截器和response拦截器计算http请求耗时
这个需求可能在开发中并不常用,这里只是作为同时使用request拦截器和response拦截器的例子,我们可以在request拦截器和response拦截器中分别计时,然后求得其差值即可:
myApp.factory('timestampMarker', [function() {
return {
request: function(config) {
config.requestTimestamp = new Date().getTime();
return config;
},
response: function(response) {
response.config.responseTimestamp = new Date().getTime();
return response;
}
};
}]);
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('timestampMarker');
}]);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
这样我们在每次请求后台时,就能够计算出相应请求的耗时了,如:
$http.get('https://api.github.com/users/liuwenzhuang/repos').then(function(response) {
var time = response.config.responseTimestamp - response.config.requestTimestamp;
console.log('The request took ' + (time / 1000) + ' seconds.');
});
angular 拦截器的更多相关文章
- Angular白名单&&Angular拦截器 全局通用
//angular 白名单全局通用 app.config([ '$compileProvider', function ($compileProvider) { $compileProvider.aH ...
- angular 用拦截器统一处理http请求和响应 比如加token
想使用angularjs里的htpp向后台发送请求,现在有个用户唯一识别的token想要放到headers里面去,也就是{headres:{'token':1}} index.html里引入以下js: ...
- angular之interceptors拦截器
<!DOCTYPE html> <html ng-app="nickApp"> <head> <meta charset="UT ...
- angular cli http请求封装+拦截器配置+ 接口配置文件
内容:接口配置文件.http请求封装 .拦截器验证登录 1.接口配置文件 app.api.ts import { Component, OnInit } from '@angular/core'; / ...
- angular中的http拦截器Interceptors
在angularJs中增加了一个对全局的http请求统一做出处理的api--interceptors Interceptors 有两个处理时机,分别是: 其它程序代码执行 HTTP 请求之后,在实际从 ...
- angular http interceptors 拦截器使用分享
拦截器 在开始创建拦截器之前,一定要了解 $q和延期承诺api 出于全局错误处理,身份验证或请求的任何同步或异步预处理或响应的后处理目的,希望能够在将请求移交给服务器之前拦截请求,并在将请求移交给服务 ...
- (转)Angular中的拦截器Interceptor
什么是拦截器? 异步操作 例子 Session 注入(请求拦截器) 时间戳(请求和响应拦截器) 请求恢复 (请求异常拦截) Session 恢复 (响应异常拦截器) 转之:http://my.osch ...
- 通过配置http拦截器,来进行ajax请求验证用户登录的页面跳转
在.NET中验证用户是否登录或者是否过期,若需要登录时则将请求转向至登录页面. 这个流程在进行页面请求时是没问题的,能正确进行页面跳转. 然而在使用xmlhttprequest时,或者jq的getJs ...
- AngularJS 拦截器
在需要进行身份验证时,在请求发送给服务器之前或者从服务器返回时对其进行拦截,是比较好的实现手段. 例如,对于身份验证,如果服务器返回401状态码,将用户重定向到登录页面. AngularJS通过拦截器 ...
随机推荐
- P2473 [SCOI2008]奖励关(期望)
P2473 [SCOI2008]奖励关 $n<=15$,显然的状压 设$f[i][w]$表示前$i$轮,状态$w$的最大期望 蓝后我们发现一个问题:$f[i][w]$可能是非法的 于是我们从$f ...
- 3 字节的 UTF-8 序列的字节 3 无效 解决
参考下列应该可以解决,笔者为3. 1.https://blog.csdn.net/hostel_2/article/details/51517361 2.https://blog.csdn.net/u ...
- opencv学习之路(14)、形态学之膨胀腐蚀
一.膨胀腐蚀概述(对高亮部分进行操作) 二.膨胀 三.腐蚀 四.代码 1.查看结构元素 #include<opencv2/opencv.hpp> #include<iostream& ...
- Codeforces 711D Directed Roads - 组合数学
ZS the Coder and Chris the Baboon has explored Udayland for quite some time. They realize that it co ...
- Codeforces 526F Pudding Monsters - CDQ分治 - 桶排序
In this problem you will meet the simplified model of game Pudding Monsters. An important process in ...
- python操作串口
import serial test = serial.Serial("COM1",115200)#这里就已经打开了串口 print(test.portstr) test.writ ...
- 题解—— 洛谷 p1269 信号放大器(贪心)
深刻的教训,不要写错读入 #include <cstdio> #include <algorithm> using namespace std; ; ; ,u[MAXM],v[ ...
- IDEA入门级使用教程----你怎么还在用eclipse?
http://blog.csdn.net/qq_31655965/article/details/52788374
- 7、nginx的upstream及fastcgi模块应用
ngx_http_proxy_module, ngx_http_upstream_module ngx_http_proxy_module:实现反向代理及缓存功能 proxy_pass http: ...
- BSEG和BSIS、BSAS、BSID、BSAD、BSIK、BSAK 六个表的关系
BSEG和BSIS.BSAS.BSID.BSAD.BSIK.BSAK六个表的关系 1.数据关系: BSAS+BSIS+BSAK+BSIK+BSAD+BSID = BSEG 2.六个表说明: clear ...