angular 拦截器

介绍:$http service在Angular中用于简化与后台的交互过程,其本质上使用XMLHttpRequestJSONP进行与后台的数据交互。在与后台的交互过程中,可能会对每条请求发送到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.‘);
});
时间: 2024-10-23 09:19:51

angular 拦截器的相关文章

ionic之angular拦截器

ionic作为应用,肯定和服务器有数据交换,分散处理api太繁琐,所以一般用拦截器来集中处理. 主要由以下几个方面的应用: 服务器地址注入 错误处理 token注入 日志处理 无token时跳转至登录页面 ... 有四个方法 request: function(config) requestError: function(config) response: function(response) responseError: function(response) 基本看方法名称就知道其意义.具体的

angular之interceptors拦截器

<!DOCTYPE html> <html ng-app="nickApp"> <head> <meta charset="UTF-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <title&g

Angular http 拦截器

Angular http的拦截器一般用来处理每个http都需要添加的参数或者是统一处理错误信息 Angular1.x的http拦截器处理: $httpProvider.interceptors.push(function ($q) { return { request: function (config) { var url = config.url; //这个token表示是在登录状态, 不要用在header中,options无法设置header if(TASApp["x-auth-token

(转)Angular中的拦截器Interceptor

什么是拦截器? 异步操作 例子 Session 注入(请求拦截器) 时间戳(请求和响应拦截器) 请求恢复 (请求异常拦截) Session 恢复 (响应异常拦截器) 转之:http://my.oschina.net/ilivebox/blog/290881?p=1 原文:Interceptors in AngularJS and Useful Examples $httpAngularJS 的 $http 服务允许我们通过发送 HTTP 请求方式与后台进行通信.在某些情况下,我们希望可以俘获所有

angular http interceptors 拦截器使用分享

拦截器 在开始创建拦截器之前,一定要了解 $q和延期承诺api 出于全局错误处理,身份验证或请求的任何同步或异步预处理或响应的后处理目的,希望能够在将请求移交给服务器之前拦截请求,并在将请求移交给服务器之前将响应拦截发起这些请求的应用程序代码-拦截器利用promise api满足同步和异步预处理的需求. 拦截器是$httpProvider通过将它们添加到$httpProvider.interceptors数组而向其注册的服务工厂.调用工厂并注入依赖项(如果指定),并返回拦截器. 有两种拦截器(和

关于angularJs的拦截器的使用

拦截器,在JavaScript中就是拦截http请求.它不仅可以拦截request,还可以拦截response. 拦截request是为了在请求发送前设置一些配置,比如在header中添加一些信息.如果每个请求都要添加一些配置数据,就可以使用request拦截.拦截response是为了在获得服务器返回的数据后,ajax处理数据前先对数据做一些处理,这样就不需要在每一次ajax中处理了,减少代码量. 具体的看下面的例子: angular.module('demo') //this service

AngularJs HTTP响应拦截器实现登陆、权限校验

$httpAngularJS 的 $http 服务允许我们通过发送 HTTP 请求方式与后台进行通信.在某些情况下,我们希望可以俘获所有的请求,并且在将其发送到服务端之前进行操作.还有一些情况是,我们希望俘获响应,并且在完成完成调用之前处理它.一个很好例子就是处理全局 http 异常.拦截器(Interceptors)应运而生.本文将介绍 AngularJS 的拦截器,并且给几个有用的例子. 什么是拦截器? $httpProvider 中有一个 interceptors 数组,而所谓拦截器只是一

AngularJS 拦截器和应用例子(转)

$httpAngularJS 的 $http 服务允许我们通过发送 HTTP 请求方式与后台进行通信.在某些情况下,我们希望可以俘获所有的请求,并且在将其发送到服务端之前进行操作.还有一些情况是,我们希望俘获响应,并且在完成完成调用之前处理它.一个很好例子就是处理全局 http 异常.拦截器(Interceptors)应运而生.本文将介绍 AngularJS 的拦截器,并且给几个有用的例子. 什么是拦截器? $httpProvider 中有一个 interceptors 数组,而所谓拦截器只是一

AngularJS 拦截器

在需要进行身份验证时,在请求发送给服务器之前或者从服务器返回时对其进行拦截,是比较好的实现手段. 例如,对于身份验证,如果服务器返回401状态码,将用户重定向到登录页面. AngularJS通过拦截器提供了一个从全局层面对响应进行处理的途径. 拦截器是$http服务的基础中间件,用来向应用的业务流程中注入新的逻辑. 一共有四种拦截器,两种成功,两种失败. request AngularJS通过$http设置对象来对请求拦截器进行调用. response requestError response