作为一名前端,在日常开发的过程中我们使用ajax请求获取数据,我们常常会遇到跨域的问题,结合自己的实践和网上的资料,对浏览器的同源策略,解决跨域问题的常见方法进行总结。
同源策略
Q: 为什么我们需要同源?
A: 因为安全性的考虑。比如我们在登陆一个网站时留下的个人信息,证明身份的用户信息,登录的cookie信息,如果没有同源策略的限制别人就会很容易拿到这些信息,用户的安全性也就无法保障了。
Q: 怎么才算同源?
A: 协议相同 域名相同 端口相同
Q: 同源策略限制了哪些信息?
A: (0) Cookie、LocalStorage、IndexDB
Cookie表明了用户的身份 LocalStorage、IndexDB也可能包含用户的信息
(1) DOM 无法获得
DOM??? 为什么DOM也无法获得呢?
因为如果有一个伪装的网站在iframe中引入你真正要访问的网站 在子iframe中父级页面获得DOM元素后可以对ta进行事件的监听能够获得用户输入的密码等
(2) AJAX 请求无法发送
请求中的 cookie 会存储在浏览器客户端本地当 AJAX请求发出时会根据请求的域名带上 cookie 信息,如果没有同源策略限制就可以在恶意的页面中发起请求
源的更改
在我们需要在父域和子域之间进行正常的通信的时候,我们可以将父域和子域中的 document.domain 设置为父域,这样这两个页面会被当成同源。
如何绕过
同源策略对我们来说是必要的,但是有些合理的数据传递也被限制了,但是我们还是能够通过一些其他的手段来间接的传递数据
0.怎么做呢?
src属性具有天生跨域的能力 所以带有src属性的元素比如script iframe img 都不受同源策略的影响
1.JSONP
JSONP和JSON有什么关系?
JSON是自从AJAX2.0以来使用最广泛的数据传输格式 [] 表示 数组 {} 表示 对象
JSONP是一种数据的传输方式
所以说关系好像 JAVA 和 JavaScript(就是没啥关系)
那我们如何使用JSONP请求数据呢?
1 | // 创建一个script |
2.CORS
CORS 全称为跨域资源共享(cross-origin sharing standard)规定了在跨源资源访问时的规则
在跨源请求访问时会带上 Header 信息来让 server 端判断时候允许访问资源。
简单请求
同时满足下列所有条件的时候称为简单请求
- 请求方法为 GET POST HEAD
- Request header 在如下的列表中
- Content-Type
- Content-Language
- Accept-Language
- Accept
- DPR
- Downlink
- Width
- Viewport-Width
- Save-Data
- Content-Type 为下面三种类型之一
- multipart/form-data
- text/plain
- application/x-www-form-urlencode
- 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;
XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。 - 请求中没有使用 ReadableStream 对象。
需要预检的请求
除简单请求外,请求都是需要预检的,在发出正常请求之前需要先发出一个 OPTIONS 请求,这个请求只携带少量的信息,来询问服务端是否允许实际请求。
Access-Control-Request-Methods
Access-Control-Request-Headers
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Max-Age
Access-Control-Allow-Credentials
设置Access-Control-Allow-Origin
第一种.将你需要跨域的站点设置上’Access-Control-Allow-Origin’, ‘http://xx.stuq.com'
第二种.对所有站点的请求都不拦截’Access-Control-Allow-Origin’, ‘*’
这样设置之后就不用做任何事情了
参数还可以根据请求的站点动态设置,这样就保证了灵活性
3.location.hash
使用iframe 在iframe中加载一个与邀请同域的页面 在这个页面中发起请求
1 | // 创建一个iframe |
4.Window.name
开始也是与上面一样
不同的地方在于在iframe中请求到数据后如何带回来
1 | // 创建一个iframe |
5.HTML5 的psotmessage
开始也是与上面一样
不同的地方在于在iframe中请求到数据后如何带回来
1 | // 创建一个iframe |
6. document.domain
当二级域名相同可以分别对 a.test.com/index.html 和 b.test.com/index.html 设置 document.domain = test.com
这样两个页面会当成同域处理
技术的适用场景
- 最省力 设置Access-Control-Allow-Origin 为 * 但是不安全 不适用于比较私密的信息
- 后端能控制 则使用JSONP
- 后端无法控制 允许上传一个页面 window.name location.hash postMessage(前提是现代浏览器…)