跨域问题踩坑记录——附多种报错详细解决方案

这篇具有很好参考价值的文章主要介绍了跨域问题踩坑记录——附多种报错详细解决方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

跨域是出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源

场景:

前端调用接口接收文件流下载文件,以本地环境为例,系统域名为http://localhost:8090,接口域名为'http://127.0.0.1:8080,后端使用springboot

此时浏览器控制台报错:

跨域报错状态码,java,前端,后端,spring boot,Powered by 金山文档
Access to XMLHttpRequest at 'http://127.0.0.1:8080/zyfbpt/dbreport/export?domainKey=zyfzyfbpt' from origin 'http://localhost:8090' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

尝试一:接口返回文件流时响应头设置Access-Control-Allow-Origin

String origin = request.getHeader("Origin");
response.addHeader("Access-Control-Allow-Origin", origin);

重启服务后发现并没有生效,报错内容不变(有没有大佬帮忙分析下这样为什么不生效)

尝试二:使用@CrossOrigin注解

//1.在controller类上使用
@Controller
@CrossOrigin
public class MyController {

}
//2.在方法上使用
@CrossOrigin
@RequestMapping(value = "/test",method = RequestMethod.POST)
public void test(@RequestBody TestRequest testRequest){
    
}

直接加上后发现依然不生效,搜索后总结原因有以下几点:

情况一:在方法上使用@CrossOrigin注解,但@RequestMapping注解中没有指定Get、Post方式,通过method = RequestMethod.POST/GET指定或者指定@CrossOrigin注解中的methods = {RequestMethod.POST}后,问题解决。

//在@CrossOrigin中methods指定方式
@CrossOrigin(methods = {RequestMethod.POST})

//或者@RequestMapping注解定义method
@RequestMapping(value = "/test",method = {RequestMethod.POST})

情况二:跨域访问响应状态码是405-Method Not Allowed,请求行中指定的请求方法不能被用于请求相应的资源。这个是请求方式不正确,检查代码。

情况三:查看springboot版本,如果是2.0以后版本,allowCredentials属性的默认值为false,返回的响应头AccessControlAllowCredentials属性值也为false,如果客户端携带cookie的请求这时是不能跨域访问的,所以需要手动在注解中设置allowCredentials为true

例如:前端ajax请求参数withCredentials=true,表示请求带上cookie信息

//a标签下载文件
axios({
      method: 'POST',
      url: downloadUrl,
      data: params,
      withCredentials:true,
      responseType: 'blob'
    }).then(res => {
      let url = window.URL.createObjectURL(new Blob([res.data]));
      let link = document.createElement("a");
      link.style.display = "none";
      link.href = url;
      link.setAttribute("download", `report-${Date.now()}.docx`);
      document.body.appendChild(link);
      link.click();
});

此时就需要后端设置allowCredentials=true解决跨域,然而这里如下配置后再请求报错了:

@CrossOrigin(allowCredentials = "true")
@RequestMapping(value = "/dbreport/export", method = RequestMethod.POST)
@ResponseBody
public Object export(@RequestBody JSONObject json HttpServletResponse response) {

}

后端报错:

java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.

翻译过来就是:

当allowCredentials为真时,allowedorigin不能包含特殊值"*",因为不能在Access-Control-Allow-Origin响应头中设置该值。要允许凭证到一组origins,显示地列出它们,或者考虑使用"allowedOriginPatterns”代替。

解决:

按提示加上originPatterns = "*"后问题解决

@CrossOrigin( originPatterns = "*", allowCredentials = "true", allowedHeaders = "*")
@RequestMapping(value = "/dbreport/export", method = RequestMethod.POST)
@ResponseBody
public Object export(@RequestBody JSONObject json HttpServletResponse response) {

}

尝试三:全局CORS配置

配置后无需每个controller或方法上加@Configuration注解了

@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            // 放行哪些域名,可以多个
            .allowedOriginPatterns("*")  
            // 是否发送Cookie信息                       
            .allowCredentials(true)
            // 允许的模式
            .allowedOriginPatterns("*");
            // 放行哪些请求方式                      
            .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "PATCH") 
            // 放行哪些原始域(头部信息)
            .allowedHeaders("*")
            // 暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)                             
            .exposedHeaders("Header1", "Header2") 
            // 预请求的结果有效期,默认1800分钟,3600是一小时
            .maxAge(3600);                                      
    }
}

搜索后发现有网友说此种配置有以下情况,但是我自己的接口就是用HttpServletResponse返回的文件流,没有加下边的响应头也成功了,供参考

适用情况:

1返回字符串或对象的接口

2.通过ResponseEntity提供文件下载功能的接口

不适用的情况:

直接适用HttpServletResponse进行内容返回的接口,需要在响应头加上下边内容

response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE");
response.addHeader("Access-Control-Max-Age", "9600");
response.addHeader("Access-Control-Allow-Headers", "x-requested-with");

解决问题途中还遇到了下边的错误:

错误一:

此时前端请求带withCredentials=true,携带cookie请求

后端配置为:

@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");                                
    }
}
跨域报错状态码,java,前端,后端,spring boot,Powered by 金山文档
Access to XMLHttpRequest at 'http://127.0.0.1:8080/zyfbpt/dbreport/export?domainKey=zyfzyfbpt' from origin 'http://localhost:8090' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

原因:如果跨域请求设置了withCredentials:true, 浏览器发起请求的时候会携带上所在域的cookie信息,同时跨域标准规定请求响应header中Access-Control-Allow-Origin不能设置*,必须设置为具体的跨域域名。

解决方法一:

前端去掉withCredentials=true参数

解决方法二:

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
            .allowCredentials(true)
            .allowedOriginPatterns("*");
}

错误二:

跨域报错状态码,java,前端,后端,spring boot,Powered by 金山文档
Access to XMLHttpRequest at 'http://127.0.0.1:8080/zyfbpt/dbreport/export?domainKey=zyfzyfbpt' from origin 'http://localhost:8090' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values '*, http://localhost:8090', but only one is allowed.

原因:Access-Control-Allow-Origin响应header重复添加了导致报错,一般出现该原因是因为运维 和 接口方同时添加了Access-Control-Allow-Origin的响应header。

解决:检查是否多处配置Access-Control-Allow-Origin,如CROS全局配置、contraller中的@CrossOrigin注解、代码中设置Access-Control-Allow-Origin响应头、nginx等网关层添加等,

只保留一处即可文章来源地址https://www.toymoban.com/news/detail-759399.html

到了这里,关于跨域问题踩坑记录——附多种报错详细解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • @EnableWebMvc注解让swagger-ui.html无法打开404报错问题及其解决方案(史上最全最详细)

    在工作中,通过Swagger2对项目的controller进行配置,以便于用户测试restful服务接口提高开发效率。 但是今天却出现了一个让我匪夷所思的问题就是在配置类里面加上@EnableWebMvc注解后(开启web配置支持)启动项目 发现访问Swagger的ui界面404 这个我就奇怪了,然后我尝试的把@Ena

    2023年04月17日
    浏览(32)
  • Python Wordcloud报错:Only supported for TrueType fonts,多种解决方案

    Python Wordcloud报错:Only supported for TrueType fonts,多种解决方案。 报错内容如下: 2023-10-26T09:35:41.190459839Z Traceback (most recent call last): 2023-10-26T09:35:41.190502589Z File “lib/task/compute.py”, line 621, in 2023-10-26T09:35:41.190514101Z compute_match_rule(rule_data) 2023-10-26T09:35:41.190521681Z File “lib/task/comp

    2024年02月07日
    浏览(39)
  • 解决mysql报错:1406, Data too long for column(多种方案)

    传送 centosAI 适用于linux系统 一般1406, Data too long for column错误大部分会是因为某一列表的数据长度受限,最好的办法是进入数据库,找到表结构中对应的表头,修改数据库类型,这里以vod_first_letter为例,如果直接修改数据类型,可能会因为文本内容不兼容而导致失败,如将V

    2024年01月21日
    浏览(44)
  • Ajax请求跨域问题及其解决方案

            我们的传统请求,比如说超链接、form表单,js代码以及直接在浏览器地址栏上写请求地址都不存在跨域问题,能够从一个网站访问另外一个网站,但是我们的Ajax请求会存在跨域问题,其主要是为了解决跨域访问带来的安全隐患。因为浏览器中有一个内置对象XMLH

    2024年02月06日
    浏览(51)
  • html前端跨域问题的解决方案

    前言: 在前端发出Ajax请求的时候,有时候会产生跨域问题,报错如下: Access to XMLHttpRequest at ‘http://127.0.0.1/api/post’ from origin ‘null’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. 针对以上问题,本文提供两种解决方案,CORS中间件和

    2023年04月22日
    浏览(70)
  • AJAX学习笔记8 跨域问题及解决方案

    AJAX学习笔记7 AJAX实现省市联动_biubiubiu0706的博客-CSDN博客 跨域:指一个域名的网页去请求另外一个域名资源.比如百度页面去请求京东页面资源. 同源与不同源三要素:协议,域名,端口 协议一致,域名一致,端口一致.才算是同源.其他一律不同源 新建项目 测试: 1.window.open(); window.lo

    2024年02月09日
    浏览(42)
  • SpringBoot 解决跨域问题的 5 种方案!

    供学习使用 SpringBoot 解决跨域问题的 5 种方案! 跨域问题指的是不同站点之间,使用 ajax 无法相互调用的问题。跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。但这个保护机制也带来了新的问题,它的问题是给不同站点之间

    2024年02月08日
    浏览(28)
  • 跨域问题解决记录

    has been blocked by CORS policy: The \\\'Access-Control-Allow-Origin\\\' header contains multiple values \\\'*, http://localhost:9000\\\', but only one is allowed. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request\\\'s mode to \\\'no-cors\\\' to fetch the resource with CORS disabled. 遇到一个问题,直接报错 根

    2024年02月11日
    浏览(22)
  • DataEase二开记录--踩坑和详细步骤(一)

    最近在看DataEase,发现挺好用的,推荐使用。 用的过程中萌生了二开的想法,于是自己玩了玩,并做了一些记录。 下载源码,选稳定版本的,本案例是1.17.0版本。 下载地址 开源社区 - FIT2CLOUD 飞致云 数据库配置 数据库初始化: DataEase 使用 MySQL 数据库,推荐使用 MySQL 5.7 版本

    2024年02月07日
    浏览(31)
  • DataEase二开记录--踩坑和详细步骤(二)

    建议先看第一篇 DataEase二开记录–踩坑和详细步骤(一) maven打包 clean - package 在backend/target 目录下就会出现 backend-1.xx.0.jar,这就是我们 DataEase 的镜像 jar 包。 修改docker配置文件 开放2375端口,用于和idea的连接 idea安装docker插件 Settings - Plugins 安装后就可以创建docker 编辑doc

    2024年02月04日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包