解决跨域--CORS
几种常用跨域方式区别:
jsonp : 前端来完成
CORS: 前后端配合完成 (存在预检请求的情况)
后端代理: 后端完成
一. CORS跨域设置
概念
CORS(Cross-origin resource sharing),跨域资源共享,是⼀份浏览器技术的规范,⽤来避开
浏览器的同源策略
简单来说就是解决跨域问题的除了jsonp外的另⼀种⽅法;⽐jsonp更加优雅。
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制,以避开浏览器的同源策略,是 JSONP 模式的现代版。
与 JSONP 不同,CORS 除了 GET 要求方法外,也支持其他的 HTTP 请求。用 CORS 可以让网页设计师用一般的 XMLHttpRequest,这种方式的错误处理比 JSONP 好。另一方面,JSONP可以在不支持 CORS 的老旧浏览器上运作,现代浏览器都支持 CORS。
1. 允许跨域 Access-Control-Allow-Origin
("Access-Control-Allow-Origin","*")
('Access-Control-Allow-Origin', 'http://www.baidu.com')
ctx.set("Access-Control-Allow-Origin","*");
(1)这个表示任意域名都可以访问,不安全
(2)不能携带凭证,默认不能携带cookie了。(必须字段)ctx.set("Access-Control-Allow-Origin","http://localhost:3000");
这样写,只有http://localhost:3000可以访问
2. 允许客户端获取的头部信息 Access-Control-Expose-Headers
(–响应头部–)
("Access-Control-Expose-Headers",'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
后端非同源接口代码:
ctx.set("Access-Control-Expose-Headers",'Content-Type,Content-Length,Date');
(1) 允许客户端获取的头部key;
(2) 用set或者header都可以;
(3) CORS请求时,XMLHttpRequest 对象的 getResponseHeader() ⽅法只能拿到6个基本字段:Cache->Control 、 Content-Language 、 Content-Type 、 Expires 、 Last-Modified 、 Pragma。
如果想拿到其他字段,就必须在 Access-Control-Expose-Headers ⾥⾯指定。
对应前端的 获取返回头部信息:xhr.onload = function(){ console.log(xhr.responseText); // 获取返回头部信息 let res = xhr.getAllResponseHeaders(); console.log(res);// date: Mon, 13 Apr 2020 11:43:32 GMT // content-type: text/plain; charset=utf-8 // content-length: 21 }
3. 允许前端设置的头部 Access-Control-Allow-Headers
(–请求头部–)
设置允许requset设置的头部
使用cors方式来跨域时,跨域时会限制设置请求头部,只能去找后端 —> 允许前端设置的头部(请求头部)
('Access-Control-Allow-Headers','Content-Type,Content-Length,Authorization, Accept,X-Requested-With,yourHeaderFeild');
后端非同源接口代码:
ctx.set("Access-Control-Allow-Headers","Content-Type,Content-Length,Authorization,test")
对应前端的 设置头部信息
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); xhr.setRequestHeader("Content-Type","application/json"); xhr.setRequestHeader("test","some value...");//属性test随便写的。。注意服务器与浏览器要一致
4. 设置前端允许发送的请求方式 Access-Control-Allow-Methods
ctx.set("Access-Control-Allow-Methods",'GET,POST,DELETE,HADE,OPTIONS');
5. 允许携带凭证 Access-Control-Allow-Credentials
ctx.set("Access-Control-Allow-Credentials",true)
凭证 例如post参数,cookie信息等等(非同源获取不到,所以需要在前端开启一下,后端也允许一下该凭证)
后端非同源接口代码:ctx.set("Access-Control-Allow-Credentials",true);
对应前端的开启 允许携带凭证
xhr.withCredentials = true;
6. 预检请求 & 设置预检请求的缓存时间 Access-Control-Max-Age
6.1 预检请求
6.1.1 概念
1.预检请求 options —> 允许前端设置头部信息
2.预检请求:不符合 可直接发送的简单请求 条件时,会出现预检请求(简单请求