• JavaScript防流量劫持


    劫持产生的原因和方式

    在网页开发的访问过程中, http是我们主要的访问协议。我们知道http是一种无状态的连接。即没有验证通讯双方的身份,也没有验证信息的完整性,所以很容易受到篡改。运营商就是利用了这一点 篡改了用户正常访问的网页,插入广告或者其他一些杂七杂八的东西 ,达到盈利的目的。

    运营商的一般做法有以下手段:

    1 、对正常网站加入额外的广告,这包括网页内浮层或弹出广告窗口;

    2 、针对一些广告联盟或带推广链接的网站,加入推广尾巴 ;

    3 、把我们的站点非法解析到其他的站点,比如我们在浏览器输入 http://baidu.com, 百度绑定的服务器 ip 地址是 111.13.101.208 ,此时如果运营商的 dns 服务器将 baidu.com 的对应的 ip 地址改为 qq 的服务器 ip 14.17.32.211 ,我们输入 http://baidu.com 就会跳转到 QQ 的页面。

    以上的手段,通过原理归纳为两种

    1、HTTP 劫持

    当我们使用 HTTP 请求请求一个网站页面的时候,网络运营商会在正常的数据流中插入精心设计的网络数据报文,让客户端(通常是浏览器)展示 “ 错误 ” 的数据,通常是一些弹窗,宣传性广告或者直接显示某网站的内容,大家应该都有遇到过。 做法 1 、 2 就是通过这种方式

    vi设计http://www.maiqicn.com 办公资源网站大全https://www.wode007.com

    2、DNS 劫持

    我们通过域名访问网页的时候,都需要通过 DNS 服务器把域名解析到对应的服务器地址上,而 用户上网的 DNS 服务器都是运营商分配的 。 所以,在这个节点上,运营商可以为所欲为。 做法 3 就是通过这种方式

    对于以上的劫持方式,我们作为前端的开发人员,通过 JavaScript 如何来做到有效的防护呢?

    对于 DNS 劫持,由于发生在域名解析的时候,我们无法控制, JavaScript 更无能为力。我们能做的就是拿起手机,投诉网络运营商,或者直接打工信部电话( 12300 )投诉。

    http劫持防范

    对于 http 劫持,运营商在实现上一般有以下几种做法

    1 、 iframe 嵌套 展示原来正常网页
    2 、在原 html 中插入 js ,再通过 js 脚本安插广告
    3 、直接返回一个带广告的 html

    首先我们来看页面被嵌入了 iframe 的 情况。 网络运营商为了尽可能地减少植入广告对原有网站页面的影响,通常会通过把原有网站页面放置到一个和原页面相同大小的 iframe 里面去,那么就可以通过这个 iframe 来隔离广告代码对原有页面的影响。 这种情况比较容易处理。我们只要判断我们的页面是否被嵌套在 iframe 中即可。 Window 对象中有两个属性 self (指向本身的窗口), top (指向顶层的窗口)可以帮我们来识别判断

    我们可以这样简单判断:

     if  (window.self !=  window.top) {   
        var  url =  location.href;
        top.location  =  url;
    } 
    

    但是,有时候我们在实际业务中,我们的页面确实需要被嵌套在 iframe 中推广,上面的判断会导致页面无法嵌套,这时候我们可以采用配置域名白名单的方式来解决

    var avoidIframeNest = {
    whiteList: [],
    init: function(whiteList) {
    if (Object.prototype.toString.call(whiteList) == "[object Array]") {
    this.whiteList = whiteList;
    }
    this.redirect();
    },
    redirect: function() {
    if (self != top) {
    var parentUrl = document.referrer; //是否在白名单内
    for (var i = 0, length = this.whiteList.length; i < length; ++i) {
    var reg = new RegExp(this.whiteList[i], 'i');
    if (reg.test(parentUrl)) {
    return;
    }
    } //页面跳转
    var url = location.href;
    top.location = url;
    }
    }
    }

    通过配置白名单的方式,比较适合于我们经常用到的域名,通常我们会遇到这样的需求,合作方要求嵌套我们的页面,我们如果将合作方也加入到我们白名单,一方面会导致白名单很长,另一方面我们需要手动去改代码,这样很不方便。这种情况,我们可以在嵌套的 url 上加上域名的参数判断,要求嵌套页面带上域名参数,如果匹配,就认为合法。

    var avoidIframeNest = {
    whiteList: [],
    init: function(whiteList) {
    if (Object.prototype.toString.call(whiteList) == "[object Array]") {
    this.whiteList = whiteList;
    }
    this.redirect();
    },
    redirect: function() {
    if (self != top) {
    var parentUrl = document.referrer; // 是否在白名单内
    for (var i = 0, length = this.whiteList.length; i < length; ++i) {
    var reg = new RegExp(this.whiteList[i], 'i');
    if (reg.test(parentUrl)) {
    return;
    }
    } // 判断URL是否带指定参数
    var iframeDomain = this.getUrlParam('iframe_domain');
    if (iframeDomain && parentUrl.indexOf(iframeDomain) != -1) {
    return;
    } // 页面跳转
    var url = location.href;
    top.location = url;
    }
    },
    getUrlParam: function(key) {
    var regStr = "^.*[\?|\&]" + key + "\=([^\&]*)",
    url = location.href;
    reg = new RegExp(regStr, 'i');;
    var ret = url.match(reg);
    if (ret != null) {
    return decodeURIComponent(ret[1]);
    } else {
    return "";
    }
    }
    }
    avoidIframeNest.init(['baidu.com']);

    通过上述的方法,基本可以解决 iframe 嵌套问题

    对于 js 注入问题, 一般都会在页面中插入图片标签,展示广告,诱导用户点击。针对这种方式,我们可以通过监控页面插入的图片内容来检测。这里,我们可以利用 HTML5 的新特性 MutationObserver   和 window 下的 DOMNodeInserted 事件

    Mutation Observer (变动观察器)是监视 DOM 变动的接口。当 DOM 对象树发生任何变动时, Mutation Observer 会得到通知。 具体的介绍可以参考:   

    可以监听某个 DOM 范围内的结构变化:http://www.cnblogs.com/jscode/p/3600060.html

    DOMNodeInserted 顾名思 义,可以监听某个 DOM 范围内的结构变化 ,这个特性只有在 firefox 的低版本和 webkit 中使用, IE 不支持,这里我们可以作为低版本浏览器的兼容实现。

    var validInsertImg = {
    httpReg: /^http://(.*.baidu.com|.*.netwin.com)//, // 验证非法图片
    validIllegalityImg: function(src) {
    var httpReg = this.httpReg;
    return !httpReg.test(src);
    },
    init: function() {
    this.monitor();
    },
    monitor: function() {
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    var mutationObserverSupport = !!MutationObserver; // html5监控变化属性
    if (!mutationObserverSupport) {
    this.mutationListen(MutationObserver);
    } else {
    this.insertedListen();
    }
    },
    insertedListen: function() {
    var that = this;
    document.addEventListener('DOMNodeInserted', function(e) {
    var dom = e ? e.srcElement : document.documentElement;
    if (!dom.outerHTML) {
    return;
    }
    var imgList = (dom.nodeName.toUpperCase() == 'IMG') ? [dom] : dom.getElementsByTagName('img');
    if (!imgList || imgList.length == 0) {
    return;
    }
    for (var i = 0; i < imgList.length; i++) {
    that.removeNode(imgList[i]);
    }
    });
    },
    mutationListen: function(MutationObserver) {
    var that = this;
    var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
    var nodes = mutation.addedNodes;
    for (var i = 0; i < nodes.length; i++) {
    var node = nodes[i];
    that.removeNode(node);
    }
    })
    })
    observer.observe(document, {
    subtree: true,
    childList: true
    });
    }, // 删除node
    removeNode: function(node) {
    if (node.nodeName.toUpperCase() == 'IMG') {
    var src = node.src;
    if (this.validIllegalityImg(src)) {
    node.parentNode.removeChild(node);
    console.log('拦截可疑静态脚本:', node.src);
    }
    }
    }
    }

    validInsertImg.init();

    body = document.getElementsByTagName('body')[0];
    var img = document.createElement('img');
    img.setAttribute('src', 'http://m.baidu.com/img/b')
    body.appendChild(img);
    var img1 = document.createElement('img');
    img1.setAttribute('src', '/YTRYTRY/A.PNG')
    body.appendChild(img1);

    对于在返回 html 内容中插入广告,我们可以借鉴注入的方式,进入页面就检测的 img 图片路径是否在白名单内

    以上方法,都是针对运营商劫持的常用手段进行的一些黑科技操作。只能尽量的减少劫持给我们带来的负面影响。针对劫持问题,最好的办法就是全站升级 https 的方式,验证通讯双方的身份以及信息的安全性。

    但是 https 也不能完全的解决劫持问题,如果 https 页面被劫持,浏览器会出现空白页面或者提示不安全,无法显示正常的内容。这也会影响到用户的体验。但是还是推荐使用 https ,如果大部分的网站都使用了 https ,运营商的劫持无法达到目的,自然不会去做这样吃力不讨好的事情。

  • 相关阅读:
    对象不支持此属性或方法
    继承多态
    GetType和typeof的区别
    比较高效的表格行背景变色及选定高亮JS
    C#获取存储过程的Return返回值和Output输出参数值
    删除表中重复记录,只保留一行
    实现自定义的ToolTip
    状态管理之Cookie
    Microsoft SQL Server,错误: 5120
    IE/Firefox中全局正则表达式的兼容
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13744881.html
Copyright © 2020-2023  润新知