技术分享 Technology to share

前端也要玩跨域“CORS”

说起CORS又是一个老生常谈的问题,这段时间在跟物联网对接,走的也是http服务、索性简单的请求就直接前端来发送(因为最终是在局域网里面所以不担心接口暴露,有权限才可以调用等问题,于是又见到我的老朋友了 cors


参考资料:

跨域资源共享 CORS 详解 -阮一峰

HTTP访问控制(CORS)

awesome-bookmarks


浏览器将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)


非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者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容器的权重大于语言权重 设置不生效可以检查下这个关系




上一篇: vue cli 也要读配置文件

下一篇: 相似图片搜索

分享到以下平台: