Access-Ctrol-Allow-Headers:*兼容问题导致的跨域失败

现象:

通过抓包看到在部分客户端上跨域的非简单请求只发送一个预检的OPTIONS请求,之后的真实请求并没有发送。

出现问题的环境:

部分IOS低版本系统。

windows系统微信内必现(2020-04-29)。

分析

通过上面条件OPTIONS请求发送成功,但是实际请求没有发送,可以推断出是服务端相关HTTP头没有设置正确,导致客户端认为服务端不允许当前源上的web应用跨域访问该资源,所以后面真正的请求没有发送(fetch的表现为status: 0)。

服务端响应头如下:

Access-Control-Allow-Origin: * 
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *

正常来说不存在问题,因为设置的值也都是合法的,并且在绝大部分客户端上都是正常的。

CORS定义:

CORS跨域资源共享,是通过额外的HTTP头告诉浏览器,源上的web应用被允许访问来自不同源服务器的指定资源。

这里额外的HTTP头值得注意,可以看出来CORS在不同的浏览器上可能是有兼容性问题。

方案

一开始的猜想是HTTP请求的method的值OPTIONS被客户端错误设置为小写,导致服务端异常。但是通过抓包看到OPTIONS请求正确返回(status: 204),并且后端日志中并未收到小写的OPTIONS请求。所以这个排除。

然后着眼于服务端返回的相关HTTP头

Access-Control-Allow-Origin: * 
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: *

本地复现出来,并排查是因为Access-Control-Allow-Headers: * 导致的,这个属性有某些兼容性问题。

Access-Control-Allow-Headers: *

MDN中介绍 Access-Control-Allow-Headers: * 有两重意思。

一个是在服务端设置Access-Control-Allow-Credentials: true的时候这个 * 只会被客户端当做字符串 * (我们不希望的,会出错的)。

另一个是没有这个设置则会被当做通配符(我们希望的,不会出错的)。

猜测是客户端对于 * 的实现上有兼容性问题,所以建议不要这样设置,用到什么设置什么最好,例如:Access-Control-Allow-Headers: Content-Type。

之后成功排除了问题。

结论

Access-Control-Allow-Headers: * 在部分客户端上有兼容问题。

注:跨域错误是不会暴露给JS的,就意味着 try{}catch(corsError){corsError.message}拿不到错误的具体信息,不太好在没有控制台的环境看到问题。

猜你喜欢

转载自blog.csdn.net/letterTiger/article/details/105939465
今日推荐