代码改变世界

Javascript 简单加密防止公布在网页上的邮箱被收集

2012-02-23 16:35  chris-shao  阅读(2609)  评论(5编辑  收藏  举报

需求描述:

 

由于业务需求,很多企业网站都需要在自己网站上公布邮箱, 但是,却经常被一些自动的邮箱收集工具收集之后,受到垃圾邮件的困扰。

 

一般邮箱收集工具主要就是通过蜘蛛的方式,扫描网页,然后通过正则表达式获取邮箱地址,比如匹配:mailto, 或者 @ 符号,这样在网页中出现的<a href='mailto:xxxx@sss.com'>xxxx</a> 这样的邮箱都难逃脱被收集的厄运。有网站不得不将@符号替换为#号,然后再提醒用户自行替换。

 

技术方案:

首先考虑可以使用脚本来创建这样的链接:

<script>document.write('<a href="mailto:xxx@sss.com"></a>')</script>

 

然后只要对write中的内容稍作改动,即可轻松避免收集工具。

于是,改进如下:

 

<script>document.write('<a href="mailto:xxx"+"@"+"sss.com"></a>')</script>

这样,是不是就可以避免一部分工具呢?

然后再考虑复杂一些,这里加入一个简单的加密处理:

 <script>

var s='amlioti:fn@osaaiansblotu.eocu.k';

var r='';

for(var i=0;i<s.length;i++,i++)

{

 r=r+s.substring(i+1,i+2)+s.substring(i,i+1);

}

document.write('<a href="'+r+'"</a>');

</script>


 仔细看一下很简单,无非就是把邮箱的字母位置进行颠倒,0和1颠倒,2和3颠倒……

 

然后为了让肉眼再无法辨识,使用script 的eval 方法,并且将这段脚本htmlEncoding

 

即变成:

 

<script>eval(unescape('%76%61%72%20%73%3d%27%61%6d%6c%69%6f%74%69%3a%66%6e%40%6f%73%61%61%69%61%6e%73%62%6c%6f%74%75%2e%65%6f%63%75%2e%6b%27%3b%76%61%72%20%72%3d%27%27%3b%66%6f%72%28%76%61%72%20%69%3d%30%3b%69%3c%73%2e%6c%65%6e%67%74%68%3b%69%2b%2b%2c%69%2b%2b%29%7b%72%3d%72%2b%73%2e%73%75%62%73%74%72%69%6e%67%28%69%2b%31%2c%69%2b%32%29%2b%73%2e%73%75%62%73%74%72%69%6e%67%28%69%2c%69%2b%31%29%7d%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%27%2b%72%2b%27%22%3e%69%6e%66%6f%40%61%73%69%61%6e%61%62%73%6f%6c%75%74%65%2e%63%6f%2e%75%6b%3c%2f%61%3e%27%29%3b'))</script>

 

如此一来,抓取工具就傻眼了。

 

附上生成处理脚本的C#代码:通过这个代码,就可以直接创建类似的脚本了 :

 

            string s = "mailto:info@asianabsolute.co.uk";
            string r = "";
            string lastchar = s.Length % 2 == 1 ? s[s.Length - 1].ToString() : "";
            for (int i = 0; i < s.Length; i=i+2)
            {
                if(i<s.Length-1)
                    r = r + s.Substring(i+1 , 1) + s.Substring(i, 1);
            }
            r = r + lastchar;
            string js = "var s='" + r + "';var r='';for(var i=0;i<s.length;i++,i++){r=r+s.substring(i+1,i+2)+s.substring(i,i+1)}document.write('<a href=\"'+r+'\">info@asianabsolute.co.uk</a>');";
            Console.WriteLine(js);
            Console.WriteLine(UrlEncode(js));

 

 另外,将字符串保存为16进制显示的编码方法:

        static string UrlEncode(string str)
        {
            StringBuilder sb = new StringBuilder();
            byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str);
            for (int i = 0; i < byStr.Length; i++)
            {
                sb.Append(@"%" + Convert.ToString(byStr[i], 16));
            }

            return (sb.ToString());
        }
 

遗留问题:

这个方案是建立在收集工具未进行DOM检查的基础上的。如果收集工具在获取HTML 后又进行了页面脚本调用显示后,还是会在DOM中创建连接,这种情况下,就还是能够捕获了。

 

不过只要是破解的收益高于成本,应该是没有不能破解的加密的吧,所以,在做网站时,适当的使用这样的方式加密敏感信息,还是能够起一定作用的。