【问题标题】:Handling CORS and CSRF between Spring Boot and Angular在 Spring Boot 和 Angular 之间处理 CORS 和 CSRF
【发布时间】:2019-07-31 07:11:33
【问题描述】:

我有一个在端口 8888 上运行的 Spring Boot 后端应用程序和一个在 4200 上运行的 Angular 前端应用程序。

在我的 Spring Boot 应用程序中,我定义了以下 bean 来处理 CORS:

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

而我的HttpSecurity 配置如下所示:

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

使用此配置一切正常,我可以从 Angular 应用程序成功调用我的 API。

但我想启用 CSRF,所以我将安全配置更改为以下内容:

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

我已将以下 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);
}

问题是tokenExtractor.getToken() 总是返回null

相应的请求和响应头如下所示:

XSRF-TOKEN 响应 cookie 存在。

我不知道问题出在哪里。

我尝试在我的 Angular 应用中导入 HttpClientXsrfModule,但没有任何区别。

非常感谢任何建议。

【问题讨论】:

标签: javascript java angular spring spring-boot


【解决方案1】:

如文档中所述 [...您可以在单个控制器或全局范围内启用跨域资源共享 (CORS)...]

  • 控制器方法 CORS 配置:可以使用 @CrossOrigin 注释启用
  • 全局 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);

            }
        };
    }
}

【讨论】:

    【解决方案2】:

    我在我的 Spring Boot 应用程序中使用了这段代码,它与 Angular 配合得很好

    @组件 公共类 SimpleCORSFilter 实现过滤器 {

    @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() {
    }
    

    希望对你有帮助:)

    【讨论】:

      【解决方案3】:

      不需要。您可以使用 chrome nosecurity 或安装 Allow-Control-Allow-Origin 插件来解决问题。

      【讨论】:

      • 我认为规避安全问题是个坏建议;以及如何与应用程序的其他用户一起使用?
      • 我们在开发环境中使用该方法。我们不能在 AT 或生产环境中遇到跨域。
      • 但这不是问题所针对的环境。因此,虽然您的答案可能足以满足您的设置,但它可能无法回答 OP 的问题。
      猜你喜欢
      • 2014-09-15
      • 2021-09-26
      • 2021-10-10
      • 1970-01-01
      • 1970-01-01
      • 2016-05-04
      相关资源
      最近更新 更多