什么是跨域?
浏览器从一个[域名](https://so.csdn.net/so/search?q=域名&spm=1001.2101.3001.7020)的网页去请求另一个域名的资源时,域名、端口、协议任意不同,都是跨域
什么是同源策略?
同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
同源策略的目的
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
为什么会有跨域问题?
请求地址的域名或端口和当前访问的域名或端口不一样
受到同源限制
1)无法读取不同源的 Cookie、LocalStorage 和 IndexDB 。
2)无法获得不同源的DOM 。
3)不能向不同源的服务器发送ajax请求。
不受同源限制
在浏览器中,<script>、<img>、<iframe>、<link>等标签都可以跨域加载资源,而不受同源策略的限制。
浏览器对跨域访问的判定
CORS机制把跨域请求分为两类:简单请求和非简单请求。
1) 请求方法是以下三种方法之一:HEAD、GET、POST
2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同时满足上面两个条件,就属于非简单请求。浏览器对这两种请求的处理,是不一样的。
简单请求:浏览器会带上Origin的请求头发送到服务器,服务器根据Origin判断是否许可。如果许可就会带上CORS相关想要头,如果不在许可范围内就不会带上CORS相关的响应头。浏览器再根据响应头中是否有相关的CORS响应头,来判断拦截响应body和抛出错误。
非简单请求:非简单请求会在发真正的请求之前发送一个OPTIONS的带着Origin、Access-Control-Request-Method、Access-Control-Request-Headers等CORS相关的请求头的预检请求到服务器,服务器确认可以这样请求,就会返回带着Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers等CORS相关的响应头的响应,浏览器检查到相关的CORS响应头,说明通过预检可以继续发送真正的请求;服务器确认不可以,则不会返回这些相关响应头,浏览器没检查到CORS的响应头就会抛出错误。
为什么要解决跨域问题?
因为,有时候我们要从别的网页获取某些资源,这个时候我们就需要用跨域解决这种问题,从而获得我们想要的一些资源。
解决跨域问题的三种思路
客户端浏览器解除跨域限制
发送JSONP请求代替XHR请求
修改服务器
解决跨域问题方法
1.vue框架解决跨域问题,反向代理 ,vue-cli 配置proxy :在vue.config.js中配置proxy
2.cors 后端设置请求头
3.后端做代理,后端请求接口,把请求过来的数据返回给前端,后端配置nginx代理
4.前端 jsonp
通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
5.document.domain + iframe跨域
实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
6.location.hash + iframe (衣服锐母)
实现原理: a欲与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。
7.window.name + iframe跨域
window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
8.postMessage跨域
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
a.) 页面和其打开的新窗口的数据传递
b.) 多窗口之间消息传递
c.) 页面与嵌套的iframe消息传递
d.) 上面三个场景的跨域数据传递
9.跨域资源共享(CORS)
只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。
10.nginx代理跨域
跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
11.nodejs中间件代理跨域
node中间件实现跨域代理,原理大致与nginx相同,都是通过启一个代理服务器,实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。
12.WebSocket协议跨域
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,是server push技术的一种很好的实现。
原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。