在现代 Web 开发中,跨域请求是一个常见且重要的概念。随着互联网应用的日益复杂,尤其是在涉及多个前端和后端服务的情况下,跨域问题经常会对应用的功能和用户体验造成影响。
背景
开发项目时,遇到一个需求,当时项目配套的线下商铺已由物业交付给我司运营,运营团队需要招商引资,经过公司考虑决定开发一个公众号交给运营团队,以便客户能够在线选择商铺。公众号内嵌一个H5页面,做到用户点击平面图中单元格(每一个商铺号就是一个单元格)优先锁定商铺,由于商铺分布在多个区域,UI绘图也需要时间,再加需求紧迫,项目必须在三天内上线。前端团队采用了 Canvas 技术,让用户能够直观地选择商铺单元格,并填写提交个人资料。开发过程中,前后端进行了接口联调,在测试环境中没有明显的问题。然而,当项目部署到微信公众号后,出现了跨域请求问题,直接是空白页面。
当时,前端因为配置代理的进度缓慢,跨域配置的解决方案转到了后端。这一问题突显了跨域请求在 Web 开发中的重要性,特别是在需要与多个服务进行交互时。
跨域请求的重要性
- 安全性:浏览器的同源政策旨在保护用户,防止恶意网站窃取信息。跨域请求需要经过严格的检查和配置,以确保数据传输的安全性。
- 用户体验:跨域请求的限制可能会导致用户在操作过程中遇到障碍,影响应用的流畅性和可用性。在我们的项目中,如果不及时解决跨域问题,将会直接影响客户体验和业务进展。
- 业务需求:在某些情况下,业务需求可能需要不同来源的资源交互。例如,在我们开发的微信公众号中,需要与后端服务进行数据交互,以完成用户的选择和定金缴纳等操作。
- 快速迭代:随着项目的推进,及时处理跨域问题是确保项目快速上线的重要环节。在短时间内解决跨域配置,能够为后续的功能扩展和业务发展打下良好的基础。
跨域是指在 Web 应用中,由于浏览器的同源政策(Same-Origin Policy),不同源的网页之间进行交互时所遇到的限制。源的定义包括三个部分:协议(如 或 )、域名(如 )和端口(如 或 )。只有当这三者都相同的时候,两个 URL 被认为是同源的。
为什么有同源政策?
通俗来说,浏览器厂商开发出来的浏览器都是有做安全限制的,当你打开某个网站时,浏览器就已经将请求标头中的origin属性改成了当前网站的域名。例如我访问bilibili,会是这样的一个origin,你在当前页面中做以下几种操作,均会出现跨域:
跨域的情形
1,http://www.bilibili.com(假设存在)
2,https://www.bilibili.com:8086(假设存在)
3,http://admin.www.bilibili.com(假设存在)
跨域原因解释
情况1跨域的原因是scheme(标识特定协议或资源类型的字符串)变了
情况2 跨域的原因是port(端口号)变了
情况3跨域的原因是host(域名,admin.www.bilibili.com是域名)变了
跨不跨域框架说了算,来看看Springboot框架是如何认定为跨域的,先附上截图,然后给源码解释
处理请求相关的参数,并通过比较来判断是否跨域的源码
源码中不难看出来,在经过一番处理之后,会通过客户端传递的Origin中的信息和接口服务资源做协议,端口,域名的比对,只要有一处不一样那就是跨域,框架会告知浏览器跨域,具体的比对过程并不难,我已经贴出来了包名和类名,鼓励朋友们自己动手。
既然服务器有处理请求,为什么你在浏览器上看不到响应回来的HTTP状态码,服务器应该要给客户端返回个状态码,取而代之的却是显示:此请求没有发起程序请求或者类似的其他提示,这都要归功于预检请求,也是浏览器厂商默认遵循的一个标准规范,属于 CORS(跨源资源共享)机制的一部分。
跨域提示截图
或者
预检请求(Preflight Request)是 CORS(跨源资源共享)机制中的一个重要概念,用于在发送复杂的跨域请求之前,先向服务器发送一个 HTTP OPTIONS 请求,以确认服务器是否允许实际的请求。预检请求的目的是为了增强安全性,确保客户端在发送敏感数据时得到服务器的许可。
何时触发预检请求
预检请求通常在以下情况下触发:
- 复杂请求:
- 当使用的 HTTP 方法不是简单请求中的 GET 或 POST(如 PUT、DELETE)。
- 当请求中包含自定义头部(例如,)。
- 当 的值不是简单请求允许的类型(如 、 或 )。
- 服务器端的 CORS 配置:
- 只有在服务器配置了 CORS,并明确允许来自特定源的请求时,预检请求才会返回成功。
完全不瞎说,有没有预检请求,依旧是springboot框架说了算,先附上原图,在附上部分源码
当我从知乎页面上请求我本机的服务接口时
服务器处理预检请求
首先服务器确实收到了该次请求,截图如下:
处理预检请求的截图:
OPTIONS请求就是预检请求的请求方式,这里解释不了为什么,只能回答这就是规范
处理预检请求的源码:
允许还是不允许,完全看程序员如何设置跨域规则,跨域策略,不做深入讲解,但是教你如何避开雷区,先看看核心逻辑的截图
服务器会判断当前是否是预检请求,如果是,则会调用一个处理内部请求的方法,如图
关键点:allowOrigin为什么为null,checkOrigin方法到底做了什么比较
问题到这里很清晰了,当程序执行到ObjectUtils.isEmpty(this.allowedOrigins)或者this.allowedOrigins.contains("*"),if语句的条件不成立了,因为this.allowedOrigins并不包含客户端的域名,也就是例子中的https://www.bilbili.com或者https://www.zhihu.com,我们要处理的正是allowedOrigins,
private List<String> allowedOrigins;
他是以数组的形式被持有的,有很多个API可以给这个数组初始化值,在我的代码中,只展示一种,因为我们要学的不是API,而是发现问题,拆分问题,解决问题的心法,API什么的不重要。
以上介绍了什么是跨域,跨域的情形,以及预检请求作为web浏览器的规范,以及服务器如何处理预检请求,浏览器对于未通过的预检请求会以什么形式展示给用户,接下来告诉大家如何解决这种小小的问题~
springboot解决跨域的方式非常之多,但是从最底层解决,往往能学到更多指定问题之外的知识
这段配置足已解决前端跨域问题,之前说的雷区就是允许发送凭据的代码和config.addAllowedOrigin("*");不可以一起使用,否则会报错。到这里,一切OK,前端跨域的问题已经解决~
给大家一段便捷的JS代码用来测试跨域问题,JS代码不做解释,相信看懂不成问题
这段js代码,按F12,在浏览器的控制台中直接执行,支持IE和Google浏览器,亲测有效,需要根据实际的请求进行微调,不要在你自己的WEB项目或者API文档页面打开,否则无法达到测试跨域的效果,具体原因,我相信你理解了上面的知识点之后应该能明白。解决问题的代码很少,但是知识点并不少,留心处处皆学问哈
到此这篇前端跨域解决方案cors(前端跨域cors怎么写)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/qdkf/31897.html