Angular6 不在http请求中添加X-XSRF-TOKENheader
Angular 6 does not add X-XSRF-TOKEN header to http request
我已经阅读了 the docs 以及关于 SO 的所有相关问题,但是 Angular 的 XSRF 机制仍然不适合我:我决不能制作 POST 请求自动附加 X-XSRF-TOKEN header。
我有一个带有登录表单的 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 {
}
然后,在服务的方法中,我发出了以下 http 请求(this.http
是 HttpClient
的一个实例):
this.http
.post<any>('api/login', {'_username': username, '_pass': password})
.subscribe(/* handler here */);
post 请求从不发送 X-XSRF-TOKEN header。为什么?
确保您的服务器允许 X-CSRF-Token
headers 在 browser requests OPTIONS
method.
时启用
示例:
Access-Control-Allow-Headers: X-CSRF-Token, Content-Type
参考:MDN Docs
问题又是 Angular 的糟糕文档。
事实是,Angular 将添加 X-XSRF-TOKEN
header 仅当 生成 XSRF-TOKEN
cookie server-side 具有以下选项:
- 路径=
/
- httpOnly =
false
(这很重要,完全未记录)
此外,Angular应用程序和被调用的URL应用程序必须位于同一台服务器上。
稍微偏离主题,但对于来到这里的其他人,我通过以下方式在后端解决了这个问题(对于 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;
}
经过无数小时的努力,对我们有用的解决方案是将请求(在 Angular 中)从“https://example.com”更改为“//example.com”。
None 其他解决方案对我们有用。
你应该把这个服务放在前端{ withCredentials: true }
例如:
this.http.put<class>(url, body, { withCredentials: true });
在我的团队中,问题是我们使用的是绝对路径而不是相对路径。
所以不要使用绝对路径,例如:
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 代码显式忽略
request = request.clone({
withCredentials: true
});
在 InterceptService 中,这对我有用
对于 Spring 引导用户,下面的内容花了我一段时间:
Besides, the Angular app and the URL being called must reside on the
same server.
我在我的本地主机上用不同端口上的应用程序测试我的解决方案,它的工作原理就像是同源的。
但问题发生在我更改上下文路径后:/api
这与原点不同,这就是为什么我认为 Angular 不会向请求添加 XSRF
令牌,所以我需要添加:
final CookieCsrfTokenRepository cookieCsrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
cookieCsrfTokenRepository.setCookiePath("/");
设置同源
Here is complex solution for diffrent context-path
我已经阅读了 the docs 以及关于 SO 的所有相关问题,但是 Angular 的 XSRF 机制仍然不适合我:我决不能制作 POST 请求自动附加 X-XSRF-TOKEN header。
我有一个带有登录表单的 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 {
}
然后,在服务的方法中,我发出了以下 http 请求(this.http
是 HttpClient
的一个实例):
this.http
.post<any>('api/login', {'_username': username, '_pass': password})
.subscribe(/* handler here */);
post 请求从不发送 X-XSRF-TOKEN header。为什么?
确保您的服务器允许 X-CSRF-Token
headers 在 browser requests OPTIONS
method.
示例:
Access-Control-Allow-Headers: X-CSRF-Token, Content-Type
参考:MDN Docs
问题又是 Angular 的糟糕文档。
事实是,Angular 将添加 X-XSRF-TOKEN
header 仅当 生成 XSRF-TOKEN
cookie server-side 具有以下选项:
- 路径=
/
- httpOnly =
false
(这很重要,完全未记录)
此外,Angular应用程序和被调用的URL应用程序必须位于同一台服务器上。
稍微偏离主题,但对于来到这里的其他人,我通过以下方式在后端解决了这个问题(对于 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;
}
经过无数小时的努力,对我们有用的解决方案是将请求(在 Angular 中)从“https://example.com”更改为“//example.com”。
None 其他解决方案对我们有用。
你应该把这个服务放在前端{ withCredentials: true }
例如:
this.http.put<class>(url, body, { withCredentials: true });
在我的团队中,问题是我们使用的是绝对路径而不是相对路径。
所以不要使用绝对路径,例如:
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 代码显式忽略 request = request.clone({
withCredentials: true
});
在 InterceptService 中,这对我有用
对于 Spring 引导用户,下面的内容花了我一段时间:
Besides, the Angular app and the URL being called must reside on the same server.
我在我的本地主机上用不同端口上的应用程序测试我的解决方案,它的工作原理就像是同源的。
但问题发生在我更改上下文路径后:/api
这与原点不同,这就是为什么我认为 Angular 不会向请求添加 XSRF
令牌,所以我需要添加:
final CookieCsrfTokenRepository cookieCsrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
cookieCsrfTokenRepository.setCookiePath("/");
设置同源
Here is complex solution for diffrent context-path