跨域是由于浏览器的同源策略造成的,是浏览器施加的安全限制。
什么是同源策略/SOP(Same origin policy)?
同源策略是一种约定,是浏览器最核心最基本的安全功能,缺少同源策略,浏览器容易收到XSS、CSRF等攻击。
同源策略是:拥有相同的协议、域名、端口号的网址间才可以相互访问资源。
一个域的页面去访问另一个域的资源就形成了跨域。
注:跨域并不是请求发不出去,而是请求发出去了,也正常返回结果了,但是结果被浏览器拦截了。
特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。
浏览器的同源策略一直是开发中经常遇到的问题,它是浏览器最核心也是最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能都会受到影响。同源策略(Same origin policy)是指,浏览器内部在发起如下请求时,该来源必须是当前同源的HTTP资源。如果两个URL同协议、同域名(ip相同也不行,没映射到ip)、同端口,就称这两个URL同源。
在浏览器中, <script> 、<img>、<iframe>、<link>
等标签可以跨域加载,而不受浏览器的同源策略的限制, 这些带herf / src属性的标签每次加载的时候,实际上都是浏览器发起一次GET请求, 不同于普通请求(XMLHTTPRequest)的是,通过src属性加载的资源,浏览器限制了JavaScript的权限,使其不能读写src加载返回的内容。
跨域资源共享规范中规定除了GET的HTTP请求以及搭配某些MINE类型的POST请求,其他http请求发起时,浏览器都需要预先发送option请求到你所请求的服务器,判断服务器是否支持跨域请求,如果支持,浏览器则继续正常发送post等请求,如果不支持,则浏览器无法正常发送post等请求。(按这个逻辑get是不会触发跨域的,但有时候有些环境下get可能也会触发跨域)
不同域之间的访问就叫跨域,因为浏览器同源策略的限制,导致我们在不同源之间通信,出现了浏览器接受不到服务端返回数据的问题,这也是目前前后端分离的项目必须要解决的问题
同源策略的限制:
浏览器的同源策略目的是为了保护用户的信息安全,为了防止恶意网站窃取用户在浏览器上的数据,如果不是同源的站点,将不能进行如下操作 :
Cookie、LocalStorage 和 IndexDB 无法读写
DOM 和 Js对象无法获得
AJAX请求不能发送(一般而言来自一个源的js只能向自己源的接口发送请求,不能向其他源的接口发送请求)
解决跨域请求的方法:可通过前端和后端两种方式来解决,但通常倾向于在后端进行解决。不同的后端框架解决的方式会有所不同,但原理都是通过配置允许跨域请求访问
解决跨域的方法:
1.通过jsonp跨域 (jq的封装的ajax前端,原理是利用<script>
标签)
利用iframe思想配合的三种形式:
2.iframe+document.domain:该方法只适合子域相同,主域不同的情况,在两个页面都设置document.domain=‘子域’,其中一个页面嵌套另一个页面,就可以进行窗口之间的通信了。
3.iframe+location.hash:通过改变location.hash的值,并不会导致页面刷新
4.iframe+window.name
5.利用H5的postMessage 方法和 onmessage 事件解决跨域问题
6.配置跨域资源共享(CORS) (服务端解决,实际开发最常用,客户端也要做少量工作)
(CORS,全称Cross-Origin Resource Sharing ,是一种允许当前域(domain)的资源(比如html/js/web service)被其他域(domain)的脚本请求访问的机制)
操作是服务端需要设置以下响应头:
Access-Control-Allow-Origin:http://www.admin.minhung.me // 一般用法(*,指定域,动态设置),*不允许携带认证头和cookies
Access-Control-Allow-Credentials: true // 是否允许后续请求携带认证信息(如:cookies),该值只能是true,否则不返回
Access-Control-Max-Age: 1800 //预检结果缓存时间,也就是上面说到的缓存,单位:秒
Access-Control-Allow-Methods:GET,POST,PUT,POST // 允许的请求动词, GET|POST|PUT|DELETE
Access-Control-Allow-Headers:x-requested-with,content-type //允许的请求头字段
7.Nginx反向代理(nginx作为代理服务器(中间人,客户端和目标服务器之间通过代理服务器访问),部署实际项目需要用Nginx,nginx相当于单独的工具,中间人,后端人员操作去监听前端地址反向代理到后端地址)
8.前端配置代理api(即proxy,vue.config.js 中配置devServer,开发时常用, 如果发布成产品 ,不会使用,思想也是Nginx的反向代理)
注:因为服务器与服务器之间不存在跨域,所以通过设置代理服务器(协议、域名、端口)去访问目标服务器,然后代理服务器返回数据就不存在跨域。
9.nodejs中间件代理跨域
10.利用H5的websocket协议,实现浏览器与服务器的全双工通信,同时允许跨域通讯。
浏览器从输入 URL 到页面加载发生了什么
1.浏览器查找缓存,如果缓存中有则直接显示页面,如果没有会进行下一步
2.根据url通过dns解析域名,获取ip地址
3.浏览器发起tcp连接请求,进行三次握手
4.三次握手成功后,浏览器向服务后发送http请求
5.浏览器接收数据并进行页面渲染
6.四次挥手断开tcp连接