同源策略,跨域问题

同源策略:

1.源:由协议,域名,端口号组合而成。

2,同源:即地址中的协议,域名和端口号均相同。

3.同源策略:同源策略是浏览器的一个安全功能,不同源的客户端在没有明确授权的情况下,不能读写对方的资源。

4.不同源:地址中的协议,域名或者端口,任意一个不同,都称其不同源。

5.受到同源限制:

  • 无法读取不同的Cookie,localStroage和indexDB.
  • 无法获取不同源的DOM.
  • 不能向不同源的服务器发送ajax请求。

6.不受同源限制:

  • 页面中的链接,重定向以及表单提交是不会受到同源策略的限制。
  • 在浏览器中,

跨域

What:

跨域问题,就是受同源策略的影响,不是同源的脚本不能操作其它源下的对象。想要操作另一个源下的脚本,就需要跨域。

How:

1. 降域:document.damain。如:

son1.a.com与a.com
son1.a.com与son2.a.com
child.son1.a.com与 son1.a.com

两两不同源,可以通过设置document.damain='a.com',浏览器就会认为它们都是同一个源。想要实现两个页面之间的任意通信,两页面均要设置document.damain='a.com'.

此方式的特点:

  • 只能在父域名和子域名之间使用,且将 child.son1.a.com设置成a.com之后,就不能再设置成son1.a.com
  • 存在安全问题,当一个站点被攻击,另一个站点就会引起安全漏洞。
  • 使用的局限性,只适用于Cookie和iFrame窗口。

2.JSONP跨域

JSONP和JSON没有任何关系!
JSONP原理:(举例:a.com/jsonp.html想得到b.com/main.js中的数据)。在a.com的jsonp.html里创建一个回调函数XXX,动态添加<script>元素,向服务器发送请求,请求地址后面加上查询字符串,通过callback参数指定回调函数的名字。请求地址为http://b.com/main.js?callback=xxx。在main.js中调用这个回调函数XXX,并以JSONP数据形式作为参数传递,完成回调。

// a.com/jsonp,html中的代码:

function addScriptTag(src) { 
    var script = document.createElement('script'); 
    script.setAttribute("type","text/javascript"); 
    script.src = src; 
    document.body.appendChild(script);
    }
    window.onload = function () { 
    addScriptTag('http://b.com/main.js?callback=foo');
    } //window.onload是为了让页面加载完成后再执行
    function foo(data) { 
    console.log(data.name+"欢迎您");
    };

//b.com/main.js中的代码:foo({name:"hi})
这样就实现了跨域的参数传递。

采用jsonp跨域存在的问题:

1.使用此方法,每个网站都可以拿到数据,存在安全性问题。需要网站双方商议基础的token身份验证。
2.只能是get,不能是post.
3.可能被注入恶意代码,篡改页面内容,可以采用字符串过滤来规避此问题。

3.CORS

CORS是一个W3C标准,全称是:跨域资源共享。它允许浏览器向资源服务器发出XMLHttpRequest请求,从而客服AJAX只能同源使用的限制。

在刚才的例子中,在b.coml里面添加响应头声明允许a.com的访问代码Access-Control-Allow-Origin: http://a.com然后a.com就可以用ajax获取b.com里的数据了。

4.window.name跨域

浏览器窗口有window.name属性。这个属性的特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属性,后一个网页可以读取它。比如,你在b页面里设定window.name="hello"你在返回到a页面的时候,访问window.name,可以得到hello.

eg:现在浏览器的一个标签页里打开http://www.damonare.cn/a.html页面,你通过location.href=http://baidu.com/b.html,在同一个浏览器标签页里打开了不同域名下的页面。这时候这两个页面你可以使用window.name来传递参数。因为window.name指的是浏览器窗口的名字,只要浏览器窗口相同,那么无论在哪个网页里访问值都是一样的。

特点:window.name容量很大,可以放置非常长的字符串;但是必须监听子窗口window.name属性的变化,影响网页性能。

5.postMessage方法跨域

HTML5中引入了一个全新的API,跨文档通信的API。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。a可以把它的LocalStorage,发送给b,b也可以把自己的LocalStorage发送给a.

  • window.postMessage(message, targetOrigin, [transfer]),有三个参数
  1. message,向目标窗口发送的数据;
  2. targetOrgin,来指定哪些窗口能接收到消息事件,可以是一个URL(发送消息的目标域名)。
    3.transfer可选参数,是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
  • 接受消息放必须有监听事件,负责发送消息时就会报错。window.addEventListener("message",onmessage)onmessage

eg:在a页面执行

var popup = window.open('http://localhost:3000', 'title');
 popup.postMessage('Hello World!', 'http://localhost:3000');

同时在http://localhost:3000
的页面里监听message事件。

window.onload=function () {
      window.addEventListener("message",onmessage);
}
function onmessage(event) {
      if(event.origin=="http://localhost:63343"){//http://localhost:63343是发送方a的域名
          console.log(event.data);//'Hello World!'
      }
      console.log(event.data);//'Hello World!'
}

6.location.hash跨域

location.hash就是指URL的#后面的部分。

父窗口改变子窗口的Url的#号后面的部分,后者把要传递的参数写在#后面,子窗口监听window.onhashchange事件,读取window.location.hash解析出有用的数据。子窗口也可以向父窗口传递数据。

参考资料1
参考资料2

猜你喜欢

转载自blog.csdn.net/qq_39083004/article/details/79579087