跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
非同源的限制
1.无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
2.无法接触非同源网页的 DOM
3.无法向非同源地址发送 AJAX 请求
跨域解决方法之一:jsonp
jsonp的实现原理:利用script和img标签有src属性的特性
只支持get,不支持post
核心思想:网页通过添加一个script
元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
跨域解决方法之一:CORS
CORS(Cross-origin resource sharing),跨域资源共享,是⼀份浏览器技术的规范,⽤来避开 浏览器的同源策略
CORS与JSONP的对比
1.JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。
2.使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。
3.JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS
CORS跨域设置
一、允许跨域 没有了同源策略,不安全/不能携带凭证
ctx.set("Access-Control-Allow-Origin","https://www.baidu.com")
表示只有www.baidu.com
可以访问
res.header("Access-Control-Allow-Origin","")
表示任意域名都可以访问,默认不能携带cookie
二、允许获取头部信息
CORS请求时, XMLHttpRequest 对象的getResponseHeader()
⽅法只能拿到6个基本字段:Cache- Control、Content-Language、Content-Type、Expires 、Last-Modified、Pragma
如果想拿到其 他字段,就必须在Access-Control-Expose-Headers
⾥⾯指定。
服务器端:ctx.set("Access-Control-Expose-Headers","Content-Type,Content-Length,Date")
获取选定的头部信息
res.header("Access-Control-Expose-Headers","*")
获取所有头部信息
客户端:xhr.getAllResponseHeaders()
三、允许前端设置的头部
res.header/ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
四、设置允许前端发送的请求方式
ctx.set("Access-Control-Allow-Methods","GET,POST,DELETE,HEAD,OPTIONS")
五、允许携带凭证(cookie就是一种凭证)
服务器端:ctx.set("Access-Control-Allow-Credentials",true)
客户端:xhr.withCredentials = true
六、设置预检请求的缓存时间
ctx.set("Access-Control-Max-Age",3600*24)
参数2为有效时间
预检请求
options 允许前端设置头部信息
可以避免跨域请求对服务器的用户数据产生未预期的影响
出现预检请求的情况:
1.指定的请求类型时(PUT DELETE CONNECT OPTIONS TRACE PATCH
)
2.修改了指定的属性名(字段)
3.修改了执行的属性值
代码:router.options("/*",ctx=>{放入修改的所有设置})
简单请求:某些不会触发预检请求的称之为简单请求
必须是下面定义对CORS安全的首部字段集合,不能是集合之外的其他首部字段
请求类型:GET HEAD POST
前端设置头部属性名(字段):Accept、Accept-Language、Content-Language、Content-Type、
DPR、Downlink、Save-Data、Viewport-Width、Width
前端设置头部属性值:Content-Type的值必须是text/plain、multipart/form-data、
application/x-www-form-urlencoded中任意一个值
满足上面所有的条件才不会发送预检请求,在实际项目中我们的请求格式可能是application/json格式编码,或者使用自定义请求头都会触发CORS的预检请求。
跨域解决方法之一:后端代理
后端代理(正向代理):利用koa-server-http-proxy
中间件
接口转发
客户端使用:
服务器端使用:
参数1为自定义 与pathRewrite要对应
参数2是个对象
target是跨域的地址
pathRewrite的属性名意思为将/api
开头路由替换为属性值的路由
一般情况属性值为空即可""