zoukankan      html  css  js  c++  java
  • 跨域请求的常用方式及解释

    同源策略

    首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个域加载的脚本去获取另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。这意味着浏览器隔离来自不同源的内容,以防止它们之间的操作。

    js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据。

    只要协议、域名、端口有任何一个不同,都被当作是不同的域。

    下面介绍几种常用的跨域请求方式

    默认端口为:8080

    一、利用jQuery获取jsonp

    JSONP的原理与实现思路

    1)Web页面调用js文件,可跨域。扩展:但凡有src属性的标签都具有跨域能力。
    2)跨域服务器 动态生成数据 并存入js文件(通常json后缀),供客户端调用。
    3)为了便于客户端使用数据,形成一个非正式传输协议,称为JSONP。该协议重点是允许用户传递一个callback参数给服务器,然后服务器返回数据时 将此callback参数作为函数名包裹住JSON数据,使得客户端可以随意定制自己的函数来自动处理返回数据。

     1.1如果我们不用跨域请求的写法的话:

    $('#cors1').click(function () {
        $.ajax({
            type:'get',
            url:'http://localhost:8081/girl/hello/say',
            success:function (data) {
                console.log(data);
            }
        })
    });

    1.2使用跨越请求的写法,最简单的就是设置dataType:jsonp:

    jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数名称。

    这里的success默认success()作为回调函数。数据返回到前端后,就是success(result)的形式,因为是script脚本,所以自动调用success函数,而result就是success的参数。

    $('#cors1').click(function () {
        $.ajax({
            type:'get',
            dataType: 'jsonp',
            url:'http://localhost:8081/girl/hello/say',
            success:function (data) {
                console.log(data);
            }
        })
    });
        @RequestMapping(value="/say", method = RequestMethod.GET)      //后端代码
        public String say(@RequestParam("callback") String callback){
    
            //callback前端传过来的回调函数名称
    
            //数据
            String result = "{age:22}";
            
            //用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了
            result = callback + "(" + result + ")";
            return result;
            
        }

     

    1.3jsonpCallback

    为jsonp请求指定一个回调函数名。这个值将用来取代jQuery自动生成的随机函数名。

    调用回调函数的时候,先调用了指定的showData,然后再调用了success。

    $('#cors1').click(function () {
        $.ajax({
            type:'get',
            dataType: 'jsonp',   //指定服务器返回的数据类型 
            jsonpCallback: 'showData',    //指定回调函数名称
            url:'http://localhost:8081/girl/hello/say',
            success:function (data) {
                console.log(data);
            }
        })
    });
    
    function showData(data) {
        console.log("show"+data);
    }

    1.4jsonp

    在一个jsonp请求中重写回调函数的名字。这个值用来替代在"callback=?"这种GET或POST请求中URL参数里的"callback"部分,比如{jsonp:'onJsonPLoad'}会导致将"onJsonPLoad=?"传给服务器。

    $('#cors1').click(function () {
        $.ajax({
            type:'get',
            dataType: 'jsonp',
            jsonpCallback: 'showData',
            jsonp: 'sendParam',  //指定参数名称
            url:'http://localhost:8081/girl/hello/say',
            success:function (data) {
                console.log(data);
            }
        })
    });
    
    function showData(data) {
        console.log(data);
    }

    指定jsonp后,后端也要改变:

        @RequestMapping(value="/say", method = RequestMethod.GET)
        public String say(@RequestParam("sendParam") String sendParam){
    
            //sendParam前端传过来的回调函数名称
    
            //数据
            String result = "{age:22}";
    
            //用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了
            result = sendParam + "(" + result + ")";
            return result;
    
        }

    1.5jsonp方式不支持POST方式跨域请求,就算指定成POST方式,会自动转为GET方式;而后端如果设置成POST方式了,那就请求不了了。

    二、设置CORS头“Access-Control-Allow-Origin”

    •  CORS的原理:
         CORS定义一种跨域访问的机制,可以让AJAX实现跨域访问。CORS 允许一个域上的网络应用向另一个域提交跨域 AJAX 请求。实现此功能非常简单,只需由服务器发送一个响应标头即可。
     
    $('#cors1').click(function () {
        $.ajax({
            type:'get',
            url:'http://localhost:8081/girl/hello/say',
            success:function (data) {
                console.log(data);
            }
        })
    });
        @RequestMapping(value="/say", method = RequestMethod.GET)
        public String say(HttpServletRequest request, HttpServletResponse response){
            //设置响应头
            response.setHeader("Access-Control-Allow-Origin","*");  //当前我设置的header为“*”,任意一个请求过来之后服务端我们都可以进行处理&响应
        // 指定特定域名可以访问
           response.setHeader("Access-Control-Allow-Origin", "http:localhost:8080/")
    //数据
            String result = "{age:22}";
            return result;
        }

     

    三、iframe+window.postMessage实现跨域

    script、image、iframe的src都不受同源策略的影响。所以我们可以借助这一特点,实现跨域。

    postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。

    发送消息

    postMessage(data,origin)方法接受两个参数

     1.data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果。

    2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

    <iframe id="ifr" src="http://localhost:8081/girl/b.html"></iframe>
    window.onload = function () {
        var ifr = document.getElementById("ifr");
        ifr.contentWindow.postMessage("crsf","http://localhost:8081");
    };

    接收消息

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>testb</title>
    </head>
    <body>
        <div>b</div>
    </body>
    </html>
    <script>
    window.addEventListener('message', function(event){
    console.log('origin: '+event.origin);    //origin: http://localhost:8080
    console.log('data: '+event.data);      //data: crsf
    console.log(event.source);
    // 回发数据
    event.source.postMessage('hello world', event.origin);
    });
    </script>

    有几个重要属性

    1. origin:发送消息窗口的源(协议+主机+端口号)
    2. data:顾名思义,是传递来的message
    3. source:发送消息的窗口对象

    这样就可以接收跨域的消息了,我们还可以发送消息回去。

  • 相关阅读:
    Java-Class-C:com.alibaba.fastjosn.JSON.java
    兆芯笔试题(2015)找反复数最多的字母的数量以及位置
    获得文件属性的函数调用实例
    错了:用流量能够放肆,有wifi则要节制
    为什么会找不到D层文件?
    Cocos2d-x3.0游戏实例之《别救我》第六篇——从代码中获取UI控件
    Add Binary
    【iOS开发之Objective-C】书签管理器项目
    UVa 11732 strcmp() Anyone?
    【打CF,学算法——二星级】Codeforces Round #313 (Div. 2) B. Gerald is into Art(水题)
  • 原文地址:https://www.cnblogs.com/chaixiaozhi/p/8545462.html
Copyright © 2011-2022 走看看