• JavaScript基础概念之----跨域


    浏览器对于javascript的同源策略的限制,出现了跨域。

    只要协议、域名、端口等不同,就会出现跨域:如下

    域名:
     主域名不同 http://www.a.com –>http://www.b.com
     子域名不同 http://www.m.a.com/index.html –>http://www.n.a.com/test.js
     域名和域名ip http://www.a.com/index.html –>http://188.44.77.98/test.js
    端口:
     http://www.a.com:8080/index.html–> http://www.a.com:9090/test.js
    协议:
     http://www.a.com:8080/index.html–> https://www.a.com:8080/test.js
    其他:
     1、端口和协议的不同,只能通过后台来解决
     2、localhost和127.0.0.1虽然都指向本机,但也属于跨域

    解决跨域有下面几种方法:

    • jsonp跨域(JSON with Padding 填充式JSON)
    • document.domain
    • wndow.name
    • postMessage
    • 后端修改header
    • nginx反向代理

    JSONP跨域

    只支持get请求。返回的是脚本代码(包含一个函数调用)。

    通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

    <script>
    function dosomething(jsonData){
        //处理获得的json数据
    }
    </script>
    <script src="http://xxx.com/test.jsp?callback=dosomething"></script>

    知道jsonp跨域的原理后我们就可以用js动态生成script标签来进行跨域操作了,而不用特意的手动的书写那些script标签。如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

    <script>
    $.getJSON('http://xxx.com/data.jsp?callback=?',function(jsonData){
        //处理获得的JSON数据
    })
    </script>

    document.domain

    浏览器中不同域的框架之间是不能进行js的交互操作的。

    比如,有一个页面,它的地址是http://www.example.com/a.html  , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

    <script>
    function onload(){
        var iframe = document.getElementById('iframe')
        
        //这里能获取到iframe里的window,但该window的属性和方法是不可用的
        var win = iframe.contentWindow
        //这里获取不到iframe里的document
        var doc = win.document
        //这里获取不到window的name
        var name = win.name
    </script>
    <iframe id="iframe" src="http://example.com/b.html" onload="onload()"></iframe>

    我们只要把http://www.example.com/a.htmlhttp://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。

    在页面 http://www.example.com/a.html 中设置document.domain:

    <iframe id="iframe" src="http://example.com/b.html" onload="test()"></iframe>
    <script>
    document.domain = 'example.com'; // 设置成主域
    function test(){
        alert(document.getElementById('iframe').contentWindow)
    </script>

    在页面 http://example.com/b.html 中也设置document.domain,而且这也是必须的,虽然这个文档的domain就是example.com,但是还是必须显示的设置document.domain的值:

    <script>
    document.domain = 'example.com'; // 也设置成主域
    </script>

    window.name

    window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。

    window.name的值只能是字符串的形式。

    比如有一个www.example.com/a.html页面,需要通过a.html页面里的js来获取另一个位于不同域上的页面www.cnblogs.com/data.html里的数据。

    data.html页面里的代码很简单,就是给当前的window.name设置一个a.html页面想要得到的数据值。data.html里的代码:

    <script>
    window.name = '我是页面a.html需要的数据'
    </script>

    在a.html页面中使用一个隐藏的iframe来充当一个中间人角色,由iframe去获取data.html的数据,然后a.html再去得到iframe获取到的数据。把这个iframe的src设为www.cnblogs.com/data.html就行了。还必须把这个iframe的src设成跟a.html页面同一个域才行,不然根据前面讲的同源策略,a.html是不能访问到iframe里的window.name属性的。这就是整个跨域过程。

    <script>
    function getData(){
        var iframe = document.getElementById('proxy')
        iframe.onload = function(){
            var data = iframe.contentWindow.name;
            alert(data)
        }
        iframe.src = 'b.html'
    }
    </script>
    
    <iframe id="proxy" src="http://www.cnblogs.com/data.html" style="display:none;" onload="getData()"></iframe>

    window.postMessage

    是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源。

    调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 *  。

    需要接收消息的window对象,可是通过监听自身的message事件来获取传过来的消息,消息内容储存在该事件对象的data属性中。

    //这是 页面 http://test.com/a.html 中的代码
    
    <script>
    function onLoad(){
        var iframe = document.getElementById('iframe')
        var win = iframe.contentWindow;//获取window对象
        win.postMessage('我是来自a.html的消息')//向不同域页面发送消息
    }
    </script>
    <iframe id="iframe" src="http://www.test.com/b.html" onload="onLoad()"></iframe>
    //这是 页面http://www.test.com/b.html的代码
    
    <script>
    window.onmessage = function(e){ //注册message事件来接收消息
        e = e || event;//获取事件对象
        alert(e.data)//通过data属性得到传送的消息
    }
    </script>

    后端修改header

    header(‘Access-Control-Allow-Origin:*’);//允许所有来源访问

    header(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式

    nginx反向代理

    Nginx配置

    server{
        # 监听9099端口
        listen 9099;
        # 域名是localhost
        server_name localhost;
        #凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 
        location ^~ /api {
            proxy_pass http://localhost:9871;
        }    
    }

    网上更详细的资源:https://segmentfault.com/a/1190000015597029

  • 相关阅读:
    destroy-method="close"
    2.2 Spring的结构组成--Spring源码深度解析
    2.1 Spring容器的基本实现--Spring源码深度解析
    1.2 Spring环境搭建--Spring源码深度解析
    1.1 Spring的整体架构--Spring源码深度解析
    迟到的2016年计划
    spring学习 之helloworld
    从零实现DNN 探究梯度下降的原理
    Java注解——这些@圈圈都是个啥?
    自动发送日报,骗过你的领导^-^
  • 原文地址:https://www.cnblogs.com/adhehe/p/9792187.html
Copyright © 2020-2023  润新知