继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

探一探慕课复制到剪贴板的内容可以被修改成指定内容究竟是怎么回事

dorseyCh
关注TA
已关注
手记 50
粉丝 1.3万
获赞 1519

  我们在访问慕课网的时候,可以不经意中发现,复制进剪贴板的信息被修改了,加入了一些版权信息什么的,比如下面这样:
图片描述
  可能你可以不假思索的想到,获取剪贴板的信息,再做一定修改,再重新设置剪贴板的信息。这在IE下是完全可行的。
  IE有一个clipboardData对象。通过clipboardData对象可以取到相应的数据。

window.clipboardData.getData("Text");

比如说下面这样:
图片描述
  然而这样实际上非常恐怖,因为仅仅只需要一句代码,就可以获得你系统的剪切板内容,假如说用户在本地的words文档刚好复制了一些非常机密的内容,而接下来刚好打开了某个具有上方代码脚本的网站,那你剪切板的内容不知不觉就被截取了,你的隐私受到了直接威胁。

  所以除了IE,其他浏览器基本上都是不能获取系统剪切板内容的,无论你怎么操作。

  事实上其他浏览器还是同样有copy事件的。我们看一下:

    $('body').on('copy', function (e) {

        e.preventDefault();//阻止默认行为

        if(!window.clipboardData) {

            window.clipboardData = e.originalEvent.clipboardData;
        }
        console.log(clipboardData.getData("text/plain")); //	无论你怎么获取都是空
        console.log(e);
        console.log(e.originalEvent);
        console.log(clipboardData);
    });

我们打印一下事件 event。
  可以发现,在event对象下originalEvent下有一个clipboardData对象,即剪切板对象。那尝试一下看看能不能拿到剪切板的数据。你会发现无论你copy啥,items的长度永远是0,出来的结果也永远为空。这是很好的,因为会比较安全。
图片描述
  那其他浏览器为了隐私安全默认不给拿剪切板的数据(当然你可以通过改变浏览器的配置),那设置剪切板的数据可以吗?因为设置,改变剪切板的数据并不会造成隐私问题。

  实际上是可以的。

  看一下代码:

   $('body').on('copy', function (e) {

       e.preventDefault();//阻止默认行为

       if(!window.clipboardData) {

           window.clipboardData = e.originalEvent.clipboardData;
       }
       clipboardData.setData('text/plain','hello, my name is dorsey');
   });

  此时你会发现,无论你怎么copy,是ctrl + C还是鼠标右键拷贝,最终的ctrl + V结果都是hello, my name is dorsey。

  尽管我们能设置剪切板的值,然而设置的值大多都是基于用户复制的结果做一些补充,比如加一些版权信息,加一些作者自定义信息。然而浏览器的隐私安全机制导致我们无法拿剪切板的内容。那又该如何着手?
  看了慕课网有这样的功能,而通常此类的方式,有一个办法是通过flash来获取。那我们关闭一下浏览器的flash。看看慕课网的这个修改剪切板的效果会不会消失。
图片描述
  此时,再次去慕课网拷贝,你会发现,效果还是在。那到底它是怎么拿到复制的内容的呢?
  既然剪切板无法拿到数据,那何不换个角度,既然你要复制,那首先得选中要复制的内容,对吧?那是不是有什么API是可以拿到这个值的呢?
  答案是肯定的。

        $('body').on('copy', function (e) {

            e.preventDefault();//阻止默认行为
            var select = getSelection();
            console.log(select.toString());
        });

  看一下getSelection到底返回了什么?
  直接查看对象里面的什么选取开始节点什么的可能不是很直观,但这个可以直接通过toString方法直接返回那串字符串。看看MDN:
图片描述
  此时,当你拷贝了啥,在控制台就很自然的打印了啥。这样我们想要的结果就拿到了。
  那慕课网的实现机制是否是这样的呢?我们看一看它的代码,经过查找,找到这样的片段。
图片描述
  这个片段是移除我们所选内容,而刚刚的toString()方法是否会被用到呢?
  好像没有,有些尴尬哈,不过实现的方式还是贴出来给大家看看。
图片描述
  当然实际的开发可能并非通过ES5以下的开发方式,而是通过ES6+webpack+babel打包的方式来转译,但其实只要看到我们想要的内容,知道了它的实现机理,那就够了。
  基于上面的思考,简单实现一个看看:
  HTML部分:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>change copy content</title>
</head>
<body>
    <div>你好啊</div>
    1231232123198
    <script src='../jquery.min.js' type='text/javascript'></script>
    <script src='js/changeCopyContent.js' type='text/javascript'></script>
</body>
</html>

  JavaScript部分


$(function () {

    contain.initPage();
    contain.initEvent();
});

(function (factory) {

    factory();

})(function () {

    window.contain = {

        initEvent: initEvent,
        initPage: initPage
    }

    function initPage () {

        initDOMHeight();
    }

    function initEvent () {

        $('body').on('copy', function (e) {

            e.preventDefault();//阻止默认行为
            var select = getSelection();

            if(!window.clipboardData) {

                window.clipboardData = e.originalEvent.clipboardData;
            }
            clipboardData.setData('text/plain', select + '\n\nhello, my name is dorsey');

            
            // console.log(clipboardData.getData("text/plain"));

            // clipboardData.setData('text/plain','hello, my name is dorsey');
            
            // console.log(e);
            // console.log(e.originalEvent);
            // console.log(clipboardData);
            
        });
        
    }

    function initDOMHeight () {

        $('body').css('height', document.documentElement.clientHeight + 'px');
    }
})

再看一下效果:
图片描述

打开App,阅读手记
2人推荐
发表评论
随时随地看视频慕课网APP