网站首页 > 基础教程 正文
前言
跨域?什么是跨域呢?我们先来看看一个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
image.png
其实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')
})
})
监听到了信息就将可以操作返回信息出去了.
以上就是解决跨域问题的几个常见的方法,希望对大家有所帮助!!感谢大家阅读
原文:https://juejin.cn/post/7412831382957211688
作者:Virtual09
猜你喜欢
- 2024-10-12 如何根治 Script Error. 如何根治神经性皮炎
- 2024-10-12 只用一个js文件,为你的网站加个黑暗模式
- 2024-10-12 闭包(一):闭包的9个应用场景 闭包一般用在什么地方
- 2024-10-12 LLM工程师应该如何防范提示注入?指导来了
- 2024-10-12 如何实现前端社交媒体分享功能 前端聊天功能如何实现
- 2024-10-12 「WWDC2018」-Web安全策略 web安全进阶
- 2024-10-12 「JS库」3个很棒的小众JavaScript库
- 2024-10-12 如何使用 如何使用验孕棒
- 2024-10-12 2 JavaScript核心 script标签 营养标签中的核心营养素
- 2024-10-12 GitHub精选 | Feather一组简单漂亮的开源图标
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)