SpringBoot后端跨域问题

今天遇到一个问题,我访问同事电脑本地服务时浏览器报跨域错误,而且很奇怪的是 get请求不报错,但是post请求报错,看到跨域,开始挥三板斧

1.前端请求加上请求头:

devServer: {
  port: 8000,
  disableHostCheck: true,
  proxy: {
    '/ac-biz-auth/api': {
      target: 'http://localhost:8088',
      ws: false,
      changeOrigin: true
    }
  },
  headers: {
    'Access-Control-Allow-Origin': '*'
  }
},

结果,不行

2.后端对应controller加上@CrossOrigin注解:

@Controller
@CrossOrigin
@RequestMapping("/" + AcStaticVarBizGwf.MODULE_CODE_AC_BIZ_GWF)
public class AcBizGwfCtl extends BaseCtl {
    @Autowired
    private IAcBizGwfInfoService iPfBizRtFInfoService;
    @Autowired
    private AcBizGwfConfig acBizGwfConfig;

    //    @PreAuth(value = "ac:core:biz:gwf:index", name = "网关引导首页")
    @GetMapping()
    public ModelAndView index(Model model) {
        model.addAttribute(AcStaticVarCoreModuleUi.PUBLIC_PTAH, acBizGwfConfig.publicPath());
        model.addAttribute(AcStaticVarCoreModuleUi.ENABLE_HTTPS, acBizGwfConfig.getEnableHttps());
        return new ModelAndView(AcStaticVarBizGwf.VIEW_AC_BIZ_GWF_INDEX);
    }

    //    @PreAuth(value = "ac:core:biz:gwf:info", name = "获取子应用以及登录信息")
    @GetMapping("/info")
    @ResponseBody
    public AcBizGwfLoginInfoDto info() {
        return iPfBizRtFInfoService.getInfo();
    }
}

结果,不行

3.加上过滤器,统一处理响应:

@Configuration
public class CorsConfig {
    private static final String MAX_AGE = "18000L";

    @Bean
    public WebFilter corsFilter() {
        return (ServerWebExchange ctx, WebFilterChain chain) -> {
            ServerHttpRequest request = ctx.getRequest();
            if (!CorsUtils.isCorsRequest(request)) {
                return chain.filter(ctx);
            }
            HttpHeaders requestHeaders = request.getHeaders();
            ServerHttpResponse response = ctx.getResponse();
            HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
            HttpHeaders headers = response.getHeaders();
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
            headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
            if (requestMethod != null) {
                headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
            }
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
            headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
            headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
            if (request.getMethod() == HttpMethod.OPTIONS) {
                response.setStatusCode(HttpStatus.OK);
                return Mono.empty();
            }
            return chain.filter(ctx);
        };
    }

}

此处标红的代码,实则是根据我们环境设置的,如果放过所有的请求,那么就设置为 “*” 即可

结果,也不生效,因为此处涉及一个大坑:此处这个过滤器我和@CrossOrigin一起用了,如果单独配置这个Filter,实则是可以的

最后,说明一下这次调试遇到的坑: 

Springboot2.x之后,@CrossOrigin注解 的 allowCredentials 默认为 false ,即不支持带认证(令牌)的请求跨域,

正确配置:

@Controller
@CrossOrigin(allowCredentials = "true")
@RequestMapping("/" + AcStaticVarBizGwf.MODULE_CODE_AC_BIZ_GWF)
public class AcBizGwfCtl extends BaseCtl {
    @Autowired
    private IAcBizGwfInfoService iPfBizRtFInfoService;
    @Autowired
    private AcBizGwfConfig acBizGwfConfig;

    //    @PreAuth(value = "ac:core:biz:gwf:index", name = "网关引导首页")
    @GetMapping()
    public ModelAndView index(Model model) {
        model.addAttribute(AcStaticVarCoreModuleUi.PUBLIC_PTAH, acBizGwfConfig.publicPath());
        model.addAttribute(AcStaticVarCoreModuleUi.ENABLE_HTTPS, acBizGwfConfig.getEnableHttps());
        return new ModelAndView(AcStaticVarBizGwf.VIEW_AC_BIZ_GWF_INDEX);
    }

    //    @PreAuth(value = "ac:core:biz:gwf:info", name = "获取子应用以及登录信息")
    @GetMapping("/info")
    @ResponseBody
    public AcBizGwfLoginInfoDto info() {
        return iPfBizRtFInfoService.getInfo();
    }
}

附上一个浏览器测试跨域demo,打开浏览器console控制台:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://172.19.66.187:8095/rebook/ticketfastchange/queryDetails?id=37',true);
xhr.setRequestHeader('content-type', 'application/json');
xhr.setRequestHeader('Authorization', 'Bearer 1a4d3a90-a15e-4200-98fe-e86f6067b3c6');
 //将用户输入值序列化成字符串
xhr.send();
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}
原文地址:https://www.cnblogs.com/linsky/p/14805600.html