说起CORS又是一个老生常谈的问题,这段时间在跟物联网对接,走的也是http服务、索性简单的请求就直接前端来发送(因为最终是在局域网里面所以不担心接口暴露,有权限才可以调用等问题,于是又见到我的老朋友了 cors
参考资料:
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。
第一个条件、请求方法是以下三种方法之一:
HEAD GET POST
第二个条件、HTTP的头信息不超出以下几种字段:
Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同时满足上面两个条件,就属于非简单请求。
浏览器对这两种请求的处理,是不一样的。
简单请求可以在服务端设置响应头 Access-Control-Allow-Origin * 即可解决 常见报错如下图
但是你也会碰到如下所示的报错,这时候就属于非简单请求
非简单请求在设置响应头 Access-Control-Allow-Origin 时候就需要注意了 这里得*号 得换成指定的想要跨域的域名才行 例如:
//php code header(Access-Control-Allow-Origin:www.hiwebpage.com)
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
withCredentials 属性
var xhr = new XMLHttpRequest(); xhr.withCredentials = true; //开启withCredentials 属性也是属于非简单请求 //根据session实现的验证码这里也需要注意 这里为true 浏览器才会携带cookie 发送到服务器
服务段设置这个字段来接收浏览器传过来的cookie
Access-Control-Allow-Credentials: true
常用设置字段代码
header('Access-Control-Allow-Origin', $origin); header('Access-Control-Allow-Headers', 'Origin, Content-Type, Cookie, X-CSRF-TOKEN, Accept, Authorization, X-XSRF-TOKEN'); header('Access-Control-Expose-Headers', 'Authorization, authenticated'); header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, OPTIONS, DELETE'); header('Access-Control-Allow-Credentials', 'true');
而且还要注意一点,也不是只有XMLHttpRequest或者 fetch请求才会有跨域问题,使用 drawImage 的 canvas、web 字体 、CSSDOM 也都是有这问题的。
还、还、还....要注意一点,web容器的权重大于语言权重 设置不生效可以检查下这个关系