标签:推送 tle 客户端 创建 发送 window 讲解 修改 idt
同源策略:
官方解释:同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
描述:例如:https://www.baidu.com https是协议,com为顶级域名,baidu是一级域名,www是主机名,必须协议(https)、域名(www.baidu.com)、端口号(8000)一样才能相互访问。
解决:
1.jsonp
定义:Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据,其实就是前端定义一个回调函数告诉后端这个函数,请求后端时候后端执行这个函数,返回数据放在函数参数里面带回给前端。
实现如下:(端口号不一样实现的跨域)
node.js 服务器端的代码:
const express = require(‘express‘) const app = express() const port = 3000 app.get(‘/‘, (req, res) => { let query = req.query let cb =query.cb res.send(`${cb}("我是服务器返回来的数据")`) }) app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) })
客户端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>jsonp</h1>
<script>
function cb(data){
console.log(data)//我是服务器返回来的数据
} </script> <script src="http://127.0.0.1:3000/?cb=cb"></script> </body> </html>
优缺点:只能发送get请求,不支持post,put,delete;不安全xss攻击,一般不采用
2.cors
定义:CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing),它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制,可以参考阮老师的仔细讲解(http://www.ruanyifeng.com/blog/2016/04/cors.html)
实现如下:
服务端代码:
const express = require(‘express‘) const app = express() const port = 4000 let whitList = ["http://localhost:3000"] app.use(function (req, res, next) { let origin = req.headers.origin; if (whitList.includes(origin)) { // 设置允许的请求源 res.setHeader("Access-Control-Allow-Origin", origin) //设置允许的请求头参数 res.setHeader("Access-Control-Allow-Headers","name") //设置允许的请求方法,默认get和post不需要配置 res.setHeader("Access-Control-Allow-Methods","PUT") //预检不处理 if(res.method=="OPTIONS"){ res.end() } //预检检测时间(最大存活时间) res.setHeader("Access-Control-Allow-Max-Age",6) //设置允许带上cookie res.setHeader("Access-Control-Allow-Credentials",true) //设置允许获取的响应头参数 res.setHeader("Access-Control-Expose-Headers",‘age‘) } next() }) app.get(‘/getData‘, (req, res) => { res.send(`get请求,我是服务器4000返回来的数据`) }) app.put(‘/getData‘, (req, res) => { res.setHeader("age",20) res.send(`put请求,我是服务器4000返回来的数据`) }) app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) })
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>cors</h1>
<script>
let xhr = new XMLHttpRequest;
xhr.open("PUT","http://localhost:4000/getData",true),
//设置请求头
xhr.setRequestHeader("name","jituitaixiao")
//设置cookie
document.cookie = ‘name=jitiu‘
//强制带上cookie,默认不带上
xhr.withCredentials = true
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("age"))
}
}
}
xhr.send()
</script>
</body>
</html>
优缺点:相比jsonp功能更加强大和安全,但是后端代码设置头部比较麻烦。
3.postMessage
定义:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>a.html</h1> <iframe src="http://localhost:4000/b.html" frameborder="0" id="iframe" onload="load()"></iframe> <script> //像b页面发送数据 function load(){ let iframe = document.getElementById("iframe"); iframe.contentWindow.postMessage("a页面数据","http://localhost:4000") // 接收b页面数据 window.onmessage = function(e){ console.log(e.data) } } </script> </body> </html>
b.html页面,用node服务器启动本地到4000端口:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>b.html</h1> <script> //接收b页面数据 window.onmessage = function(e){ console.log(e.data) //像a页面发送数据 e.source.postMessage("b页面数据",e.origin) } </script> </body> </html>
把b页面通过iframe标签放在a页面,通过postMessage和onmessage相互通讯。
优缺点:html5引入的message的API可以更方便、有效、安全的解决这些难题。postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
4.window.name
定义:下面代码有3个html页面,a页面和b页面同域,c页面独立,第一步,使用a页面的iframe标签的src属性指向c页面地址,此时不做处理就是跨域请求,会报错;第二步,在a页面的iframe标签上面定义一个onload方法,他的作用是将src的地址改成b页面地址,a和b页面属于同源,可以进行通信。开始在a页面请求c的时候,c页面抛出一个window.name,这个方法在后来a页面访问b的时候仍然存在,不会消失!这样a页面就拿到了c页面数据,实现了跨域!代码如下:
a.html(在本地服务的3000端口)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <iframe src="http://localhost:4000/c.html" frameborder="0" id="iframe" onload="onload"></iframe> <script> let first = true;//这个变量设置作用是修改src后页面从新渲染,会从新执行onload函数,防止死循环 function onload(){ if(first){ let iframe = document.getElementById("iframe") iframe.scr = "http://localhost:3000/b.html" first = false }else{ console.log(iframe.contentWindow.name)//"鸡腿太小" } } </script> </body> </html>
b.html(在本地服务的3000端口,不做任何处理)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> </body> </html>
c.html(在本地服务的4000端口)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> window.name = "鸡腿太小" </script> </body> </html>
优缺点:用的很少,有点low。。。
5.hash
定义:和window.name一样,三个页面a.html、b.html、c.html ,a页面和b页面同域,c为独立的域名,a页面通过iframe的src带一个hash值传递给c页面,在c页面通过获取hash,然后创建一个iframe,src待hash传给b页面,a页面可以通过监听b页面hash变化获取c的hash值
a.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- a页面传递过一个hash值给c页面 -->
<iframe src="http://localhost:4000/c.html#jituitaixiao" frameborder="0" id="iframe" onload="onload"></iframe>
<script>
// b页面修改了hash值,a页面监听获取hash值
window.onhashchange = function (){
console.log(location.hash)//jituizhendetaixioale
}
</script>
</body>
</html>
b.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//将c页面传递过来得hash值传给3000端口
window.parent.parent.location.hash=location.hash
</script>
</body>
</html>
c.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//获取a页面传递过来得hash值
console.log(location.hash)//jituitaixioa
//通过iframe向b页面传递hash
let iframe = document.createElement("iframe");
iframe.src = "http://localhost:3000/b.html#jituizhendetaixiaole"
document.body.appendChild(iframe)
</script>
</body>
</html>
6.document.domain
定义:首先用document.domain来指定域,是可以的,但是有局限性,也就是一级域名一致才可以。如下:
www.sojson.com 下指到sojson.com 是可以的。
icp.sojson.com 下指到 sojson.com 是可以的。
像上面是可以的,因为 一级域名 都是 sojson.com 。
www.sojson.com 下指到 www.baidu.com 是不行的。
sojson.com 指到 baidu.com 还是不行的。
比如我们要在当前页面下,“www.sojson.com/shiro” 下上传图片到 "cdn.sojson.com/images/" 下去。直接搞肯定是不行的。
在请求“www.sojson.com/shiro”和 "cdn.sojson.com/images/"的时候,都加上如下代码:
document.domain = "sojson.com"
7.webSocket
定义:它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
其他特点包括:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
客户端代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<h1>WebSocket</h1>
<body>
<script>
// 创建一个3000长链接端口
let socket = new WebSocket("ws://localhost:3000")
//打开服务器,发送请求数据
socket.onopen = function () {
socket.send("jituitaixioa")
}
//接收webSocket返回来的数据
socket.onmessage = function (evt) {
console.log("Received Message: " + evt.data);
socket.close();
};
//关闭长链接后的回调函数
socket.onclose = function (evt) {
console.log("Connection closed.");
}
//连接错误时候的回调函数
socket.onerror = function (event) {
console.log("Connection error");
};
</script>
</body>
</html>
服务端代码如下:
let WebSocket = require("ws");
let wss = new WebSocket.Server({port:3000});
wss.on("connection",function(ws){
ws.on("message",function(data){
console.log(data)
ws.send("jituzhendetaixiaole")
})
})
8.nginx后端配置即可
9.proxy反向代理
感谢各位支持
标签:推送 tle 客户端 创建 发送 window 讲解 修改 idt
原文地址:https://www.cnblogs.com/aoshilin/p/14623804.html