前言
跨域?什么是跨域呢?我们先来看看一个url的组成,http://192.x.x:3000/home
,这一个url我们可以分成四部分来看http
是协议,192.x.x
是域名,3000
是端口,home
是路径.在浏览器中,我们从一个域名发送请求到另一个域名,如果两个域名的协议,域名,端口三部分只要存在一部分不同就会发生跨域,也就是说只有两个域名的协议,域名,端口都相同才会不会发生跨域,所以我们又如何解决跨域的问题呢?在下文中会给大家介绍几种方法去解决跨域问题.
正文
那么要解决跨域就不得不谈及同源策略
,同源策略是一种安全措施,用于防止恶意网站通过脚本获取或修改其他网站的数据.只要协议,域名,端口,三者其中一个不一致,在请求响应过程中就会触发同源策略.
JSONP
第一种方式是JSONP
,但是跟JSON
并没有关系,这只是一种称呼.那么JSONP
的实现原理也是非常简单的,我们来想想,平时我们在页面加载图片时<img src="" alt="">
是不是可以正常加载页面,我们的scr
里面是放的地址,这里是需要发送请求的,如果按照跨域的说法,这里势必会发生跨域,但是事实上这里并没有发生跨域,图片依旧可以正常加载.原因是如果加载图片一直需要解决跨域的话,就会很麻烦,索性就把src
放进了“白名单”不会发生跨域,类似的<link rel="stylesheet" href="">
,<script src=""></script>
都不会发生跨域,因此JSONP的过程就采取了这个方式.
我们在JS中创建一个script
的标签,并设置src
属性并插入到html中就可以了.但是这样我们就无法操作接口请求发送响应获取到的数据了,这里我们就需要打造一下.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function jsonp(url,cb){
return new Promise((resolve,reject)=>{
const script = document.createElement('script')
window[cb] = function(data){
resolve(data)
}
script.src = `${url}?cb=${cb}`
document.body.appendChild(script)
})
}
jsonp('http://localhost:3000','callback').then(res=>{
console.log(res);
})
</script>
</body>
</html>
window[cb]
是我们在全局声明了一个叫cb
的函数.拿到响应返回的数据我们借助了new Promise
来处理异步请求,并使用resolve()
传递数据.在后端操作可能就比较绕了.
const http = require('http');
http.createServer(function (req, res){
const query = new URL(req.url,`http://${req.headers.host}`).searchParams
console.log(query);
if(query.get('cb')){
const cb = query.get('cb')
const data = 'hello world'
const result = `${cb}("${data}")`
res.end(result)
}
}).listen(3000)
new URL(req.url,`http://${req.headers.host}`).searchParams
是获取到请求携带的参数,这里返回的是一个map
对象,所以取值我们用的是get(key)
.
const cb = query.get('cb')
:获取到携带的参数callback 这里 cb = callback
const data = 'hello world'
:实参,传给函数
const result = `${cb}("${data}")
:这里就会比较绕了,首先cb
是指callback,这里加上()就变成一个函数的样子callback()
,data
实参,就变成了callback("hello world")
再使用res.end(),这里浏览器就是把这个函数给执行了.也就是把这一串执行了
window[cb] = function(data){
resolve(data)
}
总的来说JSONP的操作原理就是借助script的标签的src属性不受同源策略的影响,来发送请求,给后端携带一个参数callback 并在前端定义callback函数体,后端返回callback 的调用形式并将要影响的值作为callback,当浏览器接受到响应后,就会触发全局的callback函数,从而让callback以参数的形式接收到后端的响应.
cors
使用cors
处理同源,这个用一句话说明就是通过在后端代码中,操作http响应头添加‘Access-Control-Allow-Origin’字段,来限制任意url不会被同源策略操作,从而达到解决跨域.
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const xhr = new XMLHttpRequest();//创建一个ajax
xhr.open('GET', 'http://localhost:3000', true); // 建立一个GET请求
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200){
console.log(xhr.responseText);
}
}
</script>
</body>
</html>
后端代码:
const http = require('http');
http.createServer(function (req, res){
res.writeHead(200, {
'Access-Control-Allow-Origin': '*',
// 'accept-control-allow-methods':
});
res.end('hello world')
}).listen(3000)
我们操作这一个字段Access-Control-Allow-Origin
,设置哪一个源可以跨域,这里*
是指所有的源都可以.
nginx
其实nginx
的原理就是代理,当发送请求过程中会被nginx
代码后再到接受请求,然后在响应的过程中,也会在nginx
中被代理后再返回出去.这个nginx
主要用于项目部署到服务器上时使用的.
WebSocket
scoket协议天生不受同源策略的影响这一点就非常的厉害,那么它的作用是什么呢?它是双端管道,信息是双向传递的,不用只有一发送了请求,才会响应信息给你.
我们可以这张极其简陋的图,这里A随时发消息给B,B不做请求也可以也接收到,A不作出请求,B也可以随时发消息给A.
我们先在终端使用npm init -y
初始化一下一个后端项目,并npm i ws
这里我们使用的WebScoket
协议而不是HTTP
协议
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function myWebSocket(url,params={}) {
return new Promise((resolve,reject)=>{
const socket = new WebSocket()
socket.onopen = ()=>{
socket.send(JSON.stringify(params))
}
socket.onmessage = (e)=>{
resolve(e.data)
}
})
}
myWebSocket('ws://localhost:3000',{age:18}).then(res=>{
console.log(res);
})
</script>
</body>
</html>
这里需要注意的是WebScoket
只能接受字符串数据,所以这里socket.send(JSON.stringify(params))
我们要处理一下处理的类型.
后端我们需要监听连接事件。当连接后我们就要监听信息
const webSocket = require('ws')
const ws = new webSocket.Server({port:3000})
ws.on('connection',function(obj){
obj.on('message',function(data){
obj.send('hello world')
})
})
监听到了信息就将可以操作返回信息出去了.
以上就是解决跨域问题的几个常见的方法,希望对大家有所帮助!!感谢大家阅读