• 跨域&JSONP


    1. 同源&跨域

    1.1 什么是同源?什么是跨域?

    • 同源:协议头、域名、端口完全一致就叫同源

    • 跨域:协议头、域名、端口有一个不一样就叫跨域

    • 判断是否同源,如:http://www.example.com/detail.html 与以下地址对比

    对比地址是否同源原因
    http://api.example.com/detail.html 不同源 域名不同
    https://www.example.com/detail.html 不同源 协议不同
    http://www.example.com:8080/detail.html 不同源 端口不同
    http://api.example.com:8080/detail.html 不同源 域名、端口不同
    https://api.example.com/detail.html 不同源 协议、域名不同
    https://www.example.com:8080/detail.html 不同源 端口、协议不同
    http://www.example.com/other.html 同源 只是目录不同

     

     

     

     

     

     

     

     

     

    1.2 跨域的影响

    • 注:根据同源和跨域的意思,跨域就是指不同源
    • 如果要在 localhost/test.html 这个网站上访问 http://api.douban.com/v2/movie/top250 这个接口,那么浏览器会出现以下错误:

    • 原因:浏览器本身从安全角度考虑,不支持跨域访问

    2. JSONP

    2.1 如何突破跨域请求限制

    2.1.1 使用img标签(拿不到响应体)

    我们知道:img 标签,有个 href 属性,这个属性其实也是向服务器发送请求,我们看看这种方式是否可以跨越访问,代码如下:

    <img href="http://api.douban.com/v2/movie/top250" alt="">

    此时可以看到能正确收到响应,但拿不到响应体(返回的JSON数据),如图:

    2.1.2 使用link标签(拿不到响应体)

    link 标签,有个 src 属性,我们以前是用来外联css样式,其实它也是相当于发送请求

     <link rel="stylesheet" src="http://api.douban.com/v2/movie/top250"

     看浏览器响应报文,可以发现link标签也可以跨域请求,但是一样,没办法拿到响应体

    2.1.3 使用script标签(曲线拿到响应体)

    代码如下:

    1 <script>
    2     function test(json) {
    3         console.log('我被调用了');
    4         console.log(json);
    5     }
    6 </script>
    7 <script src="http://api.douban.com/v2/movie/top250?callback=test"></script>

    结果如下图

     说明:我们可以看到,我们预先定义了一个函数叫test,再然后在src里加了一个参数callback=test,可以发现,当请求完成,会自动调用test这个函数,并且把响应体(JSON数据)当做参数传递过来

    2.2 使用script标签拿到JSON数据

    2.2.1 script导入外部文件作用

    • 使用script导入外部文件时,默认会把文件内容当JS代码执行,例:

    • 新建 1.txt 文件,文件内容如下:

    alert('你好');
    • 新建 index.html 文件,核心代码如下:
    <script src="1.txt"></script>

    结果:

    结论:script导入文件会默认把文件内容当JS代码执行,跟文件格式无关

    2.2.2 script标签曲线拿到响应体原理

    • 新建 index.html 页面,代码如下
    1 <script>
    2     //声明一个success函数
    3     function success(obj){
    4         console.log(obj);
    5     }
    6 </script>
    7 <!-- script导入文件 -->
    8 <script src="http://www.demo.com/top250.php"></script>
    • 新建 top250.php 页面,代码如下
    echo "success('hello')";

    结果

    说明:请求的top250文件里,服务器最终返回的是 success('hello'); 这个当JS代码执行时,是调用函数并传递参数hello的语法,因此可以看到success函数被调用,并且打印了参数hello

    图解:

    ★★ 思考:如果在上例中,把success函数的参数换成json对象,会怎样?

    • 修改 top250.php 代码,如下:
    1     $data = array('name' => 'jack','age'=>16,'gender'=>'true' );
    2 
    3     $json = json_encode($data);
    4 
    5     echo "success({$json})"; 
    • 再次访问网页可以发现,打印的参数就变成了json对象

    结论:script标签拿到JSON数据的原理就是在服务器端写调用浏览器端函数的方法 ,然后把JSON数据当参数传递过去

    ★★ 思考:现在服务端代码这么写,如果要解决跨域问题,是不是每个浏览器端都要准备一个名叫success的函数?能让浏览器端自己指定吗?怎么指定?

    • 请求数据时加参数,修改 index.html
    1 <script>
    2     //声明函数
    3     function myFunc(obj){
    4         console.log(obj);
    5     }
    6 </script>
    7 
    8 <!-- 请求数据,并加入callback参数,值为myFunc -->
    9 <script src="http://www.demo.com/top250.php?callback=myFunc"></script>
    • 此时,除了请求 top250.php 外,还传递了个 callback 的参数过去,修改 top250.php,拿到这个参数
     1 <?php
     2 
     3     //拿到传递过来的参数,即函数名
     4     $funcName = $_GET['callback'];
     5 
     6     //准备数据
     7     $data = array('name' => 'jack','age'=>16,'gender'=>true );
     8 
     9     //转化为JSON
    10     $json = json_encode($data);
    11 
    12     //传过来的是什么函数名,就调用什么函数
    13     echo "$funcName($json)"; 
    14 ?>

    结果:此时就完成了指定函数名让服务器调用传参的效果了。

    这就是之前跨域拿数据的原理,即服务器端调用浏览器端的函数,把参数传递过来即可

    2.3 JSONP概念总结

    • JSONP:

      • JSON with Padding 是一种借助于script标签发送跨域请求的技巧方案。

    • 它不是一套新技术,只是聪明的程序员想出的一套方案

    • 能不能用这套方案,要看服务器端代码怎么写,服务器端如果写了调用函数的代码,那么就能支持JSONP方案

    • 服务器的接口会有接口文档进行说明是否支持JSONP

    • 建议:不要随意使用别人的接口,特别是别人写的支持JSONP的接口

      例:https://developers.douban.com/wiki/?title=api_v2

    3. CORS

    • Cross Origin Resource Share,跨域资源共享

    • 直接从服务器端解决ajax无法跨域访问的问题(可以不要用jsonp了)

    // 允许远端访问
    header('Access-Control-Allow-Origin: *');

    这种方案无需客户端作出任何变化(客户端不用改代码),只是在服务端添加一个 Access-Control-Allow-Origin 的响应头,表示这个资源是否允许指定域请求(*代表任何网站都可以访问)。

  • 相关阅读:
    LOJ#3157. 「NOI2019」机器人 DP+拉格朗日插值
    BZOJ4832 [Lydsy2017年4月月赛]抵制克苏恩 记忆化搜索
    LazySysAdmin 靶机渗透
    zico2靶机渗透
    6_面向对象-下之关键字:static
    5_面向对象-中之单元测试方法、包装类的使用
    5_面向对象-中之Object类的使用
    5_面向对象-中之面向对象的特征三:多态性
    5_面向对象-中之子类对象实例化全过程
    5_面向对象-中之关键字:super
  • 原文地址:https://www.cnblogs.com/linqb/p/9535975.html
Copyright © 2020-2023  润新知