Angular 6不会将X-XSRF-TOKEN标头添加到http请求

时间:2018-05-24 13:46:40

标签: angular csrf angular6 x-xsrf-token

我已经阅读了the docs以及关于SO的所有相关问题,但Angular的XSRF机制仍然无效:我绝不能在附加X-XSRF-TOKEN标头的情况下发出POST请求自动。

我有一个带登录表单的Angular 6应用程序。

它是Symfony(PHP 7.1)网站的一部分,Angular应用程序页面,当从Symfony提供时,发送正确的Cookie(XSRF-TOKEN):

enter image description here

我的app.module.ts包含正确的模块:

// other imports...
import {HttpClientModule, HttpClientXsrfModule} from "@angular/common/http";

// ...
@NgModule({
  declarations: [
    // ...
  ],
  imports: [
    NgbModule.forRoot(),
    BrowserModule,
    // ...
    HttpClientModule,
    HttpClientXsrfModule.withOptions({
      cookieName: 'XSRF-TOKEN',
      headerName: 'X-CSRF-TOKEN'
    }),
    // other imports
  ],
  providers: [],
  entryComponents: [WarningDialog],
  bootstrap: [AppComponent]
})
export class AppModule {
}

然后,在Service的方法中,我正在发出以下http请求(this.httpHttpClient的实例):

this.http
    .post<any>('api/login', {'_username': username, '_pass': password})
    .subscribe(/* handler here */);

post请求永远不会发送X-XSRF-TOKEN标头。为什么呢?

7 个答案:

答案 0 :(得分:15)

问题再一次是Angular糟糕的文档。

事实是,Angular只会在服务器端生成X-XSRF-TOKEN Cookie时使用以下选项添加XSRF-TOKEN标题

  • 路径= /
  • httpOnly = false(这非常重要,完全无证件

此外,Angular应用程序和被调用的URL必须位于同一服务器上。

参考:this Angular Github issue

答案 1 :(得分:5)

在我的团队中,问题在于我们使用的是绝对路径而不是相对路径。

因此请勿使用绝对路径,例如:

this.http.post<any>("https://example.com/api/endpoint",data)

使用

this.http.post<any>("api/endpoint",data)

或使用

this.http.post<any>("//example.com/api/endpoint",data)

这是因为HttpClientXsrfModule(see)上的Angular代码明确地忽略了绝对路径

答案 2 :(得分:3)

稍微偏离主题,但对于其他来这里的人,我通过以下方式(针对spring-boot)解决了该问题

     /**
     * CORS config - used by cors() in configure() DO NOT CHANGE the METDHO NAME
     * 
     * @return
     */
    @Bean()
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Lists.newArrayList("http://localhost:4200"));
        configuration.setAllowedMethods(Lists.newArrayList("GET", "POST", "OPTIONS"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Lists.newArrayList("x-xsrf-token", "XSRF-TOKEN"));
        configuration.setMaxAge(10l);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

答案 3 :(得分:1)

确保您的服务器在browser requests OPTIONS method时允许X-CSRF-Token标题。

示例:

Access-Control-Allow-Headers: X-CSRF-Token, Content-Type

参考:MDN Docs

答案 4 :(得分:1)

经过无数小时的努力,对我们有用的解决方案是将请求(以Angular形式)从“ https://example.com”更改为“ //example.com”。

没有其他解决方案对我们有用。

答案 5 :(得分:1)

您应该将此{ withCredentials: true }

放在前端的服务上

例如:

this.http.put<class>(url, body, { withCredentials: true });

答案 6 :(得分:1)

    request = request.clone({
        withCredentials: true
      });

在InterceptService中,这与我一起工作