简体   繁体   中英

Handling CORS and CSRF between Spring Boot and Angular

I have a Spring Boot back-end application that runs on port 8888 and an Angular front-end app that runs on 4200.

In my Spring Boot application i've defined the following bean to handle CORS:

@Bean
public WebMvcConfigurer webMvcConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**");
        }
    };
}

And my HttpSecurity configuration looks like this:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors()
        .and()
        .csrf().disable()
        // ... the rest of the config
}

With this configuration everything works fine, i can successfully call my API from the Angular app.

But i would like to enable CSRF, so i've changed the security config to the following:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors()
        .and()
        .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        // ... the rest of the config
}

And i've added the following HttpInterceptor to my Angular app:

constructor(private tokenExtractor: HttpXsrfTokenExtractor) { }

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = this.tokenExtractor.getToken();
    if (token) {
        req = req.clone({ setHeaders: { 'X-XSRF-TOKEN': token } });
    }
    return next.handle(req);
}

The problem is tokenExtractor.getToken() always returns null .

The corresponding request and response headers look like this:

在此处输入图像描述

The XSRF-TOKEN response cookie is present.

I cannot figure out what the problem is.

I've tried importing the HttpClientXsrfModule in my Angular app, but it doesn't make any difference.

I'd really appreciate any advice.

No need. You can use chrome nosecurity or install Allow-Control-Allow-Origin plugin is ok to resolve the problem.

I'm using this code in my Spring Boot apps and it works great with Angular

@Component public class SimpleCORSFilter implements Filter {

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

Hope it helps :)

as said in the documentation [ ...you can enable cross-origin resource sharing (CORS) from either in individual controllers or globally...]

  • Controller Method CORS Configuration: can be enabled using @CrossOrigin annotation
  • Global CORS configuration:
@Configuration
public class CorsConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer(){
        return new WebMvcConfigurer(){
            @Override
            public void addCorsMappings(CorsRegistry registry){

                registry.addMapping("/**")
                        .allowedOrigins("*")
                        .allowedMethods("*")
                        .allowedHeaders("*").maxAge(3600);

            }
        };
    }
}

In fact Spring handles the server side implementation here. All you have to do is add the .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) config, as you did.

The security pattern that Spring implements for you here, is the "cookie-to-header" pattern. Spring adds a cookie named XSRF-TOKEN to the response of your GET request. Let's say the value is aa5f7a64-cf4d-4706-b5aa-bcdec2b41798 .

When you try to do a POST request, Spring will return a 403 Forbidden , unless you add a header with key X-XSRF-TOKEN and the value of the cookie you got from the GET request. For our example, that would be aa5f7a64-cf4d-4706-b5aa-bcdec2b41798 .

Spring will check whether the value of the cookie and of the header are the same. Only if they are the same, the request will pass. Otherwise you get a 403 Forbidden .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM