问题描述
- 浏览器在进行跨域请求前,会像服务器发送option请求
- 浏览器会根据option的reponse的 header 中的信息判断跨域请求是否合法
- 主要是 Access-Control-Allow-Origin 和当前网页的url 是否match(和
xmlHttpRequest
请求的url 没有关系) - Access-Control-Allow-Credentials 决定跨域请求是否可以携带cookie等信息。
- 如果是false,则
xmlhttpRequest.withCredentials=true
时会报错 - 如果没有跨域
withCredentials
默认为true,跨域则默认为false - 跨域请求携带的cookie是目标domain的cookie,而不是当前页面的cookie
- 除了这个设置外,cookie本身的samesit属性也会影响是否可以在xhr中使用cookie
一个跨域的post请求能拿到cookie至少有三个条件- cookie 的 samesite 为 None
- option response 中
Access-Control-Allow-Credentials:true
- js 调用 xhr请求时
xhr.withCredentials=true
- 如果是false,则
- 主要是 Access-Control-Allow-Origin 和当前网页的url 是否match(和
所以总结下:
跨域问题就是如何绕开浏览器 对 xmlHttpRequest
的限制。
后端方案
要被访问的那个服务器,在返回头中加入:
(比如我想写个插件,把抓到的数据存到我自己的服务器上,就在我的服务器的返回头中加入)
//不同语言不同,仅供参考
header("Access-Control-Allow-Origin: *");
//或者直接加入网址
header("Access-Control-Allow-Origin:http://www.otherweb.com");
这里几个地方需要注意
Access-Control-Allow-Origin
, 只允许填入一个值似乎,所以如果想允许多个值,可以根据 origin 字段动态设置w.Header().Add("Access-Control-Allow-Origin",req.Header.Get("Origin"))
- 除了
Access-Control-Allow-Origin
外,还有一些其他跨域 header 可以设置,目的都是为了限制跨域请求,比如Access-Control-Allow-Headers
规定了跨域请求允许的header, 也就是此时除了不能是常见的不能设置的header, 还要满足header 要在Access-Control-Allow-Headers
出现
前端解决方案
- jsonp,例子以后补上吧。。。
- 虽然 jsonp 可以跳过浏览器的检测,但是服务端依然可以通过验证referer字段,拒绝跨域的 GET 请求
- origin 和 referer ,和host 的差别
- origin 只在跨域时才会发,并且只有host
- referer 则一直会有,并且包括请求的完整路径
- host 目标 url 的host,origin/referer都是源的
- 这几个header都是js-xmlHttpRequest不能手动设置的
- 比如,我在blog的页面,打开console,发送跨域请求到我本地服务器,那么几个header是这样的
Host: localhost:8080 Origin: https://blog.csdn.net Referer: https://blog.csdn.net/harryhare/article/details/80778066
- origin 和 referer ,和host 的差别
- 虽然 jsonp 可以跳过浏览器的检测,但是服务端依然可以通过验证referer字段,拒绝跨域的 GET 请求
- 油猴脚本,脚本运行时会弹出窗口,让用户选择是否允许跨域请求。从而跳过浏览器对跨域请求的阻止。
//@grant GM_xmlhttpRequest GM_xmlhttpRequest({ method: "GET", url: "http://asdf.com/asdf", onload: myonload, });
参考:
http://www.ruanyifeng.com/blog/2016/04/cors.html
https://www.jianshu.com/p/89a377c52b48
https://blog.csdn.net/hehexiaoxia/article/details/61916737