实现前端跨域的几种方式
2019-08-19 本文已影响0人
wayne1125
1、jsonp跨域实现方式
function jsonp({url,params,cb}){
return new Promise((resolve,reject) => {
window[cb] = function (data) {
resolve(data)
document.body.removeChild(script)
}
params = {...params,cb} // { wd:b,cb:show }
let arrs = []
for(let key in params){
arrs.push(`${key}=${params[key]}`)
}
let script = document.createElement('script')
script.src = `${url}?${arrs.join('&')}`
document.body.appendChild(script)
})
}
jsonp({
url: 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',
params: {wd: 'b'},
cb: 'show'
}).then(data => {
console.log(data)
})
jsonp({
url: 'http://localhost:3000/say',
params: {wd: 'I love you'},
cb: 'showLove'
}).then(data => {
console.log(data)
})
- server.js
let express = require('express')
let app = express()
app.get('/say', function (req, res){
let {wd,cb} = req.query
console.log(req.query,'query')
console.log(wd)
res.send(`${cb}('I love you to')`)
})
app.use(express.static(__dirname))
app.listen(3000)
2、CORS跨域实现方式
- index.html
<!DOCTYPE html>
<html>
<head>
<title>cors</title>
</head>
<body>
<script type="text/javascript">
let xhr = new XMLHttpRequest;
document.cookie = 'name=wayne'
xhr.withCredentials = true
xhr.open('PUT','http://localhost:4000/getData',true)
xhr.setRequestHeader('name', 'waynename')
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
console.log(xhr.response)
console.log(xhr.getResponseHeader('name'))
}
}
}
xhr.send()
</script>
</body>
</html>
- server1.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(3000)
- server2.js
let express = require('express')
let app = express()
let whiteList = ['http://localhost:3000']
app.use(function(req,res,next){
let origin = req.headers.origin
if(whiteList.includes(origin)){
// 设置哪个源可以访问我
res.setHeader('Access-Control-Allow-Origin', origin)
// 允许哪个头访问我
res.setHeader('Access-Control-Allow-Headers', 'name')
// 允许哪个方法访问我
res.setHeader('Access-Control-Allow-Methods', 'PUT')
// 允许携带Cookie
res.setHeader('Access-Control-Allow-Credentials', true)
// 允许返回的头
res.setHeader('Access-Control-Expose-Headers', 'name')
// 预检的存活时间
res.setHeader('Access-Control-Max-Age', 1000)
if(req.method === 'OPTIONS'){
res.end() // OPTIONS请求不做任何处理
}
}
next()
})
app.put('/getData',function(req,res){
console.log(req.headers)
res.setHeader('name','wayne')
res.end('I dont‘t like you PUT')
})
app.get('/getData',function(req,res){
console.log(req.headers)
res.end('I dont‘t like you')
})
app.use(express.static(__dirname))
app.listen(4000)
3、possMessage跨域实现方式
// a.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<iframe src="http://localhost:4000/b.html" frameborder="0" id="frame" onload="load()"></iframe>
<script type="text/javascript">
function load(){
let frame = document.getElementById('frame')
frame.contentWindow.postMessage('I love you','http://localhost:4000')
window.onmessage = function (e){
console.log(e.data)
}
}
</script>
</body>
</html>
// a.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(3000)
// b.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
window.onmessage = function (e){
console.log(e.data)
e.source.postMessage('I don’t love you', e.origin)
}
</script>
</body>
</html>
// b.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(4000)
4、window.name跨域实现方式
// a.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<iframe src="http://localhost:4000/c.html" frameborder="0" id="frame" onload="load()"></iframe>
<script type="text/javascript">
// a和b是同域 http://localhost:3000
// c是独立的 http://localhost:4000
// a获取c的数据
// a先引用c c把值放到window.name,把a引用的地址改到b
let first = true
function load(){
if(first){
let frame = document.getElementById('frame')
frame.src = 'http://localhost:3000/b.html'
first = false
} else{
console.log(frame.contentWindow.name)
}
}
</script>
</body>
</html>
// a.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(3000)
// b.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
</script>
</body>
</html>
// b.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(4000)
// c.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
window.name = 'I dont love you'
</script>
</body>
</html>
5、hash跨域实现方式
// a.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<iframe src="http://localhost:4000/c.html#Iloveyou"></iframe>
<script type="text/javascript">
// 路径后面的值可以用来通信
// 目的a想访问c
// a给c传一个hash值 c收到hash值后 c把hash值传递给b b将结果放到a的hash值中
window.onhashchange = function(){
console.log(location.hash)
}
</script>
</body>
</html>
// a.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(3000)
// b.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
window.parent.parent.location.hash = location.hash
</script>
</body>
</html>
// b.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(4000)
// c.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
console.log(location.hash)
let iframe = document.createElement('iframe')
iframe.src = 'http://localhost:3000/b.html#Idontloveyou'
document.body.appendChild(iframe)
</script>
</body>
</html>
6、document.domain
// a.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
hello a
<iframe src="http://b.zf1.cn:3000/b.html" frameborder="0" onload="load()" id="frame"></iframe>
<script type="text/javascript">
// 域名,此用法限制是一级域名和二级域名的关系
// a是通过 http://a.zf1.cn:3000/a.html
document.domain = 'zf1.cn'
function load() {
console.log(frame.contentWindow.a)
}
</script>
</body>
</html>
// a.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(3000)
// b.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
hello b
<script type="text/javascript">
document.domain = 'zf1.cn'
var a = 100
</script>
</body>
</html>
// b.js
let express = require('express')
let app = express()
app.use(express.static(__dirname))
app.listen(4000)
7、websocket跨域实现方式
// socket.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
websocket
<script type="text/javascript">
// 高级api 不兼容,一般使用socket.io做兼容
let socket = new WebSocket('ws://localhost:9000')
socket.onopen = function () {
socket.send('I love you')
}
socket.onmessage = function (e) {
console.log(e,e.data)
}
</script>
</body>
</html>
// server.js
let express = require('express')
let app = express()
let WebSocket = require('ws')
let wss = new WebSocket.Server({port: 9000})
console.log(123456)
wss.on('connection', function(ws){
console.log(123)
ws.on('message', function(data){
console.log(data)
ws.send('I dont love you')
})
})
app.use(express.static(__dirname))
app.listen(3000)
8、nginx跨域实现方式
nginx反向代理方式之前总结过https://www.jianshu.com/p/96bc88beba91
image.png
文件夹crossDomain下执行 cnpm install express ws --save后,可公用一份依赖包