同源策略及跨域的解决方案

同源策略的基本概念

同源策略简介:1995年,同源政策由Netscape引入浏览器,目前,全部的浏览器都实行这个政策.javascript

同源:指的是协议,域名,端口号相同都称为是同源网站css

同源策略的目的html

同源策略的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据前端

同源策略的限制范围html5

随着互联网的发展,'同源策略'愈来愈严格,目前,若是非同源,下面的行为将会受到限制:java

  1. Cookie、LocalStorage 和 IndexDB 没法读取。
  2. DOM 没法得到。
  3. AJAX 请求在浏览器端有跨域限制

虽然这些限制是保证了数据的安全性,可是同时他也给开发者带来了必定的困扰,因为网络的不断发展,不一样公司的业务更加庞大,所须要的技术也更加精准,因此各个部门都会有本身的域名,这时就会出现跨域现象ajax

解决跨域的方案

方法一JSONP:json

JSONP(JSON with Padding)、可用于解决主流浏览器的跨域数据访问的问题。后端

因为DOM中的src属性支持跨域,因此JSONP的原理也就是利用了script标签中的src来实现跨域的,除了script标签以外,还有img和link标签.api

<!--不受同源策略限制的标签-->
<img src="http://www.api.com/1.jpg" alt="">
<link rel="stylesheet" href="http://www.api.com/1.css">
<script src="http://www.api.com/1.js"></script>
复制代码

JSONP实现代码

<script> var inp = document.getElementById('inp'); var ul = document.querySelector('ul'); function suggest_so(data){ // console.log(data) ul.innerHTML ='' var {result} = data; result.forEach(function(ele){ var li = document.createElement('li'); li.innerHTML = ele.word; ul.appendChild(li) }) } inp.oninput = function(){ if(document.getElementsByClassName('ss').length>0){ document.getElementsByClassName('ss')[0].remove() } var val = inp.value; // 经过动态建立src属性实现 var jsonp = document.createElement('script'); jsonp.src = 'https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word='+val; jsonp.className = 'ss'; document.body.appendChild(jsonp) } </script>

复制代码

在script属性中有一个src属性,里面有一个callback回调函数,这个回调函数是在src里面的,他的做用就是当响应来到时,应该在页面中调用的函数,而数据就是传入回调函数的JSON数据.

JSONP实现原理

  • 1)利用了script的src属性支持跨域访问
  • 2)script标签的后面须要写上须要请求的页面,发送了一个方法的名字到服务器.
  • 3)服务器接收到名字以后,拼接一个方法的调用在参数中传入须要给浏览器的数据
  • 4)返回浏览器,浏览器把他们当js解析,没有跨域问题,从服务器获取数据
原理:服务端返回一个定义好的js函数的调用,而且将服务器的数据以该函数参数的形式传递过来,这个方法须要先后端配合.
复制代码

jQuery实现跨域

$(function(){
  $('#inp').on('input',function(){
    $.ajax({
      url:'https://sug.so.360.cn/suggest?callback=suggest_so&encodein=utf-8&encodeout=utf-8&format=json&fields=word&word='+$(this).val(),
      dataType:'jsonp',
      jsonpCallback:'suggest_so',
      success:function(data){
        var {result} = data;
        var str = template('tpl',{result});
        $('ul').html(str)
      }
    })
  })
})
复制代码

这里用的是dataType和jsonpCallback,来实现跨域

JSONP的缺点:

  • 1它只支持GET请求而不支持POST等其它类型的HTTP请求
  • 2它只支持跨域HTTP请求这种状况,不能解决不一样域的两个页面之间如何进行JavaScript调用的问题。
  • 3 jsonp在调用失败的时候不会返回各类HTTP状态码。
  • 4缺点是安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制的。那么结果是什么?全部调用这个 jsonp的网站都会存在漏洞。因而没法把危险控制在一个域名下…因此在使用jsonp的时候必需要保证使用的jsonp服务必须是安全可信的。

只支持get请求的缘由:

因为script标签只能发送get请求 因此jsonp不支持post方式的跨域

方法二CORS: 具体流程: 浏览器发送跨域请求

服务器端收到一个跨域请求后,在响应头中添加Access-Control-Allow-Origin Header资源权限配置。发送响应

浏览器收到响应后,查看是否设置了header('Access-Control-Allow-Origin:请求源域名或者*');

若是当前域已经获得受权,则将结果返回给JavaScript。不然浏览器忽略这次响应。

app.get('/getmsg',(req,res)=>{
    let msg =[{name:'zs',age:18,gender:'boy'}];
    res.header('Access-Control-Allow-Origin',"*")
    res.json({msg:'ok',code:200,data:msg})
})
复制代码

这种方法虽然简单,可是这种方法是h5新出的,因此这种方法有兼容性问题

方法三Nginx:

同源策略只是针对的浏览器端,因此这里经过服务端反向代理的方式实现跨域, Nginx解决跨域问题经过Nginx反向代理将对真实服务器的请求转移到本机服务器来避免浏览器的"同源策略限制"。

方法四:

window.name+iframe 须要目标服务器响应window.name。

方法五:

window.location.hash+iframe 一样须要目标服务器做处理。

方法六:

html5的 postMessage+ifrme 这个也是须要目标服务器或者说是目标页面写一个postMessage,主要侧重于前端通信。

HTML5为了解决这个问题,引入了一个全新的API:跨文档通讯 API(Cross-document messaging)。

这个API为window对象新增了一个window.postMessage方法,容许跨窗口通讯,不论这两个窗口是否同源。

举例来讲,父窗口http://aaa.com向子窗口http://bbb.com发消息,调用postMessage方法就能够了。

var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');
复制代码

postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也能够设为*,表示不限制域名,向全部窗口发送。

子窗口向父窗口发送消息的写法相似。

window.opener.postMessage('Nice to see you', 'http://aaa.com');
复制代码

方法七:

Cookie 是服务器写入浏览器的一小段信息,只有同源的网页才能共享。可是,两个网页一级域名相同,只是二级域名不一样,浏览器容许经过设置document.domain共享 Cookie。

举例来讲,A网页是http://w1.example.com/a.html,B网页是http://w2.example.com/b.html,那么只要设置相同的document.domain,两个网页就能够共享Cookie。

document.domain = 'example.com';
复制代码

如今,A网页经过脚本设置一个 Cookie。

document.cookie = "test1=hello";
复制代码

B网页就能够读到这个 Cookie。

var allCookie = document.cookie;
复制代码

注意,这种方法只适用于 Cookie 和 iframe 窗口,LocalStorage 和 IndexDB 没法经过这种方法,规避同源政策,

相关文章
相关标签/搜索