• 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);
    }
  • 相关阅读:
    GET和POST区别
    es索引介绍
    前端 用法记录
    axios 使用
    react技巧 学习
    vuex 学习笔记
    fetch 学习笔记
    react-router 4.0 学习笔记
    react 学习笔记2
    react 学习笔记
  • 原文地址:https://www.cnblogs.com/linsky/p/14805600.html
Copyright © 2020-2023  润新知