跨域笔记
这几天在联调的时候请求后端同学的电脑总是报错,之前开发环境都是配好了的所以就没有在意。这次遇到了就顺便学习下,这次的解决办法是在vue.config.js里配置porxy把对应的接口地址匹配到对应的后台同学的ip就能访问了。然后顺便找了篇比较全的文章学习了一下,顺着他的思路敲了一遍。原文地址:segmentfault
什么是跨域?
指一个域下的文档或脚本试图去请求另一个域下的资源。
- 资源跳转、a超链接、重定向、表单提交
- 资源嵌入 < link >、< scirpt >、< img >、< frame >
- 脚本请求 js发起的ajax请求、DOM和js对象的跨域操作
同源策略
协议+域名+端口号 一致。即便两个不同的域名指向同一个ip地址,也非同源。
跨域解决方案
- 通过jsonp跨域
- document.domain + iframe跨域
- location.hash + iframe
- window.name + iframe跨域
- postMessage跨域
- 跨域资源共享(CORS)
- nginx代理跨域
- nodejs中间件代理跨域
- WebSocket协议跨域
跨域资源共享 CORS
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无需配置。在之前的项目的开发环境就用的这种模式。但是 若需要带cookie请求则需要前后端都设置。
1 | // 原生ajax |
若后台配置成功,前端跨域访问时是不会提示跨域报错的。
nginx代理跨域
nginx配置解决iconfont跨域
在nginx静态资源服务器中加入以下配置1
2
3location / {
add_header Access-Control-Allow-Origin
}nginx 反向代理接口跨域
跨域原理:同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器调用端调用HTTP接口只使用了HTTP协议,不会执行JS脚本,不存在同源策略也就不存在跨域问题。
实现思路:通过nginx配置一个代理服务器做跳板机。域名与domain1相同,端口不同。反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。1
2
3
4
5
6
7
8
9
10
11
12server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass http://www.doamin2.com:8080; #反向代理
proxy_cookie_domain www.domain2 www.domain1.com;
index index.html index.html //???
// 当用webpack-dev-server等中间件代理接口访问nginx,此时无浏览器参与,所以下面的配置可以不启用。
add_header Access-Control-Allow-Origin http://www.domain1.com
add_header Access-Control-Allow-Credentials true
}
}
NodeJS中间件代理跨域
用vue-cli 3.0 搭建的项目,在vue.config.js里配置devServer就行,简单省事。
1 | module.exports = { |
WebSocket协议跨域
这个最近还没有用到,用到了再补充。
jsonp
我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
1 | //原生实现 |
document.domain + iframe跨域
此方案仅限主域相同,子域不同的跨域应用场景。
实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
父窗口:(http://www.domain.com/a.html)
1 | <iframe id="iframe" src="http://child.domain.com/b.html"></iframe> |
子窗口:(http://child.domain.com/b.html)
1 | <script> |
location.hash + iframe
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象。
a.html (http://www.domain1.com/a.html)
1 | <iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe> |
b.html (http://www.domain2.com/b.html)
1 | <iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;"></iframe> |
c.html (http://www.domain1.com/c.html)
1 | <script> |