简体   繁体   English

在 Spring Boot 和 Angular 之间处理 CORS 和 CSRF

[英]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.我有一个在端口 8888 上运行的 Spring Boot 后端应用程序和一个在 4200 上运行的 Angular 前端应用程序。

In my Spring Boot application i've defined the following bean to handle CORS:在我的 Spring Boot 应用程序中,我定义了以下 bean 来处理 CORS:

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

And my HttpSecurity configuration looks like this:我的HttpSecurity配置如下所示:

@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.使用此配置,一切正常,我可以从 Angular 应用程序成功调用我的 API。

But i would like to enable CSRF, so i've changed the security config to the following:但我想启用 CSRF,所以我将安全配置更改为以下内容:

@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:我已经将以下HttpInterceptor添加到我的 Angular 应用程序中:

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 .问题是tokenExtractor.getToken()总是返回null

The corresponding request and response headers look like this:相应的请求和响应标头如下所示:

在此处输入图像描述

The XSRF-TOKEN response cookie is present. XSRF-TOKEN响应 cookie 存在。

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.我试过在我的 Angular 应用程序中导入HttpClientXsrfModule ,但这没有任何区别。

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.您可以使用 chrome nosecurity 或安装 Allow-Control-Allow-Origin 插件即可解决问题。

I'm using this code in my Spring Boot apps and it works great with Angular我在我的 Spring Boot 应用程序中使用了这段代码,它与 Angular 配合得很好

@Component public class SimpleCORSFilter implements Filter { @Component 公共类 SimpleCORSFilter 实现 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...]如文档中所述 [...您可以从单个控制器或全局启用跨源资源共享 (CORS)...]

  • Controller Method CORS Configuration: can be enabled using @CrossOrigin annotation控制器方法 CORS 配置:可以使用 @CrossOrigin 注释启用
  • Global CORS configuration:全局 CORS 配置:
@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.事实上,Spring 在这里处理服务器端实现。 All you have to do is add the .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) config, as you did.您所要做的就是像您一样添加.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())配置。

The security pattern that Spring implements for you here, is the "cookie-to-header" pattern. Spring 在这里为您实现的安全模式是“cookie-to-header”模式。 Spring adds a cookie named XSRF-TOKEN to the response of your GET request. Spring 将名为XSRF-TOKEN的 cookie 添加到 GET 请求的响应中。 Let's say the value is aa5f7a64-cf4d-4706-b5aa-bcdec2b41798 .假设值为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.当您尝试执行 POST 请求时,Spring 将返回403 Forbidden ,除非您添加带有键X-XSRF-TOKEN的标头和您从 GET 请求中获得的 cookie 的值。 For our example, that would be aa5f7a64-cf4d-4706-b5aa-bcdec2b41798 .对于我们的示例,这将是aa5f7a64-cf4d-4706-b5aa-bcdec2b41798

Spring will check whether the value of the cookie and of the header are the same. Spring 会检查 cookie 的值和 header 的值是否相同。 Only if they are the same, the request will pass.只有它们相同,请求才会通过。 Otherwise you get a 403 Forbidden .否则你会得到一个403 Forbidden

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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