首页>国内 > 正文

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

2022-03-11 10:26:57来源:八戒技术团队

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

一、跨域的概念

简单介绍一下跨域的基本概念,不满足浏览器同源安全策略的请求即是跨域,同源安全策略因不同浏览器,以及不同版本有所不同,同源的含义通常为协议(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-languagecontent-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"的值不正确

值不正确主要是两种情况:一种是“Access-Control-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面板无法看到服务端任何响应信息,具体表现可见下面的附图:

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

四、总结

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

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

关键词: 安全策略 这种情况 请求参数 基本概念 截然不同

相关新闻

Copyright 2015-2020   三好网  版权所有