如何解决开发中常见的跨域问题

开发
本文主要介绍几种常见的跨域问题的表现,排查问题的思路。

在我们日常开发中,跨域请求是不可避免的事情,本文主要是结合猪八戒的技术体系,介绍几种常见的跨域问题的表现,排查问题的思路。

一、跨域的概念

简单介绍一下跨域的基本概念,不满足浏览器同源安全策略的请求即是跨域,同源安全策略因不同浏览器,以及不同版本有所不同,同源的含义通常为 协议(http\https),域名( www.taobao.com )和端口号( 80  8080 )都相同。

二、允许跨域的设置

允许跨域设置,主要是由服务器端处理,在猪八戒技术体系里即是在node层,分为两种情况,简单请求和复杂请求。

1、简单请求

不会触发 CORS 预检请求的请求一般称为简单请求,且必须满足以下所有条件:

条件1:使用下列方法之一:

GET

HEAD

  • POST

条件2:Content-Type 的值仅限于下列三者之一:

text/plain

multipart/form-data

  • application/x-www-form-urlencoded

条件3:不能手动设置以下集合之外的请求头:

accept

accept-language

  • content-language
  • content-type

条件4:请求中的任意 XMLHttpRequest 对象均没有注册任何事件监听器;XMLHttpRequest 对象可以使用 XMLHttpRequest.upload 属性访问。 (一般都满足)

条件5:请求中没有使用readableStream对象 (一般都满足)

满足简单请求的跨域只需要node层在接口响应的时候设置以下头部信息即可:

2、复杂请求

不符合以上条件的请求就肯定是复杂请求,且肯定会触发 CORS 预检请求 ,比如常见的POST请求:Content-Type为application/json。

node层需做以下配置,以utopia举例;

配置预检请求:

接口请求设置:

特别注意:

"Access-Control-Allow-Origin"的值最合适的是配置白名单,因为headers里的Origin某些客户端在特定情况下请求的时候不会携带,如果设置为"*",根据w3c标准"Access-Control-Allow-Credentials"就不能设置为true,主流浏览器都会遵循此标准,防止泄漏隐私数据,在这种情况下会拒绝将数据返回给js, 如果不想配置白名单那么麻烦,常用的方式是通过请求参数将origin传递到utopia服务器。

三、常见的跨域表现和原因

1、因为未设置允许跨域,不满足浏览器同源安全策略

通常看到的跨域的表现,就是下面这种报错:

重点的报错信息是这个, "No 'Access-Control-Allow-Origin' header is present on the requested resource" ,请求的资源上不存在访问控制允许源标头,这种就直接排查接口的实现是否设置了允许跨域,如果确定允许跨域的设置没有问题,继续看下面的可能情况

注意: 排查允许跨域设 置的时候,要先明确当前请求是简单请求还是复杂请求,两种请求方式的跨域设置有差异。

2、"Access-Control-Allow-Origin"的值不正确

值不正确主要是两种情况: 一种是“Ac cess-Con trol-Allow-Origin”的值 与当前请求的站点不一样  比如:

当前请求的站点是 “http://local.test.zbjdev.com:3100”与接口设置的允许的跨域访问的站点“https://chongqing.zbj.com”不 相等,自然就会访问失败,这种检查一下配置就行了

另外一种就是“Access-Control-Allow-Origin”的值格式不正确,比如:

和第一种情况的报错非常相似,但原因其实截然不同,“Access-Control-Allow-Origin”的值应该仅仅包含站点信息,不包含任何路径信息,' http://local.test.zbjdev.com:8300/ '就是带上路径了,正确语法如下:

如果排除是"Access-Control-Allow-Origin"的值不正确导致的问题,请看下面的情况。

3、访问接口被重定向了,但重定向的url不支持跨域访问

这种情况常见因为接口做了登录限制,但请求的时候没有带上用户登录信息导致

报错信息里面会有关键的“redirected from”等重定向的信息,需要去排查是不是请求的时候是否存在有效的登录cookie,或者是客户端在请求的时候没有带上cookie信息,客户端请求带cookie配置以axios库举例:

特殊情况: 如果是复杂请求,浏览器会进行一次 CORS 预检请求 ,预检请求是不会携带cookie的,确认是这种情况,就不要对预检请求做登录限制。

4、接口只在代码正常执行的逻辑里设置了允许跨域,代码执行异常的响应没有设置允许跨域

这种情况非常隐蔽,在node层我们可以设置各种各样的中间件来抽离一些公共逻辑,但是公共逻辑的异常报错响应,一般是不会有跨域相关的设置的,比如这段示范代码:

在这段代码的逻辑里面,会有一个“paramsCheck”的中间件对请求参数“text”是否为空做校验,“text”不为空的情况下,在最后响应客户端的请求的时候会进行允许跨域的设置,不会有问题,但如果“text”为空的时候,“paramsCheck”中间件会拦截,响应客户端,但是并没有进行允许跨域的设置,就会导致前端报错,且报错信息即是普通跨域的样子,并且因为浏览器同源安全策略,在chrome调试工具的network面板无法看到服务端任何响应信息,具体表现可见下面的附图:

我们再看另外一段示范代码,是常见的另一种没有在异常逻辑进行允许跨域设置,导致出现跨域报错的代码:

四、总结

经常遇到的跨域情况,我们可以按照以下这个思路去进行排查:

希望以上内容能对有需要的人有所帮助

责任编辑:张燕妮 来源: 八戒技术团队
相关推荐

2021-06-06 13:05:15

前端跨域CORS

2024-10-29 16:41:24

SpringBoot跨域Java

2022-09-07 07:05:25

跨域问题安全架构

2022-02-22 11:54:05

跨域项目前后端

2022-10-13 14:11:29

浏览器域名端口

2023-02-15 07:03:41

跨域问题面试安全

2023-04-07 10:51:39

2023-07-18 16:05:00

IP地址

2023-05-06 15:32:04

2009-06-30 16:03:00

异常Java

2022-11-11 10:22:54

前端Promise

2022-11-11 15:49:09

前端JavaScript开发

2017-08-20 12:49:59

浏览器跨域服务器

2020-09-17 13:33:39

开发

2009-02-18 09:30:10

AJAX跨域XML

2009-07-06 18:53:52

ESXESX主机VMware

2011-01-21 14:13:10

2009-01-09 23:01:24

2020-02-17 13:05:37

物联网IOT物联网应用

2018-04-25 07:34:59

物联网卡网络运营商
点赞
收藏

51CTO技术栈公众号