Angular拦截器实现REST认证

在RESTful风格的系统中,由于后端没有session等持续性状态信息,所以每次前端的请求都必须携带认证信息。
那我们就需要一个全局的统一处理,来为请求加上认证所需的信息。
以下是我的实现方法:

在Angular中可选的方法有两种:

  • 自己实现一个Http拦截器
  • 在官方Http模块的基础上封装自己的Http服务

自己实现一个Http拦截器

定义自己的拦截器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//http-interceptor.ts
@Injectable()
export class HttpInterceptor {
beforeRequest(request:Request):Request{
console.log(request);
return request;
}
afterResponse(res:Observable<Response>):Observable<any>{
res.subscribe((data)=> {
console.log(date);
});
return res;
}
}

这里提供两个方法,分别对请求和响应进行处理。
for example:添加统一的请求头、对结果进行预处理和错误进行全局统一处理

实现ConnectionBackend抽象类

Angular的HTTP服务默认调用XHRBackend作为第一个参数构建的
所以我们需要自己重新封装XHRBackend服务,在其中对HttpInterceptor的方法进行调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//http-interceptor-backend.ts
@Injectable()
export class HttpInterceptorBackend implements ConnectionBackend{
//注入XHRBackend,和我们定义的HttpInterceptor
constructor(private _httpInterceptor:HttpInterceptor,private _xhrBackend:XHRBackend) { }
createConnection(request:Request):XHRConnection{
let interceptor =this._httpInterceptor;
//请求发出前拦截请求并调用interceptor进行处理
let req=interceptor.beforeRequest ? interceptor.beforeRequest(request):request;
//通过XHRBackend对象新建XHRConnection实例
let result=this._xhrBackend.createConnection(req);
//拦截响应并调用interceptor进行处理
result.response=interceptor.afterResponse ? interceptor.afterResponse(result.response):result.response;
return result;
}
}

封装Http工厂

这里就体现出依赖注入的好处了,在不改变原有代码的基础上就能替换掉Http提供类,避免了大面积重构。

1
2
3
4
5
6
//http-factory.ts
export function HttpFactory(httpInterceptorBackend:HttpInterceptorBackend,requestOptions:RequestOptions):Http{
console.log('Http拦截器生效');
return new Http(httpInterceptorBackend,requestOptions);
}

在appModule中声明提供器即可

1
2
3
4
5
6
7
providers: [
HttpInterceptor,
HttpInterceptorBackend,
{provide:Http,
useFactory:HttpFactory,
deps:[HttpInterceptorBackend,RequestOptions]}
]

http拦截器配置完成

接下来就只需要通过拦截器向请求头添加认证信息就好了
我自己的后端使用的是shiro进行授权认证,前端的实现思路很简单

1
2
用户提交登录信息->服务器验证通过->将认证信息写入到AuthorizationService->
每次请求时拦截器调用AuthorizationService获取并添加认证信息

通过配置路由守卫实现AuthorizationService中认证信息为空时路由到401页面,服务器返回401时通过拦截器路由到401页面


封装自己的Http服务

在http模块的Request方法基础上进行封装
此方法优点在于可以单独对get,put,post,delete等请求单独定义预处理方法
缺点在于使用不方便,可能需要大量重构,因为自己封装的HttpService依赖于官方的Http模块,
而如果以Http作为提供器的名称的话无法正常引用官方的模块
具体实现就不写了
有好的方法解决使用不便的问题的话欢迎指教~