全局和动态地将标头添加到HTTP请求 - Angular2

时间:2017-05-13 11:50:07

标签: angular http-headers angular-http

我需要将Authorization标头附加到我的Angular2应用程序完成的每个HTTP请求中。

第一个请求是登录请求,它没有授权标头。登录成功后,将从服务器返回一个令牌,我需要将其作为授权头附加到每个后续HTTP请求中。

我从服务器获取令牌没有任何问题。我可以使用angular2应用程序成功登录。但问题是,令牌未附加到后续请求标头。

这是我的实施。

我创建了一个扩展BaseRequestOptions类的CustomRequestOptions类。

@Injectable()
export class CustomRequestOptions extends BaseRequestOptions {
    constructor(private _globals: Globals) {
        super();
        this.headers.append('Content-Type', 'application/json');
    }

    addHeader(headerName: string, headerValue: string) {
       console.log("Custom req options, setting the customer header "+headerName+" , "+headerValue);
       this.headers.append(headerName, headerValue);
    }
}

我已将其添加到@NgModule,以使此CustomRequestOptions为全局。(在所有组件中可见)

@NgModule({
  imports:      [ BrowserModule, HttpModule, routing, FormsModule ],
  declarations: [ AppComponent, TendersComponent, TenderCategoriesComponent, TenderDetailsComponent, PageNotFoundComponent, ConvertUrlPipe ],
  providers   : [ Globals, 
        {provide: RequestOptions, useClass: CustomRequestOptions}
    ],
  bootstrap:    [ AppComponent ]
}) 

现在,在我的组件类中,我在addHeader中调用了CustomRequestOptions方法。

export class LoginComponent {

  private _token: string;
  private _returnMsg: string;

  constructor(private _usersService: UsersService, private _globals: Globals, private _customRequestOptions: CustomRequestOptions) {

  }

  onLoginFormSubmit(formData: any) {

    this._usersService.login(formData.emailAddress, formData.password).subscribe(

      returnRes => {

        this._returnMsg = returnRes.returnMsg;
        this._token = returnRes.token;

        if (this._returnMsg == "SUCCESS") {

          //sucess
          console.log("AUTH SUCCESS");
          let x = "Bearer " + this._token;
          this._customRequestOptions.addHeader("Authorization", x);

          this.getUserRoles(); //this call needs authorization header.

        }

      }

    );

  }

}

即使我使用this._customRequestOptions.addHeader("Authorization", x);设置标头,下一个需要授权标头以便正常工作的调用也会失败。在服务器端,我可以看到,该部分为空。

这里有什么问题?

1 个答案:

答案 0 :(得分:1)

扩展BaseRequestOptions的问题是构造函数只在浏览器的生命周期中运行一次,除此之外,更改不会传播。而且,更改需要在super调用中,如下所示:

super({ 
  method: RequestMethod.Get,
  headers: new Headers({
    'Content-Type': 'application/json',
    'X-Some-Header': 'some-content'
  });
});

super属性的headers之外的操作不起作用。扩展BaseRequestOptions的另一个选择是在模块中执行一次:

class DefaultRequestOptions extends BaseRequestOptions{
    headers:Headers = new Headers({
        'Content-Type': 'poop'
    });
}
....
providers: [{provide: RequestOptions, useClass: DefaultRequestOptions}],

早期版本的Angular2中曾经有一种方法可以访问_defaultOptions上的http对象,但它现在已受到保护且无法访问。它看起来像这样:  this.http._defaultOptions.headers.set('Authorization', 'token');

<强> TLDR;

如果您需要在应用程序的生命周期内更改标题,那么我建议您查看类似https://github.com/auth0/angular2-jwt的内容或将自己的包装器写入http库(类似于angular2-jwt的工作方式) 。我已经编写了自己的分支来处理我的用例,之后我可以说“如果存在某些内容”,那么请执行 x &#39;。如果您决定写信给自己,那并不难,您可以查看https://github.com/auth0/angular2-jwt/blob/master/angular2-jwt.ts#L94的灵感。这将替换@ angular / http。

中的普通http

很抱歉,这可能不是您所寻求的解决方案,但这是我在尝试解决同一挑战时所学到的。希望它能够解释您的代码和潜在解决方案的问题。