美文网首页
非同源策略请求/WebSocket

非同源策略请求/WebSocket

作者: 欢西西西 | 来源:发表于2022-04-29 16:26 被阅读0次

    WebSocket使用及优化(心跳机制与断线重连)https://juejin.cn/post/6945057379834675230
    vue项目使用WebSocket技术 https://juejin.cn/post/6982078455722557448

    1.资源请求标签【link、img】-缺点:只能发起get请求,无法接收响应数据

            let img = new Image();
    
            img.src = '[http://192.168.4.154](http://192.168.4.154/):4005/list';
    
            let link = document.createElement('link');
    
            link.setAttribute("rel", "stylesheet");
    
            link.setAttribute('href', '[http://192.168.4.154](http://192.168.4.154/):4005');
    
            document.head.append(link); // 只设置href不会请求,必须添加才会请求
    
            document.head.removeChild(link);
    

    2.JSONP【script标签】

    要求服务端将返回数据和传过去的全局函数名称组织成可执行的js代码,缺点:只能发起get请求,随意执行响应数据,不安全

            window.execJson = function (dataJson) {
                console.log(dataJson);
            };
    
            let scripte = document.createElement('script');
    
            scripte.setAttribute('src', '[http://192.168.4.154](http://192.168.4.154/):4005/jsonp?funName=execJson');
    
            document.body.append(scripte);
    
            document.body.removeChild(scripte);
    
    
    组织成可执行的js代码.png

    3.iframe+form发送post请求-无法接收响应数据

     const requestPost = ({ url, data }) => {
    
                const iframe = document.createElement('iframe');
    
                iframe.name = 'iframePost';
    
                iframe.style.display = 'none';
    
                document.body.appendChild(iframe);
    
                const form = document.createElement('form');
    
                const node = document.createElement('input');
    
                iframe.addEventListener('load', function () {
    
                    console.log('post success');
    
                    document.body.removeChild(this);
    
                });
    
                form.action = url;
    
                // 在指定的iframe中执行form
    
                form.target = iframe.name;
    
                form.method = 'post';
    
                for (let name in data) {
    
                    node.name = name;
    
                    node.value = data[name].toString();
    
                    form.appendChild(node.cloneNode());
    
                }
    
                // 表单元素需要添加到主文档中.
    
                form.style.display = 'none';
    
                document.body.appendChild(form);
    
                form.submit();
    
                // 表单提交后,就可以删除这个表单,不影响下次的数据发送.
    
                document.body.removeChild(form);
    
            }
    
            requestPost({
    
                url: '[http://192.168.4.154](http://192.168.4.154/):4005/postData',
    
                data: { name: 'wxm' }
    
            });
    
    

    4.CORS 跨域资源共享-需要服务端设置允许某些访问源

    image.png
    server.get('/open', function (request, response) {
    
        console.log('get请求了open');
    
        // 允许哪些源访问,可以是通配符*
    
        response.setHeader("Access-Control-Allow-Origin", "[http://192.168.4.154](http://192.168.4.154/):4004");
    
        // 是否允许携带验证信息(非必须,如果请求携带了证书,需要设为true)    Credentials-证书
    
        response.setHeader("Access-Control-Allow-Credentials", true);
        response.setHeader("wxm-en", "ha");
        response.setHeader("hu-en", "haha");
    
        // 设置允许客户端访问的响应头
        response.setHeader("Access-Control-Expose-Headers", "wxm-en");
    
        response.send('open请求成功');
    });
    
            fetch('[http://192.168.4.154](http://192.168.4.154/):4005/open', {
                // 默认情况下为omit:不发送;same-origin:同源情况下发送;include:都发送
                // 如果设置了发送,但服务端未设置Access-Control-Allow-Credentials或设为了false都无法请求
                credentials: 'include',
            }).then(res => {
                res.text().then((r) => {
                    console.log(r);
                });
            });
    

    Access-Control-Expose-Headers 仅设置了wxm-en没设置hu-en则访问不到hu-en :


    image.png
    fetch('[http://192.168.4.154](http://192.168.4.154/):4005/post/open', {
    
                method: 'post',
                headers: {
                    "Content-type": "application/x-www-form-urlencoded",
    
                    // 新增了一个头信息,此时该请求为非简单请求,会先发送一个预检请求,服务端也应处理这类预检请求
                    "member-name": "wxm",
                },
    
                body: JSON.stringify({ length: 100 })
            }).then(res => {
                res.text().then((r) => {
                    console.log(r);
                });
            })
    
    preflight.png
    OPTIONS.png
    server.options('/post/open', function (request, response) {
    
        console.log('接收到post open的预检请求');
    
        response.setHeader("Access-Control-Allow-Origin", "[http://192.168.4.154](http://192.168.4.154/):4004");
    
        // 用于preflight request中,列出了允许的首部信息
    
        response.setHeader("Access-Control-Allow-Headers", "member-name");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.send('');
    });
    
    

    简单请求:①请求方式为GET/POST/HEAD ② 请求头不超过Accept、Accept-Language、Content-Language、Content-Type(只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)
    预检请求:假设没有预检请求,跨域请求直接到达服务器,并有可能对数据库里的数据进行了操作,但是返回的结果被浏览器拦截了,那么我们就获取不到返回结果,这是一次失败的请求,但是可能对数据库里的数据产生了影响
    // 浏览器必须先使用OPTIONS方法发起一个预检请求,从而获知服务器是否允许该跨域请求:如果允许,就发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求

    5.postMessage -- 建立在页面基础上的跨域通信

    image.png
     let iframe = document.getElementById('crossOrigin');  // 页面内嵌了一个非同源的页面
     iframe.contentWindow.postMessage("message info", "[http://192.168.4.154](http://192.168.4.154/):4006");
    
    

    // 虽然能互相拿到引用但无法互相访问


    image.png

    // 但可以通过postMessage 进行通信:


    onMessage.png
    接收到通过postMessage发送的信息.png

    6.WebSocket

    不限制非同源连接,实现客户端与服务端的通信
    服务端也可以将接收到的信息发给其他已连接的客户端,实现客户端与其他客户端的通信

            let wsUrl = 'ws://192.168.4.154:4007';
            let ws = new WebSocket(wsUrl);
    
            ws.onopen = function () {
                console.log('ws连接成功!');
            }
            ws.onmessage = function (event) {
                console.log(event.data);
            }
            window.onunload = function () {
                ws.close();
            }
    
            let msgInput = document.getElementById('messgae');
            document.getElementById('send').onclick = function () {
                ws.send(msgInput.value);   // 向服务端发送信息
            };
    

    // WebSocket实例的属性

     {
    
            binaryType: "blob", // blob:Binary Large Object
            bufferedAmount: 0, // 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数
            extensions: "",
            onclose: null,
            onerror: null,
            onmessage: null,
            onopen: null,
            protocol: "",
    
            // 0未连接(WebSocket.CONNECTING)          
            // 1已连接(WebSocket.OPEN)             
            // 2正在关闭(WebSocket.CLOSING)               
            // 3已关闭(WebSocket.CLOSED) 
            readyState: 3,  
    
            url: "ws://192.168.4.154:4007/"
        }
    

    // 心跳检测

    var heartBeat = {
                interval: 1 * 1000,
                timeout: 3 * 1000, // 发出后timeout时间内还未收到信息则认为连接已断开
    
                wsUrl: 'ws://192.168.4.154:4007',
                ws: null,
                isConnecting: false,
                assertConnect: false,
                startHeartBeat() {
                    setTimeout(() => {
                        if (this.ws.readyState === WebSocket.OPEN) {
                            console.log('<乒乒');
                            this.ws.send('wxm');
                            this.waitServer();
                        }
    
                    }, this.interval);
    
                },
    
                waitServer() {
                    this.assertConnect = false;
                    setTimeout(() => {
                        if (this.assertConnect) { // 如果保持连接
                            this.startHeartBeat();
                        } else {
                            console.log('无响应,需重新连接...');
                            this.reConnect();
                        }
                    }, this.timeout);
                },
    
                reConnect() {
                    if (this.isConnecting) {
                        return;
                    }
    
                    try {
                        this.ws.close();
                        console.log('重新连接前先关闭连接...');
    
                    } catch (err) {
                        console.log('连接已关闭,无需再次关闭');
                    }
    
                    this.init();
                },
    
                init() {
                    console.log('连接中...');
                    this.isConnecting = true;
                    let ws = new WebSocket(this.wsUrl);
                    this.ws = ws;
    
    
    
                    ws.onopen = () => {
                        console.log('已连接√');
                        this.isConnecting = false;
                        this.startHeartBeat();
                    };
    
                    ws.onerror = () => {
                        console.log('连接失败');
                        this.isConnecting = false;
                        this.reConnect();
                    };
    
                    ws.onclose = () => {
                        this.isConnecting = false;
                        console.log('客户端:连接已关闭');
                    };
    
                    ws.onmessage = (e) => {
                        // 接收的如果是心跳消息
    
                        let isHeartMsg = true;
    
                        if (isHeartMsg) {
                            console.log('乓乓>');
                            this.assertConnect = true;
    
                        }
    
                    };
    
                },
    
            }
    

    相关文章

      网友评论

          本文标题:非同源策略请求/WebSocket

          本文链接:https://www.haomeiwen.com/subject/lzpsyrtx.html