前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >34·灵魂前端工程师养成-[前后分离]跨域、CORS、JSONP

34·灵魂前端工程师养成-[前后分离]跨域、CORS、JSONP

作者头像
DriverZeng
发布2022-10-31 18:10:43
1.2K0
发布2022-10-31 18:10:43
举报

-曾老湿, 江湖人称曾老大。


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。


跨域

跨域的关键知识点:

同源策略 浏览器故意设计的一个功能限制

CORS 突破浏览器限制的一个方法

JSONP

IE时代的妥协

同源策略


什么是同源?

window.origin或location.origin可以得到当前源。

代码语言:javascript
复制
window.origin
"https://www.baidu.com"

location.origin
"https://www.baidu.com"

源=协议 + 域名 + 端口号

如果两个URL的协议域名端口号完全一致,那么这两个url就是同源的

例如:

https://www.qq.com https://www.baidu.com 不同源 http://www.baidu.com https://www.baidu.com 不同源 完全一致,才算同源


同源策略定义

浏览器规定,如果JS运行在源A里,那么就只能获取源A的数据,不能获取源B的数据,即不允许跨域访问。

例如: 架设 driverzeng.com/index.html 引用了 linuxgc.com/1.js 那么就说 1.js 运行在源driverzeng.com里 注意:这跟linuxgc.com没有关系,虽然1.js从那个域名下载。 所以1.js就只能获取driverzeng.com的数据 不能获取www.driverzeng.com或download.driverzeng.com的数据

这是浏览器的功能,浏览器故意这么设计的。

浏览器为什么这样做?

用来保护用户的隐私。

我们试想,如果没有同源策略,会怎样?

以QQ空间为例 源:https://user.qzone.qq.com 假设,当前用户已经登录(用cookie) 假设,AJAX请求/friends.json就可以获取用户好友列表 到目前为止都很正常

黑客来了 假设你的女神分析https://user.qzone-qq.com给你。 实际上这是一个钓鱼网站,你点开这个网页,这个网页也去请求你的好友列表 https://user.qzone.qq.com/friends.json 请问,你的好友列表是不是就就被黑客,偷摸的偷走了?


问题的根源

无法区分发送者 QQ空间面里的JS和黑客网页里面的JS发的请求几乎没有区别(Referer有区别),如果后台开发者没有检查referer那么就完全没有区别。所以,没有同源策略,任何页面都能偷QQ空间的数据,甚至支付宝余额

那检查referer不就好了? 安全原则,安全链条的强度取决于最弱一环,万一这个网站后端开发,是一个傻X呢?所以浏览器应该主动预防这种投数据的行为,总之,浏览器是为了用户隐私,设置了严格的同源策略。

同源策略总结:不同源的页面之间,不准互相访问数据

代码演示

创建两个网站:

qq-com里面有一个server.js,用来模拟QQ空间。 driverzeng-com里面有一个server.js,用来模拟坏人网站

qq-com: /index.html 是首页 /qq.js 是JS脚本文件 /friend.json 是模拟好友数据 端口:8888 URL:http://127.0.0.1:8888

打开qq-com目录,里面创建server.js文件,写入代码

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(`
        <!DOCTYPE html>
        <head>
            <link rel="stylesheet" href="/x">
        </head>
        <body>
            <h1>曾老湿</h1>
            <script src="/y"></script>
        </body>
    `)
    response.end()
  } else if(path === '/x'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.write(`body{color: red;}`)
    response.end()
  } else if(path === '/y'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(`console.log('这是JS内容')`)
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

zls-com: /index.html 是首页 /zls.js 是JS脚本文件 端口:9999 URL:http://127.0.0.1:9999

打开zls-com目录,里面创建server.js文件,写入代码

启动服务,创建两个终端:

先创建QQ,启动服务

代码语言:javascript
复制
MacBook-pro:qq-com driverzeng$ node-dev server.js 8888

再创建ZLS,启动服务

代码语言:javascript
复制
MacBook-pro:zls-com driverzeng$ node-dev server.js 9999

打开浏览器分别访问:

http://127.0.0.1:8888

http://127.0.0.1:9999


完善QQ页面

server.js

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

index.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>QQ空间</title>
</head>
<body>
    欢迎来到xxx的QQ空间
</body>
</html>

qq.js

代码语言:javascript
复制
console.log('qq.js')

friends.json

代码语言:javascript
复制
[
    {"name":"邓紫棋"},
    {"name":"吴彦祖"},
    {"name":"彭于晏"},
    {"name":"周杰伦 "}
]


完善zls页面

server.js

代码语言:javascript
复制

index.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>曾老湿 黑客网站</title>
</head>
<body>
    说了你可能不信,我特么的是黑客
</body>
</html>

zls.js

代码语言:javascript
复制
console.log('zls')

跨域使用AJAX

正常使用AJAX,在qq.com:8888里运行JS可以访问到/friend.json

index.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>QQ空间</title>
</head>
<body>
    欢迎来到xxx的QQ空间
    <script src="qq.js"></script>
</body>
</html>

qq.js

代码语言:javascript
复制
const request = new XMLHttpRequest()
request.open('GET','friends.json')
request.onreadystatechange = () => {
    if(request.readyState === 4){
        if(request.status >= 200 && request.status < 400){
            console.log(request.response)
        }
    }
}
request.send()

黑客偷数据,在zls.com:9999里运行JS,不能访问!浏览器需要CORS

index.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>曾老湿 黑客网站</title>
</head>
<body>
    说了你可能不信,我特么的是黑客
    <script src="zls.js"></script>
</body>
</html>

zls.js

代码语言:javascript
复制
const request = new XMLHttpRequest()
request.open('GET','http://127.0.0.1:8888/friends.json')
request.onreadystatechange = () => {
    if(request.readyState === 4){
        if(request.status >= 200 && request.status < 400){
            console.log(request.response)
        }
    }
}
request.send()

解决跨域问题方法一:CORS

问题根源,浏览器默认不同源之间不能相互访问数据,但是qq.com和zls.com都是我的网站,我是老板,我就想让两个公司的资源做共享,你作为一个浏览器,你凭阻止?

浏览器:emmm... 那行吧,那我给你一个方法,你要是想共享数据,那就需要提前声明。

哦?是吗?那我要怎么声明呢?

浏览器:你要跟qq.com这个网站说一声,在响应头里写上zls.com可以访问。

哦?是吗?那具体语法呢?

浏览器:Access-Control-Allow-Origin:http://zls.com mmp,都在文档里,不好去MDN看吗?

走起,后台服务设置一波:

server.js

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

解决方法二:JSONP

有了第一种解决办法,为啥还需要第二种呢?是因为第二种方法更好么?

这个时候IE浏览器不得不问你一句话:你猜,我支不支持CORS?

Fuck,这还用猜?IE 6 7 8 9,白扯,前端开发的噩梦,兼容IE。

老板:我特么的就要兼容IE。

你:...我(qu)这(ni)就(da)去(ye)做(de)


JSONP

定义

JSONP跟JSON半毛钱关系都没有,由于前端水平低下,错误的将其称为JSONP

面临问题

程序猿常常面临奇葩需求 没有CORS,怎么跨域? 记不记得我们可以随意引用JS 虽然我们不能 访问qq.com:8888/friends.json 但是我们能引用qq.com:8888/friends.json啊 这有什么用?JS又不是数据 我们让JS包含数据不就好啦?试试看吧,明天就要上线了。

首先我们在qq.com中创建一个friends.js

先占个位,然后在server.js中添加路由

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else if(path === '/friends.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    const string = fs.readFileSync('public/friends.js').toString()
    const data = fs.readFileSync('public/friends.json').toString()
    const string2 = string.replace('{{ data }}',data)
    response.write(string2)
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

可以发现,这并不是一个合法的JS,这个只是数据,所以我们需要在friends.js里面加上一赋值

代码语言:javascript
复制
window.zls = {{ data }}

这才是一个合法的JS,然后我们使用zls.js调用JS

代码语言:javascript
复制
const script = document.createElement('script')
script.src = 'http://127.0.0.1:8888/friends.js'
document.body.appendChild(script)

我们还可以监听JS的onload事件

代码语言:javascript
复制
const script = document.createElement('script')
script.src = 'http://127.0.0.1:8888/friends.js'
script.onload =  () =>{
    console.log(window.zls)
}
document.body.appendChild(script)

一开始我说,这个跟JSON一点关系都没有,为啥呢?因为我们可以把数据改成别的,不一定非得是JSON,可以是XML,HTML...

friends.js

代码语言:javascript
复制
window.zls = `<xml>曾老湿</xml>`

那是不是就可以叫,XMLP?

那如果里面的数据是3呢?

代码语言:javascript
复制
window.zls = 3

卧槽,细思极恐~~~~~~~~ 不知道该叫啥。不知所措。

话说回来,CORS的方法,可以设置白名单,指定谁能访问,还是挺安全的,但是...JSONP没有办法指定啊。mmp,这怎么搞?那我们就只能从判断referer开始入手了。

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else if(path === '/friends.js'){
    if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
        response.statusCode = 200
        response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
        const string = fs.readFileSync('public/friends.js').toString()
        const data = fs.readFileSync('public/friends.json').toString()
        const string2 = string.replace('{{ data }}',data)
        response.write(string2)
        response.end()
    }else{
        response.statusCode = 404
        response.end()
    }
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)


优化

window.zls 这样不就写死了么?那空间还有其他函数调用朋友的名字,比如,最近访客,比如,评论的人,比如,好友生日...

所以我们要定义一个随机数给函数,给url添加一个查询参数

zls.js

代码语言:javascript
复制
const random = Math.random()
window[random] = (data) =>{
    console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload =  () =>{
    console.log(window.zls)
}
document.body.appendChild(script)

server.js

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else if(path === '/friends.js'){
    if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
        response.statusCode = 200
        console.log(query.functionName)
        response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
        const string = fs.readFileSync('public/friends.js').toString()
        const data = fs.readFileSync('public/friends.json').toString()
        const string2 = string.replace('{{ data }}',data)
        response.write(string2)
        response.end()
    }else{
        response.statusCode = 404
        response.end()
    }
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

这样一来,我们查询参数和后台的server.js就可以配合了,然后我们在后台,获取到这个functionName,做个替换。

friends.js

代码语言:javascript
复制
window['{{ zls }}'] ({{ data }})

server.js

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/index.html'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/qq.js'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(fs.readFileSync('public/qq.js'))
    response.end()
  } else if(path === '/friends.json'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'application/json;charset=utf-8')
    response.setHeader('Access-Control-Allow-Origin','http://127.0.0.1:9999')
    response.write(fs.readFileSync('public/friends.json'))
    response.end()
  } else if(path === '/friends.js'){
    if(request.headers["referer"].indexOf("http://127.0.0.1:9999") === 0 ){
        response.statusCode = 200
        response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
        const string = fs.readFileSync('public/friends.js').toString()
        const data = fs.readFileSync('public/friends.json').toString()
        const string2 = string.replace('{{ data }}',data).replace('{{ zls }}',query.functionName)
        response.write(string2)
        response.end()
    }else{
        response.statusCode = 404
        response.end()
    }
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

这样每次都是随机数了,就不会被写死了。但是也可能随机会随机到相同的或者跟别的开发,'撞衫'了,怎么办呢?

那我们就在随机数前面加一个前缀,保证不会重复

zls.js

代码语言:javascript
复制
const random = 'zlsFunctionNameJSONPbalala'+Math.random()
window[random] = (data) =>{
    console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload =  () =>{
    console.log(window.zls)
}
document.body.appendChild(script)

问题又来了,我们每发一次请求,就会多加载一个js文件。

怎么办呢?我们既然能创建script也能删除。

代码语言:javascript
复制
const random = 'zlsFunctionNameJSONPbalala'+Math.random()
window[random] = (data) =>{
    console.log(data)
}
const script = document.createElement('script')
script.src = `http://127.0.0.1:8888/friends.js?functionName=${random}`
script.onload =  () =>{
    script.remove()
}
document.body.appendChild(script)

这个就叫做...过河拆桥,emmm... 我们先创建script,拿到数据后,我们就可以把它删掉了。

封装JSONP[扩展]

代码语言:javascript
复制
function  jsonp(url){
    return new Promise((resolve,reject)=>{
        const random = 'zlsFunctionNameJSONPbalala'+Math.random()
        window[random] = (data) =>{
            resolve(data)
        }
        const script = document.createElement('script')
        script.src = `${url}?functionName=${random}`
        script.onload =  () =>{
            script.remove()
        }
        script.onerror = ()=>{
            reject()
        }
        document.body.appendChild(script)
    })
}

使用jsonp

代码语言:javascript
复制
jsonp('http://127.0.0.1:8888/friends.js')
    .then((data)=>{
        console.log(data)
    })

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 跨域
  • 同源策略
  • 代码演示
  • 跨域使用AJAX
  • 解决跨域问题方法一:CORS
  • 解决方法二:JSONP
  • 封装JSONP[扩展]
相关产品与服务
堡垒机
腾讯云堡垒机(Bastion Host,BH)可为您的 IT 资产提供代理访问以及智能操作审计服务,为客户构建一套完善的事前预防、事中监控、事后审计安全管理体系,助力企业顺利通过等保测评。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档