最近看到有些论坛在讨论js压缩、混淆和加密的问题,特意找了些资料看了下,现在总结一下:
1.关于三者的定义与区别
压缩:删除 Javascript 代码中所有注释、跳格符号、换行符号及无用的空格,从而压缩 JS 文件大小,优化页面加载速度。
混淆:经过编码将变量和函数原命名改为毫无意义的命名(如function(a,b,c,e,g)等),以防止他人窥视和窃取 Javascript 源代码,也有一定压缩效果。
加密:一般用eval方法加密,效果与混淆相似,也做到了压缩的效果。
从定义中可以看出,压缩的主要目的是消除注释等无用字符,达到精简js代码,减小js文件大小的目的,这也是页面优化的一种方式;而混淆和加密的目的比较接近,都是为了防止他人直接查看源码,对代码(如重要的api等)起保护作用,但这也只是增加了阅读代码的代价,也就是所谓的防君子不防小人。但是当混淆和加密联合使用时,如先混淆在加密(或者先加密再混淆)时,破解时间就会增加。关于js的加密,可以参考这篇文章:http://www.cnblogs.com/top5/archive/2009/08/07/1540860.html
2.demo
下面以更直观的方式来体会一下这四种方式(压缩、混淆、加密、混淆&加密)的不同。
源js代码如下:
/* 这个是一个类 */
function xx(num, str) {
//说明
var a = num;
this.aa = a;
this.bb = function() {alert(str);}
this.cc = function() {
for (var i = 0; i < 10; i++) {
document.title = i;
}
}
this.yy = new yy();
function xxf() {
alert("xxf");
if ((/\{\d+\}/).test("a\sdf{2}ab"))
alert("{\\d} is match!");
}
}
xx.prototype.dd = function(){
alert("dd");
a.yy.ll();
var fnx = function(i) {
this.ab = i;
this.aa = function(){
alert(this.ab);
}
}
var f1 = new fnx(1);
f1.aa();
}
function yy(){
alert('yy');
}
yy.prototype.ll = function() {
alert("yyll");
}
var a = new xx(100, "hello"), b = new xx(0, "ttyp");
eval("a.aa=20");
a.bb();
b.dd();
alert(a.aa);
var k = 9;
function kk() {
var k = 0;
alert(k);
}
kk();
alert(k);
//输入结果alert:"yy"->"yy"->"hello"->"dd"->"yyll"->"12"->"20"->"0"->"9"
(1)经过压缩后的代码如下:
1 function xx(num,str){var a=num;this.aa=a;this.bb=function(){alert(str)};this.cc=function(){for(var i=0;i<10;i++){document.title=i}};this.yy=new yy();function xxf(){alert("xxf");if((/\{\d+\}/).test("a\sdf{2}ab"))alert("{\\d} is match!")}};xx.prototype.dd=function(){alert("dd");a.yy.ll();var fnx=function(i){this.ab=i;this.aa=function(){alert(this.ab)}};var f1=new fnx(1);f1.aa()};function yy(){alert('yy')};yy.prototype.ll=function(){alert("yyll")};var a=new xx(100,"hello"),b=new xx(0,"ttyp");eval("a.aa=20");a.bb();b.dd();alert(a.aa);var k=9;function kk(){var k=0;alert(k)};kk();alert(k);
压缩后与源码相比只是少了注释、空格、换行等。
(2)经过混淆后的代码如下:
1 function xx(d,e){var f=d;this.aa=f;this.bb=function(){alert(e)};this.cc=function(){for(var g=0;g<10;g++){document.title=g}};this.yy=new yy();function xxf(){alert("xxf");if((/\{\d+\}/).test("a\sdf{2}ab"))alert("{\\d} is match!")}};xx.prototype.dd=function(){alert("dd");a.yy.ll();var fnx=function(e){this.ab=e;this.aa=function(){alert(this.ab)}};var d=new fnx(1);d.aa()};function yy(){alert('yy')};yy.prototype.ll=function(){alert("yyll")};var a=new xx(100,"hello"),b=new xx(0,"ttyp");eval("a.aa=20");a.bb();b.dd();alert(a.aa);var c=9;function kk(){var d=0;alert(d)};kk();alert(c);
混淆后除了少了注释、空格和换行等,参数也被a,b,c,d,e等字符代替,提高了阅读的难度。
(3)经过加密后的代码如下:
1 eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('3 e(o,l){5 a=o;6.8=a;6.p=3(){4(l)};6.B=3(){A(5 i=0;i
加密后除了有混淆的作用外,有些代码被加密了,进一步提高了阅读的难度。
(4)经过混淆&加密后的代码如下
eval(function(p,a,c,k,e,d){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('4 i(d,e){5 f=d;6.8=f;6.p=4(){3(e)};6.s=4(){t(5 g=0;g
3.浏览器是怎么解析混淆和加密后的js代码的
其实变量名只要是Unicode字符就行了,对于js引擎来说都是一样的,只是人类觉得他们不同而已。
4.js压缩工具
其实js的压缩工具网上有很多,在线和安装版的都有,文章中使用的是HDS JSObfuscator v2.13绿色版。
在线的js压缩工具:http://tool.chinaz.com/js.aspx
5.注意事项
源js文件一定要按照规范编写,分号,注释符,var等都要规范,否则很容易出错。
6.参考文章
(1)http://m.blog.csdn.net/blog/Shb_derek/25032169
(2)http://blog.csdn.net/kof820/article/details/19345929
(3)http://www.zhihu.com/question/29169806
转载 一切都是傅里叶!