实现跨域访问的2种方案:Cors , Jsonp

254 阅读2分钟

在了解跨域访问之前,先说一下浏览器的安全策略。

浏览器的安全策略:不允许非同源的数据相互访问的,例如京东和淘宝等不同平台之间。

但在我们的生活中,我们会发现,其实我们可以在一个网站去浏览另一个网站的资源,这就是跨域访问。虽然浏览器默认不允许,但是我们可以人为的去改变它。

那么什么是同源呢?

同源:大家都知道一个url是由 协议://域名:端口/路径名称?查询字符串#位置标识符组成,同源就是要求域名,协议,端口完全一致,这三个有任何一个不一样都是不同源的。

Cors

CROS(Cross-Origin Resource Sharing) 用于解决浏览器中跨域请求的问题。简单的Get请求可以使用JSONP来解决,下面将会讲到jsonp,而对于其它复杂的请求则需要后端应用的支持CROS。简单的说,cros是后端平台需要支持的。上代码:

以下是php代码:

<?php
header("Access-Control-Allow-Origin:*");

$id = $_GET['id'];


$info = array(
    "id" => $id,
    "name" => "孙颖",
    "like" => "运动",
    "time" => 120
);
echo json_encode($info);

?>

其实就是在服务器端:设置响应头信息:header("Access-Control-Allow-Origin:*");

下面是前端html代码:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>Document</title>
   <script src="utils.js"></script>
</head>
<body>
   <button onclick="Message()">发送请求</button>
   <script>
   let btn = document.getElementById('id');
   function Message(){
       let id = prompt();
       utils.ajaxget('http://localhost/day24ajax/01.cors.php',{id},function(resp){
           console.log(resp);
           
       })
   }
   
   </script>
</body>
</html>

此处的 utils.ajaxget('http://localhost/day24ajax/01.cors.php',{id},function(resp){ console.log(resp);

    })

是我上篇文章中封装好的函数,我是直接调用,也可以用utils.ajaxpost()来调用,相应的在php代码中更改请求的方式就可以了。**(想要了解 ajaxget() 和 ajaxpost())**的可以看看我的上篇文章。

Jsonp

jsonp,主要是前端的开发工作人员会用得比较多,主要是利用src的开放性原则,而jsonp则是利用了的src引入外部JS时不受同源策略限制的特性,来实现跨域。但jsonp只支持get请求方式的跨域。

后端:由服务器端构建一个字符串:字符串中的内容是能够在 JS 中执行的函数调用的结构。

<?php

$id = $_GET['id'];
$cb = $_GET['cb'];

$shop = array(
  "id" => $id,
  "name" => "孙颖",
  "like" => "运动"
);

$str = json_encode($shop);

echo "$cb($str)";

?>

前端主要的实现步骤:

  • 创建<script>标签元素
  • 设置 src 属性,传递 callback 参数指明全局回调函数的名称
  • 添加到 body 中
  • 创建全局函数,用于处理响应数据
  • 删除 <script> 标签元素
/**ajax jsonp请求
   * 
   * @param {string} url     请求的路径
   * @param {string} cb      回调函数名(这个函数必须是全局函数)
   * @param {object} [query] 其他参数
   */
  ajaxjsonp (url, cb, query) {
    // 创建script标签
    url += `?cb=${cb}`
    if (query) {
      for( var key in query) {
        url += `&${key}=${query[key]}`
      }
    }
    var script = document.createElement('script')
    script.src = url
    document.body.appendChild(script)
    // 过河拆桥
    document.body.removeChild(script)
  }

下面是html代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="utils.js"></script>
</head>
<body>
        <button onclick="sendMsg()">发送请求</button>
   <script>
     function callback(obj){ //回调
         console.log(obj);   //得到输出内容
         
     }
     function sendMsg (){
         const id = prompt()
         utils.ajaxjsonp('http://localhost/day24ajax/02.jsonp.php','callback',{id});
     }
    
    </script>
</body>
</html>

如有错误,请大佬名告之,写得不好,请各位大佬指正。