CSRF issue while sending POST request from Angular 2 to Spring-backed Java app

人走茶凉 提交于 2019-12-23 01:36:17

问题


I have UI written with Angular 2 and Java based backend that uses OpenID Connect authentication on top of Spring Security.

The authentication works fine but only for GET requests. I'm getting HTTP 403 every time I perform POST, PUT or DELETE methods on a resource:

{
  "status": 403,
  "message": "Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.",
}

I use HttpClient like this:

http.post(
    '/api/my-resource',
    JSON.stringify(myObject),
    new RequestOptions({
        headers: new Headers({'Content-Type': 'application/json'})
    })
)

When I add withCredentials: true to the RequestOptions as proposed here I still get HTTP 403 but with different message:

{
  "status": 403,
  "message": "Could not verify the provided CSRF token because your session was not found.",
}

What do I need to do to make HttpClient work with CSRF?

Note: I also took a look at similar questions, especially angular-2-spring-security-csrf-implementation-problems, but the solutions proposed there do not solve my problem. At the same time I don't want to disable CSRF.


回答1:


Update Angular >= 6

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    HttpClientXsrfModule.withOptions({cookieName: 'XSRF-TOKEN'})
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Original answer

Add the CSRF cookie configuration as below :

@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');
}

And configure Spring security with the correct header name.

    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;
    }

where 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);
    }
}


来源:https://stackoverflow.com/questions/45237003/csrf-issue-while-sending-post-request-from-angular-2-to-spring-backed-java-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!