今天思考下前端源碼安全的東西(不是前端安全,只是針對於源碼部分)。在我看來,源碼安全有兩點,一是防止抄襲,二是防止被攻破。實際上講,前端的代碼大多是沒有什麼可抄襲性,安全更是形同虛設的(任何前端輸入都是不能相信的)。但如果還是想防止源碼被查看,HTML、CSS並不能做什麼,最終都會用露出來(最簡單用
今天思考下前端源碼安全的東西(不是前端安全,只是針對於源碼部分)。在我看來,源碼安全有兩點,一是防止抄襲,二是防止被攻破。實際上講,前端的代碼大多是沒有什麼可抄襲性,安全更是形同虛設的(任何前端輸入都是不能相信的)。但如果還是想防止源碼被查看,HTML、CSS並不能做什麼,最終都會用露出來(最簡單用Chrome開發者工具就可以看到),所以只能針對JS做文件的壓縮合併和混淆。
關於抄襲
其實就前端來講,代碼沒有什麼好抄襲的,大多人都是抄UI設計(這個是躲不了),還有一些富前端的控制項和演算法,重要之處還是在於後端,而後端是抄不了的。所以前端文件壓縮合併,目的並不是防止抄襲,而是為了減少文件體積、加快載入速度,提高程式的執行性能,當然壓縮也有混淆的功能。文件混淆是防止其他人查看代碼邏輯,但是生成的代碼比原代碼體積大得多,所以文件如果做了混淆,載入速度和執行速度都會有所下降。
關於安全
所有的用戶輸入都是不能相信的,如果後端的檢查校驗還做得不好,那就可能被攻破。前端代碼的邏輯如果還被瞭解清楚,那就是雪上加霜。後端的問題我們前端管不著,前端的代碼安全,簡單的可以用壓縮解決、再進一步就去混淆,讓別人看不懂。
HTML壓縮
很少有人去做HTML的壓縮(特指去除空白字元和註釋),根據其他資料有幾個原因:
1. HTML文檔中,多個空白字元等價為一個空白字元。也就是說換行等空白字元的刪除是不安全的,可能導致元素的樣式產生差異。
2. HTML元素中,有一個pre, 表示 preformatted text. 裡面的任何空白,都不能被刪除。
3. HTML中有可能有 IE 條件註釋。這些條件註釋是文檔邏輯的一部分,不能被刪除。
也是鑒於上面幾個原因,不提倡壓縮HTML,通過gzip壓縮就已經能達到很好的效果。
CSS壓縮合併
CSS壓縮合併很常見,或者說是必做的,可以由後端動態生成或工具提前生成。目的也只是為了提高載入速度,CSS即便的壓縮之後,代碼也是清晰可見,沒有混淆說法。CSS壓縮合併的工具很多,一般是用sass、less直接生成壓縮後的CSS,如果是直接壓縮,用grunt還不錯。
JS壓縮合併混淆
在生產環境上,壓縮合併是必做的。就如上面說的,目的不是為了防止暴露業務邏輯,是為了提高載入速度。在上一篇文章《AngularJS結合RequireJS做文件合併壓縮的那些坑》,說了一點JS壓縮合併要註意的東西。除了用RequireJS,直接使用grunt來做發佈是不錯的方式,開發後一鍵調用grunt。
grunt需要配置兩個文件:
package.json:聲明應用信息和使用依賴庫的版本
{ "name":"BingoTouch", "version":"3.0.0", "engines":{ "node":">= 0.8.0" }, "devDependencies":{ "grunt":"~0.4.0", "grunt-contrib-concat":"~0.3.0", "grunt-contrib-copy" : "~0.4.1", "grunt-contrib-cssmin" : "~0.6.0", "grunt-contrib-uglify":"~0.2.0", "express":"" } }
Gruntfile.js:聲明壓縮合併的文件
module.exports = function(grunt){ grunt.initConfig({ pkg : grunt.file.readJSON('package.json'), concat : { 'dist/bingotouch.js' : [ 'demo/js/ui.js', 'demo/js/module/ui.GarbageCollection.js', 'demo/js/module/ui.plugins.js'] }, uglify : { target : { files : { 'dist/bingotouch.min.js': 'dist/bingotouch.js' } } } }); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.registerTask('default', ['concat','uglify']); }
JS的混淆我到現在為止還沒用過,原理都是類似的,混淆是把JS代碼變成亂七八糟的字元串,然後用eval執行。
PS:uglify本身有一定的混淆作用,但也只是對變數名的混淆,混淆度並不夠。
混淆前:
function hello(){ alert('hello'); }
混淆後:
eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[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}('1 0(){2(\'0\')}',3,3,'hello|function|alert'.split('|'),0,{}))
不同混淆演算法混淆的結果不一樣,而且混淆後也不是一勞永逸,還是可以被反混淆的。另外混淆會降低程式執行性能,所以是否需要做混淆得做評估。
總結
我覺得做好文件壓縮合併,簡單的變數名混淆就可以了,並不需要那麼徹底的混淆。即便是前端被人挖得清清楚楚,只要後端強勁也就沒問題了。所以當你想進行代碼混淆時候,想想是為了什麼,值不值得。
本文為原創文章,轉載請保留原出處,方便溯源,如有錯誤地方,謝謝指正。
本文地址 :http://www.cnblogs.com/lovesong/p/5185543.html