我有一个angular2应用程序,它与ASP.Net MVC后端通信。
后端需要在AntiForgeryToken
次请求中显示POST
。
为此,我的index.html
提供了隐藏输入,其值代表令牌。我想这是ASP.Net MVC
项目中的一种常见方法(不是这个问题的主题)。
现在抓住这个令牌并在我的请求标题中使用它我在我的main.ts中扩展BaseRequestOptions
,如下所示:
@Injectable()
class AntiForgeryRequestOptions extends BaseRequestOptions {
constructor () {
super();
let xsrfElement = <HTMLInputElement>document.querySelector('[name=__RequestVerificationToken]');
if (xsrfElement) {
let xsrfToken:string = xsrfElement.value;
this.headers.append('X-XSRF-Token', xsrfToken);
}
this.headers.append('Content-Type', 'application/json');
}
}
并将其提供为RequestOptions
,如下所示:
bootstrap(AppComponent, [
...
provide(RequestOptions, {useClass: AntiForgeryRequestOptions}),
...
]);
通过此设置,我可以在我的服务中提出POST
- 请求:
post(url:string, body:any):Observable<any> {
let options = new RequestOptions();
return this._http.post(url, body, options)
.map((response:any) => {
...
})
.catch(this._handleError);
}
工作正常。 POST
正常工作,CSRF Token
随之发送。
今天我不得不调整这一点,因为我必须在某些场合切换出令牌并经历一些我无法解释的奇怪行为:
我的理解是:let options = new RequestOptions()
我应该调用AntiForgeryRequestOptions
的构造函数,并为此RequestOptions
创建标题。但是,如果我在通话后直接进行console.log(options)
,我会看到所有属性都是NULL
甚至标题。 (它仍然有效,CSRF Token
已发送,其content-type
为application/json
)但我无法访问它或更改即将发出的请求。
任何人都可以告诉我为什么会发生这种情况,或者我如何改变我RequestOptions
的构造函数中之前定义的AntiForgeryRequestOptions
?
我有理由这样做。当我开始这个项目时,angular2仍处于beta状态(现在我正在使用angular2 rc1)。当时CSRF Tokens
存在问题,您无法在选项中直接设置它。现在有了新版本,我不需要提供自定义AntiForgeryRequestOptions
。我可以把它留下来,只是在帖子请求中这样做:
post(url:string, body:any):Observable<any> {
let options = new RequestOptions();
options.headers = new Headers();
let xsrfElement = <HTMLInputElement>document.querySelector('[name=__RequestVerificationToken]');
if (xsrfElement) {
let xsrfToken:string = xsrfElement.value;
options.headers.append('X-XSRF-Token', xsrfToken);
}
options.headers.append('Content-Type', 'application/json');
...
}
正如Günther在评论中所说,我必须在我的自定义merge
中使用AntiForgeryRequestOptions
:
@Injectable()
class AntiForgeryRequestOptions extends BaseRequestOptions {
constructor () {
super();
}
merge(options?:RequestOptionsArgs):RequestOptions {
options.headers = new Headers();
let xsrfElement = <HTMLInputElement>document.querySelector('[name=__RequestVerificationToken]');
if (xsrfElement) {
let xsrfToken:string = xsrfElement.value;
options.headers.append('X-XSRF-Token', xsrfToken);
}
options.headers.append('Content-Type', 'application/json');
return super.merge(options);
}
}
哪个有效。现在,每当我调用new RequestOptions()
时,Headers
属性都会正确更新,这意味着无论何时我更改CSRF令牌的隐藏输入字段的值,标题都会按照应有的方式进行调整。
答案 0 :(得分:2)
您需要实现自定义merge(options?: RequestOptionsArgs): RequestOptions { ... }
方法,因为默认实现只是检查标头是否传递给merge(...)
然后采用这些或以其他方式获取当前AntiForgeryRequestOptions
实例的标头但是id实际上并没有合并。
示例(来自问题 - 感谢您的许可)
@Injectable()
class AntiForgeryRequestOptions extends BaseRequestOptions {
constructor () {
super();
}
merge(options?:RequestOptionsArgs):RequestOptions {
options.headers = new Headers();
let xsrfElement = <HTMLInputElement>document.querySelector('[name=__RequestVerificationToken]');
if (xsrfElement) {
let xsrfToken:string = xsrfElement.value;
options.headers.append('X-XSRF-Token', xsrfToken);
}
options.headers.append('Content-Type', 'application/json');
return super.merge(options);
}
}