从Angular 2向Spring支持的Java应用程序发送POST请求时出现CSRF问题
我有使用Angular 2和基于Java的后端编写的UI,它在Spring Security之上使用OpenID Connect身份validation。
身份validation工作正常,但仅适用于GET请求。 每次在资源上执行POST,PUT或DELETE方法时,我都会收到HTTP 403:
{ "status": 403, "message": "Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.", }
我像这样使用HttpClient:
http.post( '/api/my-resource', JSON.stringify(myObject), new RequestOptions({ headers: new Headers({'Content-Type': 'application/json'}) }) )
当我添加withCredentials: true
这里提出的RequestOptions,我仍然得到HTTP 403但是有不同的消息:
{ "status": 403, "message": "Could not verify the provided CSRF token because your session was not found.", }
我需要做些什么才能使HttpClient
与CSRF一起工作?
注意:我也看了类似的问题,特别是angular-2-spring-security-csrf-implementation-problems ,但是那里提出的解决方案并没有解决我的问题。 同时我不想禁用CSRF。
添加CSRF
cookie配置如下:
@NgModule({ declarations: [declarations], imports: [imports], providers: [ {provide: XSRFStrategy, useFactory: xsrfFactory} ], bootstrap: [AppComponent] }) export class AppModule { } export function xsrfFactory() { return new CookieXSRFStrategy('XSRF-TOKEN', 'XSRF-TOKEN'); }
并使用正确的标头名称配置Spring安全性。
private static final String CSRF_HEADER_NAME = "XSRF-TOKEN"; @Override protected void configure(HttpSecurity http) throws Exception { http ... .and() .csrf() .ignoringAntMatchers(CSRF_IGNORE) .csrfTokenRepository(csrfTokenRepository()) .and() .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class); } private CsrfTokenRepository csrfTokenRepository() { HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); repository.setHeaderName(CSRF_HEADER_NAME); return repository; }
其中CsrfHeaderFilter :
public class CsrfHeaderFilter extends OncePerRequestFilter { private static final String CSRF_COOKIE_NAME = "XSRF-TOKEN"; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName()); if (csrf != null) { Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME); String token = csrf.getToken(); if (cookie == null || token != null && !token.equals(cookie.getValue())) { cookie = new Cookie(CSRF_COOKIE_NAME, token); cookie.setPath("/"); response.addCookie(cookie); } } filterChain.doFilter(request, response); } }