我已经阅读了the docs以及关于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 {
}
然后,在Service的方法中,我正在发出以下http请求(this.http
是HttpClient
的实例):
this.http
.post<any>('api/login', {'_username': username, '_pass': password})
.subscribe(/* handler here */);
post请求永远不会发送X-XSRF-TOKEN标头。为什么呢?
答案 0 :(得分:15)
问题再一次是Angular糟糕的文档。
事实是,Angular只会在服务器端生成X-XSRF-TOKEN
Cookie时使用以下选项添加XSRF-TOKEN
标题:
/
false
(这非常重要,完全无证件)此外,Angular应用程序和被调用的URL必须位于同一服务器上。
答案 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中,这与我一起工作