• 跨域&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 的响应头,表示这个资源是否允许指定域请求(*代表任何网站都可以访问)。

  • 相关阅读:
    21.Merge Two Sorted Lists 、23. Merge k Sorted Lists
    34. Find First and Last Position of Element in Sorted Array
    leetcode 20. Valid Parentheses 、32. Longest Valid Parentheses 、301. Remove Invalid Parentheses
    31. Next Permutation
    17. Letter Combinations of a Phone Number
    android 常见分辨率(mdpi、hdpi 、xhdpi、xxhdpi )及屏幕适配注意事项
    oc 异常处理
    oc 类型判断
    oc Delegate
    oc 协议
  • 原文地址:https://www.cnblogs.com/linqb/p/9535975.html
Copyright © 2020-2023  润新知