好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Angular4---认证---使用HttpClient拦截器,解决循环依赖引用的问题

  在angular4 项目中,每次请求服务端需要添加头部信息AccessToken作为认证的凭据。但如果在每次调用服务端就要写代码添加一个头部信息,会变得很麻烦。可以使用angular4的HttpClient来拦截每个请求,然后在头部添加上信息。

  直接上代码实践

  一、创建拦截器Service,实现HttpInterceptor的 intercept 方法

import { Injectable, Injector}  from   '  @angular/core  '  ;
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse}   from   '  @angular/common/http  '  ;
import {Observable}   from   '  rxjs/Observable  '  ;
import   '  rxjs/add/operator/do  '  ;
import {AuthenticationService}   from   '  ./auth/authentication.service  ' ;  //   用于获得AccessToken的服务类 
import {environment}  from   '  environments/environment  '  ;

  /*  *
 * HTTP拦截器,设置头部信息
   */  
@Injectable()
export   class   BaseHttpInterceptorService implements HttpInterceptor {

  authService: AuthenticationService;
  skipAuth: [  string  ];
  constructor(  private   inject: Injector) {
    //   用户登录或认证请求则不需要添加头部AccessToken信息 
     this .skipAuth =  [
      `${environment.serverUrl} /api/v1/User/ login`,
    ];
  }
    /*  *
   * 拦截器拦截请求
   * @param {HttpRequest<any>} req
   * @param {HttpHandler} next
   * @returns {Observable<HttpEvent<any>>}
     */  
  intercept(req: HttpRequest <any>, next: HttpHandler): Observable<HttpEvent<any>>  {
      this .authService =  this .inject. get  (AuthenticationService); // 注意此句
       const  req_started =  Date.now();
    let authReq;
      /*  *
     * 如果是跳过认证的链接,则不添加头部信息
       */ 
     if  ( this  .isSkipAuth(req.url)) {
      authReq  =  req.clone();
    }  else   {
        const  access_token = `Bearer ${ this .authService.getAccessToken( '  563151811@qq.com  '  )}`;
      authReq  =  req.clone({
        setHeaders: {
          Authorization: access_token
        }
      });
    }
      return  next.handle(authReq). do ( event  =>  {
        if  ( event   instanceof HttpResponse) {
          const  elapsed = Date.now() -  req_started;
        console.log(`Request   for   ${req.urlWithParams} took ${elapsed} ms`);
      }
    });
  }
    /*  
   *是否跳过添加头部认证
    */  
  isSkipAuth(url:   string  ) {
    let isMatch  =  false  ;
      this .skipAuth.forEach((reg_url:  string ) =>  {
        if  ( ! isMatch) {
          if  (url.search(reg_url) >=  0  ) {
          isMatch  =  true  ;
        }
      }
    });
      return   isMatch;
  }
} 

  二、注册拦截器,在APPModule中,添加如下代码

 {
      provide: HTTP_INTERCEPTORS,
      useClass: BaseHttpInterceptorService,  //   上边定义的拦截器名字 
      multi:  true  
    }, 

  三、每个请求服务端数据的Service依赖HttpClient,而不是http。

  那么一个基础的拦截器已经完成了,但是,你会发现调用认证服务Service的时候,会报错: Cyclic dependency error with HttpInterceptor , 如果添加了第一步代码中注意点那段代码后,又会发现OK了。

  这是 依赖注入循环嵌套:A依赖B,B中又引用A。

  官方文档中采用 forwardRef, 但是发现没用。在Stack Overflow中看到有人采用上述方法成功解决问题。 https://github.com/angular/angular/issues/18224

如需要更详细的代码或有问题,请联系我

 

查看更多关于Angular4---认证---使用HttpClient拦截器,解决循环依赖引用的问题的详细内容...

  阅读:42次