浏览器页面功能限制与反限制的斗争

开博两年多,只自己重新以高优先级的样式弄了博客的展示界面(兼容IE6···),之后没有任何博文产出,因为后来才开始知道有响应式布局这个东西,想弄完再写(哈哈哈哈,我是屁事特多的类型),也有点不好意思了。这篇文章基本上是对网上已有的文章做了下整理而已,写的也是大家用的主流方法,所以也没啥新内容,也没有多少技术水平,是本人用以当作技术类文章的Helloworld的练笔测试。好啦,开撸,小弟语文不好,有错误请帮忙订正一下(*@ο@*) 哇~

大伙在看网页时,或多或少都会遇到一些禁止右键、选择、复制、黏贴之类的网站,或者在写一些要限制用户操作的页面时应该也有实现过类似的需求。

首先说说可以实现对应禁止功能的,可以达到目的的事件咯。So Easy~ 

  1. 禁止右键菜单方法只有一个: 'contextmenu'
  2. 禁止选择 'selectstart','select'
  3. 禁止拖动 'dragstart', 
  4. 禁止复制 有这种 'beforecopy', 'copy' ,'selectstart','select','keydown','mouseup'(不然你选择不让你玩鼠标和键盘也是个思路对不?)
  5. 哈哈哈哈,俺只是个打杂的,不是什么专业的前端开发工程师,估计还会有遗漏,就先留个来凑凑数哈···

简单,这种需求网上一搜到处都是,网上实现的最简单方法无非也就是在body标签里面,禁止掉对应的事件。

如禁止右键菜单:

<body oncontextmenu="return false">    
</body>

所谓你省心大家也省心,破解方法也是So Easy:对body,玩个事件一次过解绑就好了。

(function () {
    ['contextmenu', 'dragstart', 'mouseup', 'copy', 'beforecopy', 'selectstart', 'select', 'keydown']
        .forEach(function (evt) {
            document.body['on'+evt]=null;
        });
})();

当然,有些会用事件绑定,这里只讨论一些常规的方案哈。但jQuery这东东,实在是太好用了,不给大家讲shenmegui的基础知识,就是告诉大家,bind绑定的都可以用unbind解绑。不要问我为啥不说$.fn.on什么的,on出现的版本太后了,我还真看过现在还有 1.3.2的jq。

思路还是同上,不过,用jquery的网站大部分绑定在 document那里。这次以禁止右键和禁止选择为栗子

(function () {
$(document).on('contextmenu selectstart', function () {
return false;
});
})();

附上解决方法的话:

(function ($) {
    ['contextmenu', 'dragstart', 'mouseup', 'copy', 'beforecopy', 'selectstart', 'select', 'keydown']
        .forEach(function (evt) {
            $(document).unbind(evt);
        });
})(jQuery);

哈哈哈,像我这么写这两段代码太恶劣了,太偷懒了,然后就可以合体出兼容性更好的方案

(function ($) {
    ['contextmenu', 'dragstart', 'mouseup', 'copy', 'beforecopy', 'selectstart', 'select', 'keydown']
        .forEach(function (evt) {
            document.body['on' + evt] = null;
            if ($)
                $(document).unbind(evt);
        });
})(window.jQuery);

当然,绑定的话,不一定是绑定在body或者document元素。可能是绑在某个div那里,就不恶意卖萌加段代码了。这个时候,我们就要对整个页面元素 document.all 都解绑一次,然后你会发现漏掉了 window 和document 这两个也是可以绑定的,所以必须补上。

灯灯灯灯,大家久等的代码:

(function (window) {
    var eventArr = ['contextmenu', 'dragstart', 'mouseup', 'copy', 'beforecopy', 'selectstart', 'select', 'keydown'];

    function runScript(window) {
        var document = window["document"],
            $ = window["jQuery"],
            unbind = function (ele) {
                eventArr.forEach(function (evt) {
                    ele['on' + evt] = null;
                    if ($) {
                        $(ele).unbind(evt);
                    }
                });
            };
        [window, document].forEach(unbind);
        for (var i = 0, all = document.all, len = all.length; i < len; i++) {
            var ele = all[i];
            if (ele && ele.nodeType === 1) {
                unbind(ele);
            }
        }
    }
    runScript(window);
})(window);

另外,跑到这里的时候,你会发现在路由器管理页面的右键禁止你是无法解决。 因为用了frameset 和iframe。 所以,在遍历元素的时候,要对frame和iframe 进行操作。同时要反防止跨域的js权限问题,导致后面的元素没跑,也把try catch加上。

 1 (function (window) {
 2     var eventArr = ['contextmenu', 'dragstart', 'mouseup', 'copy', 'beforecopy', 'selectstart', 'select', 'keydown'];
 3 
 4     function runScript(window) {
 5         var document = window["document"],
 6             $ = window["jQuery"],
 7             unbind = function (ele) {
 8                 eventArr.forEach(function (evt) {
 9                     ele['on' + evt] = null;
10                     if ($) {
11                         $(ele).unbind(evt);
12                     }
13                     try {
14                         if (/frame/i.test(ele.tagName)) {
15                             runScript(ele.contentWindow);
16                         }
17                     } catch (err) {
18                     }
19                 });
20             };
21         [window, document].forEach(unbind);
22         for (var i = 0, all = document.all, len = all.length; i < len; i++) {
23             var ele = all[i];
24             if (ele && ele.nodeType === 1) {
25                 unbind(ele);
26             }
27         }
28     }
29 
30     runScript(window);
31 })(window);

然后,有史以来兼容性最强的解决页面功能被禁用的方案终于出炉了。

利用谷歌那啥 js压缩编译器来着,压一下的话共398个字符(唉,我数得可辛苦了/(ㄒoㄒ)/~~)···对应是书签代码也出来了。把这个加到书签里面有事点一点···

javascript:(function(c){function e(a){var b=a.document,f=a.jQuery,g=function(a){h.forEach(function(b){a["on"+b]=null;f&&f(a).unbind(b);try{/frame/i.test(a.tagName)&&e(a.contentWindow)}catch(c){}})};[a,b].forEach(g);a=0;for(var b=b.all,c=b.length;a<c;a++){var d=b[a];d&&1===d.nodeType&&g(d)}}var h="contextmenu dragstart mouseup copy beforecopy selectstart select keydown".split(" ");e(c)})(window);

  所以说,禁止页面功能不能用简单方法来实现。如果让我写的话,至少也会实现成这样,看你丫的怎么解绑我原生匿名函数···

(function (window) {
    function bindEvent(elem, event, handler, useCapture) {
        event = event.replace(/^on/ig, "").toLowerCase();
        if (elem.addEventListener) {
            elem.addEventListener(event, handler, useCapture);
            return true;
        }
        else if (elem.attachEvent) {
            return elem.attachEvent('on' + event, handler);
        }
        elem['on' + event] = handler;
    }


    ['contextmenu', 'dragstart', 'beforecopy', 'copy', 'cut', 'paste', 'selectstart', 'select']
        .forEach(function (evt) {

            bindEvent(window, evt, function () {
                cancBub(evt);

                return prtDtV(evt);

                function cancBub(evt) {
                    var e = window.event || evt;
                    e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true
                }

                function prtDtV(evt) {
                    var e = window.event || evt;
                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
                    return false;
                }
            })
        });

})(window);

最后,我看了他这代码一眼,默默选择在那个页面关掉了浏览器的javascript功能···

posted @ 2015-04-25 05:04  Nieg  阅读(...)  评论(...编辑  收藏