在我们日常的开发中,跨域请求是不可避免的。本文主要介绍基于猪八戒技术体系的几种常见跨域问题的表现,以及如何排查问题的思路。1.跨域的概念简单介绍一下跨域的基本概念。如果不满足浏览器同源安全策略的请求,就是跨域。同源安全策略对于不同的浏览器和不同的版本是不同的。同源的含义通常协议(http\https)、域名(www.taobao.com)和端口号(80、8080)都相同。2.允许跨域设置允许跨域设置,主要由服务器处理。在猪八戒技术体系中,处于节点层。有两种情况,简单请求和复杂请求。1、简单的请求不会触发CORS预检请求。该请求一般称为简单请求,必须满足以下所有条件:条件一:使用以下方法之一:GETHEADPOST条件二:Content-Type的取值限于以下三种之一:text/plainmultipart/form-dataapplication/x-www-form-urlencoded条件3:不能手动设置以下集合以外的请求头:acceptaccept-languagecontent-languagecontent-type条件4:请求中的任何XMLHttpRequest对象都没有注册任何事件监听器;可以使用XMLHttpRequest.upload属性访问XMLHttpRequest对象。(基本满足)条件5:请求中没有使用readableStream对象(基本满足)。满足简单的跨域请求,只需要节点层在接口响应时设置如下头信息即可:2.复杂请求不满足以上条件请求肯定是复杂请求,肯定会触发CORS预检请求,比如一个普通的POST请求:Content-Type是application/json。node层需要做如下配置,以utopia为例;配置预检请求:接口请求设置:特别注意:“Access-Control-Allow-Origin”的值是最适合配置白名单的,因为headers中的Origin有的客户终端在请求下不会带上某些情况下。如果设置为“*”,根据w3c标准“Access-Control-Allow-Credentials”不能设置为true,主流浏览器都会遵循这个标准来防止隐私数据泄露。在这种情况下,它会拒绝将数据返回给js。如果不想那么麻烦配置白名单,常用的方式是通过请求参数将origin传给utopiaserver。三、常见的跨域表现及原因1、由于不允许跨域,也不符合浏览器的同源安全策略,通常看到的跨域表现是如下错误:关键错误信息是这样的,”No'Access-Control-Allow-Origin'headerispresentontherequestedresource”,请求的资源上没有访问控制权限originheader,直接查看接口的实现是否设置了允许跨域,如果确定是允许跨域域设置没有问题。继续看下面可能出现的情况。注意:检查是否允许跨域设置时,首先要明确当前请求是简单请求还是复杂请求。两种请求方式的跨域设置不同。2.“Access-Control-Allow-Origin”的值不正确。“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不支持跨域访问,这个常见是因为接口有登录限制,但是请求的时候没有带上用户登录信息,导致错误信息中key“redirected”等重定向信息,需要检查是否有有效的请求时登录cookie,或者客户端请求时不带cookie信息,客户端请求带cookie配置。以axios库为例:特例:如果是复杂请求,浏览器会进行CORS预检请求。预检请求不会携带cookies。如果是这种情况,请不要对预检查请求设置登录限制。4、接口只在正常代码执行逻辑中设置允许跨域,异常代码执行的响应没有设置允许跨域。这种情况非常隐蔽。在节点层,我们可以设置各种中间件来提取一些Public逻辑,但是Public逻辑的异常错误响应一般不会有跨域相关的设置,比如这个例子代码:在这段代码的逻辑中,会有一个检查请求参数“text”是否为空的“paramsCheck”中间件来检查,如果“text”不为空,最后响应客户端的请求时会允许跨域设置,不会有问题,但是如果“text”为空,“paramsCheck”中间件会拦截响应客户端,但是不允许跨域设置,会导致前端报错,报错信息同上一次正常的跨域,并且因为浏览器的同源安全策略,在chrome调试工具的网络面板是看不到服务器的任何响应信息的。具体表现可以看下图:再看一段演示代码,也是常见的在异常逻辑中不允许跨域设置,导致跨域的错误代码:4.总结对于经常遇到的跨域情况,我们可以按照以下思路进行排查:希望以上内容可以对有需要的人有所帮助
