NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load xxxx错

在开发项目的过程中,和后端对接,我们使用是一个成熟的集成很全面的架构JHipster。后端为java spring-boot 前端ts+react,需求是有一个需要在页面里嵌套iframe的需求。然后在iframe中发起$.ajax请求前端出现了错误如下:

"NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://192.168.31.149:8081/api/concepts/3253'

 

前端代码:

$.ajax({
  url: `${RED.API.schema.URI()}/${conceptIds}`,
  method: "GET",
  async: false,
  crossDomain: true,
  headers: {
  'Access-Control-Allow-Origin': '*',
  accept: 'application/json',
  Authorization: `Bearer ${window.parent.localStorage
    .getItem("jhi-authenticationToken")
    .replace(/\"/g, "")}`,
  },
  success: data => {
    console.log(data)
  },
  error: err => {
    console.error(err)
  },
});

可以看到,只要$.ajax请求打开关闭async开启同步模式则就会无法请求数据。

解决方法:

经过查阅,网上的一些信息。发现大部分解决方案都是吧async改为true就可以了。但我的项目运用里必须使用同步来渲染数据。所以没法改成异步使用。

最后使用docker跑两个容器分别模拟线上和本地的环境。发现请求的请求头里有着如下差异:

经过本地调试,找到静态文件代理模式和本地开发模式的请求响应差异如下: 
【线上的Response Headers】 
Accept-Ranges: bytes 
Cache-Control: no-store 
Connection: keep-alive 
Content-Encoding: gzip 
Content-Language: en- 
Content-Length: 2213 
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: 
Content-Type: text/html;charset=utf-8 
Date: Thu, 18 Jul 2019 06:28:37 GMT 
Feature-Policy: geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none' 
Last-Modified: Thu, 18 Jul 2019 02:03:28 GMT 
Referrer-Policy: strict-origin-when-cross-origin 
Server: nginx/1.17.0 
X-Content-Type-Options: nosniff 
X-Frame-Options: DENY 
X-XSS-Protection: 1; mode=block 


【本地的Response Headers】 
accept-ranges: bytes 
Connection: keep-alive 
Content-Type: text/html; charset=UTF-8 
Date: Thu, 18 Jul 2019 06:40:59 GMT 
etag: W/"16de-hwm87recU2tkzw2pAE/RFVGX6+0" 
Server: nginx/1.17.0 
Transfer-Encoding: chunked 
x-powered-by: Express 

【对比差异】 
线上的多了一下设置: 
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: 
Feature-Policy: geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none' 
Referrer-Policy: strict-origin-when-cross-origin 
X-Content-Type-Options: nosniff 
X-Frame-Options: DENY 
X-XSS-Protection: 1; mode=block

结果是该框架的后端配置了一种叫Content-Security-Policy的xss安全机制,拦截的不安全的请求。随后在java项目里config/SecurityConfiguration.java 注释去掉该响应头的注入即解决问题。

// SecurityConfiguration.java

@Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .csrf()
            .disable()
            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
            .exceptionHandling()
            .authenticationEntryPoint(problemSupport)
            .accessDeniedHandler(problemSupport)
        .and()
            // .headers()
            // .contentSecurityPolicy("default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:")
        // .and()
            // .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
        // .and()
            // .featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none'")
        // .and()
            // .frameOptions()
            // .sameOrigin()
        // .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
            .authorizeRequests()
            .antMatchers("/api/authenticate").permitAll()
            .antMatchers("/api/register").permitAll()
            .antMatchers("/api/activate").permitAll()
            .antMatchers("/api/account/reset-password/init").permitAll()
            .antMatchers("/api/account/reset-password/finish").permitAll()
            .antMatchers("/api/**").authenticated()
            .antMatchers("/management/health").permitAll()
            .antMatchers("/management/info").permitAll()
            .antMatchers("/management/prometheus").permitAll()
            .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
        .and()
            .httpBasic()
        .and()
            .apply(securityConfigurerAdapter());
        // @formatter:on
    }

 

上一篇:并发编程基础进阶(下)


下一篇:C#使用指针详解