实例一:360doc 禁止复制

如题。每当你要复制 360doc 上的文字时,就会跳出一个对话框,告诉你“登录即可复制”。

用火狐打开一篇这样的文档,F12 打开查看器,发现<body>节点旁有ev,点击展开。在事件列表中,有一条是这样的:

copy http://www.360doc.com/js/showarticle.js?...

访问http://www.360doc.com/js/showarticle.js,发现 JS 代码经过混淆,于是把代码复制到这里解混淆。得到四千多行代码。

搜索oncopy发现

document.body.oncopy = function() {
    return copyArt()
}

于是找到copyArt()函数:

function copyArt() {
    var CurUserNameCookiescgcg = getCookie("LoginName");
    if (CurUserNameCookiescgcg == "" || CurUserNameCookiescgcg == null) {
        var docarttitle = document.getElementById("docarttitle");
        var docencodetitle = "";
        if (docarttitle == null) {
            docencodetitle = ""
        } else {
            docencodetitle = "&titleencode=" + docarttitle.value
        }
        $("#LayerLogin").load('/artlogin.html');
        $("#LayerLogin").show();
        ArtLoginTypeID = 0;
        artStatistics('20-21-1');
        return false
    } else {
        var selhtml = "";
        var selection;
        if (window.getSelection) {
            selection = window.getSelection();
            if (selection != null) {
                selhtml = selection.toString()
            }
        } else if (document.selection) {
            selection = document.selection.createRange();
            if (selection != null) {
                selhtml = selection.text
            }
        }
        if (selhtml.length > 200) {
            document.getElementById("fuzhitishidiv").style.display = 'none';
            if (getCookie("360doc1") != null && UserID != 0) {
                $.ajax({
                    url: "http://www.360doc.com/ajax/GetLoginForm20130912.ashx?ArtID=" + ArticleID + "&type=5&arttype=" + CurArtType + "",
                    cache: false,
                    success: function(result) {
                        if (result == "-1") {
                            return true
                        } else {
                            showfuzhitishidiv();
                            return false
                        }
                    },
                    error: onFailed
                })
            } else {
                showfuzhitishidiv();
                return false
            }
        } else {
            return true
        }
    }
}

逻辑已经很清楚了。

那么如何破解呢?很简单,只要在火狐的控制台中重新设置监听事件对应的方法即可:

document.body.oncopy=""

注意,重新加载网页后将失效,需要重新设置。

实例二:慕课网自动添加出处信息

很巧,我在慕课网上也发现了类似的机制。但是慕课网没有禁止复制,而是在你复制的内容尾部自动添加了作者和出处信息。

我们以《什么是拜占庭将军问题》这篇文章为例来探究一下。

首先看一下效果:

我们复制这篇文章的开头:

接触区块链的同学,多少都听说过拜占庭将军问题,经常看到或听到某某区块链使用某某算法解决了拜占庭将军问题,那么究竟什么是拜占庭将军问题呢?

剪贴板上实际得到的是:

接触区块链的同学,多少都听说过拜占庭将军问题,经常看到或听到某某区块链使用某某算法解决了拜占庭将军问题,那么究竟什么是拜占庭将军问题呢?
作者: 叮咚一浮云
链接:https://www.imooc.com/article/23622
来源:慕课网

采用实例一中的方法,但是我们在body中没有找到oncopy事件。经过测试,我们发现只有在复制文章正文文字时才会有上述效果。层层递进,终于在

<div class="detail-content js-lookimg">
...

这里找到了oncopy

同样转到 JS 代码,慕课网没有做混淆:

function addCopyright() {
  var a = "</br>作者:" + $author + "</br>链接:" + location.href + "</br>来源:慕课网</br>" + $original;
  if ("undefined" != typeof window.getSelection) {
    var c = document.getElementsByTagName("body")[0],
      g = window.getSelection(),
      h = document.createElement("div");
    h.style.position = "absolute", h.style.left = "-99999px", c.appendChild(h), h.appendChild(g.getRangeAt(0).cloneContents()), "PRE" == g.getRangeAt(0).commonAncestorContainer.nodeName && (h.innerHTML = "<pre>" + h.innerHTML + "</pre>"), h.innerHTML += a, g.selectAllChildren(h), window.setTimeout(function() {
      c.removeChild(h)
    }, 200)
  }
}

还是很明了的。

但这里的oncopy不在body节点上,怎么办呢?可以使用一个万能的方法:移除当前网页中所有oncopy事件:

$('*').removeAttr('oncopy');

这个方法对实例一也适用。

参考