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

Pao*_*fan 16 csrf typescript x-xsrf-token angular angular6

我已经阅读关于SO 的文档和所有相关问题,但是Angular的XSRF机制仍然不适合我:我绝不能自动附加X-XSRF-TOKEN标头发出POST请求.

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

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

在此输入图像描述

我的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 {
}
Run Code Online (Sandbox Code Playgroud)

然后,在Service的方法中,我正在进行以下http请求(this.http是一个实例HttpClient):

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

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

Pao*_*fan 28

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

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

  • 路径= /
  • httpOnly = false(这非常重要,完全没有记录)

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

参考:这个Angular Github问题

  • 除上述内容外:-未为GET或HEAD请求设置标头-cookie的名称必须为:XSRF-TOKEN(除非覆盖默认名称)-最重要的是确保您未使用绝对路径。意思是指以HTTP或HTTPS开头的路径。它必须是相对路径。 (5认同)

Leo*_*Leo 21

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

所以不要使用绝对路径,如:

this.http.post<any>("https://example.com/api/endpoint",data)
Run Code Online (Sandbox Code Playgroud)

this.http.post<any>("api/endpoint",data)
Run Code Online (Sandbox Code Playgroud)

或使用

this.http.post<any>("//example.com/api/endpoint",data)
Run Code Online (Sandbox Code Playgroud)

这是因为 HttpClientXsrfModule 上的 Angular 代码显式忽略了绝对路径(请参阅


Ana*_*kzz 6

稍微偏离主题,但对于来到这里的其他人,我在后端解决了以下问题(对于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;
    }
Run Code Online (Sandbox Code Playgroud)


Sau*_*lik 6

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

其他解决方案都不适合我们。


小智 6

你应该把这个服务放在前端{ withCredentials: true }

前任:

this.http.put<class>(url, body, { withCredentials: true });
Run Code Online (Sandbox Code Playgroud)