常用的跨域方法

作者 糖一瓶 日期 2018-01-11
常用的跨域方法

什么是跨域技术?

比如我们现在本机地址是127.0.0.1 我们想请求127.0.0.2上的数据 
我们无法使用ajax来实现这样的跨域的数据请求
浏览器会阻止对ip地址不同,或者端口号不同的数据请求。
此时我们必须要进行请求,就是跨域技术。
所以这里介绍几种常见的跨域方法

一、JSONP跨域

JSONP叫做JSON 和 padding
  1. 我们写一个接口,这个接口不是一个JSON,而是一个语句,这个语句是函数的调用
    1
  2. 在页面上,我们定义一个函数,然后用script标签引入这个语句,执行这个语句。
    此时数据就通过函数的实参和形参的结合,传入了页面。

    <!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>
    </head>
    <body>
    <script>
    // 定义函数
    function haha(info){
    console.log(info);
    }
    </script>
    // 创建script标签
    <script src="http://127.0.0.2/a.txt"></script>
    </body>
    </html>
    • script没有跨域限制的,可以轻松src引入其他ip地址的js文件。
    • 关于script的相关知识
      script标签仅在创建的时候发生HTTP请求 更改src属性时是不发出请求的
      所以script标签是一次性的,用完删掉她再用时再重新创建

JQuery中写法:

<!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>
</head>
<body>
<button>按我发出请求</button>

<script src="jquery-3.3.1.min.js"></script>
<script>
$("button").click(function(){
$.ajax({
"dataType" : "JSONP" ,
"url" : "http://127.0.0.2/a.php?callback=?",
"success" : function(data){
console.log(data);
}
})
});
</script>
</body>
</html>

小总结:

  1. 请求一个接口,接口中的数据形式是一个函数的调用
  2. 接口中是函数的调用所以在本地我们要创建相应的函数
    需要注意的是:在JSONP跨域时,函数是没有声明提升的,所以函数的定义必须写在script标签创建之前
  3. script标签没有跨域限制,所以我们通过src引入其他ip地址的文件实现跨域请求数据
    需要注意:script标签是在创建的那一刻调用,调用一次后就失效了,想再次使用必须重新创建
    所以我们最好要动态的生成script标签,上树过后立即下数

二、CORS跨域

这是最最简单的跨域方法,但是IE8才开始兼容。
火狐MDN的解释

重点
跨域资源共享( CORS , cross-origin resource sharing)机制允许 Web 应用服务器进行跨域访问控制,
从而使跨域数据传输得以安全进行。
浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。

说白了,就是在HTTP下行响应的头部加上了一些头部:
2
我们一般:就加Access-Control-Allow-Oringin值为*

以node.js为服务器
所以我们的express代码加一行代码:

app.get("/a" , function(req,res){
res.setHeader("Access-Control-Allow-Origin" , "*");
res.json({"a" : 100})
});
表示允许来自任何域名的请求。

此时我们就能无脑跨域了!因为后端有一个允许的*,表示允许任何域的请求。
$.get("http://127.0.0.1:3000/a", function(data){
console.log(data);
})

三、代理跨域

比如用PHP实现(了解即可)这就代理到了百度首页:

<?php
echo file_get_contents("http://www.baidu.com");
?>

代理跨域就是通过后台的命令,因为服务器与服务器之间没有跨域限制,实现跨域。

以webpack为例,详细说一下代理跨域:
你的webpack.config.js中添加配置

const path = require('path');

module.exports = {
entry: "./www/app/main.js",
output: {
path: path.resolve(__dirname, "www/dist"),
filename: "bundle.js",
publicPath: "/xuni/"
},
mode : "development",
module: {
rules: [
{
test: /\.js$/,
include: [
path.resolve(__dirname, "www/app")
],
exclude: [
path.resolve(__dirname, "node_modules")
],
loader: "babel-loader",
options: {
presets: ["es2015","react"],
plugins: ["transform-object-rest-spread"]
}
}
]
},
// 就这里就这里 我的服务端放在了3000端口
devServer: {
proxy: {
"/api": {
target: 'http://127.0.0.1:3000/',
changeOrigin: true,
pathRewrite: {
'^/api': '/'
}
}
}
}
}

这配置是从webpack官网上来的,你就拿来主义即可。
我的服务端放在了3000端口,我的前端在8000端口
现在加上了上边的配置后,我在3000端口下的数据,将会被代理到8000/api下
这样从本质上讲,因为数据已经被代理到了8000端口下,我们在前段请求数据的时候,就已经不是跨域请求了。