某快消品行業“進銷存管理系統“ ,由於歷史原因其前頁面展示採用jsp,js引用採用的是原始的文件引入、全局變量調用,甚至很多事件綁定直接基於html元素的onclick屬性實現。現在甲方提出,儘量提高系統安全性,包括js代碼安全性,那麼問題來了,如何提高js代碼安全性?通用做法有2:
- js壓縮,去除註釋、空格、換行符等字符;
- js混淆,替換變量,目的是代碼依然在,但是通常不知道啥意思;
- 也有所謂的加密,本質上就是高級混淆。
由於項目前後端未分離,js引用也未採用模塊化,因此使用常見的webpack打包實現js代碼混淆肯定不合適,那麼如何實現?
- 引用開源的js混淆庫,obfuscator.io
- 自己用java寫個混淆處理類,批量將jsp頁面中<script>標籤中的js代碼、js文件中的js代碼調用js混淆庫,混淆處理後替換原文件。
1、原項目概述
WebContent
|-assets
|-css
|-images
|-js
|-app
|-page-bill.js
|-page-zj.js
...
|-views
|-site
|-index.jsp
|-login.jsp
...
|-sales
|-order-create.jsp
...
1)jsp頁面有大量<script>代碼,如:
</div><!-- /.modal -->
<%@ include file="/views/layouts/main-body.jspf"%>
<script src="<%=res_url%>/assets/js/jsAddress.js?t=<%=tag%>"></script>
<script src="<%=base_url%>/assets/js/app/page-zj.js?t=<%=tag%>"></script>
<script type="text/javascript">
var jxsData = [];//緩存經銷商信息
//修改經銷商信息
function edit_vendors(obj){
var table = $('#example').DataTable();
currentTr = $(obj).closest('tr');
var rowData = table.row(currentTr).data();
rowData.method = "edit";
openvendorsDialog(rowData);
}
...
2)jsp頁面中有大量的事件處理函數,通過元素的onclick屬性定義
<div class="btn-group">
<button id="search" class="btn btn-primary btn-sm mr-2" onclick="search(this)">
<span class="fa fa-search"></span> 查詢</button>
<button id="export" class="btn btn-primary btn-sm" onclick="search(this)">
<span class="glyphicon glyphicon-export"></span> 導出</button>
</div>
3)引用的js文件,只是引入代碼,未模塊化
2、部署js混淆node服務
1)從git獲取項目,https://github.com/javascript-obfuscator/javascript-obfuscator-ui
2)部署node.js,啓動項目中的server.js,本案例端口號修改爲20001
3)加密接口http://xx.xom:20001/obfuscate
java通過httpclient組件可以調用http://xx.xom:20001/obfuscate接口進行js加密。
參數: {"code": "要加密的js串"}
返回結果:{"code": "加密後的js串", "sourceMap": ""}
3、編寫java類進行jsp文件、js文件批量加密處理
脫敏需要,不提供具體java代碼,有需要請私信或im聯繫我。
1)必須指定js或jsp文件,或者文件夾
如果文件夾則遍歷該文件夾,得到要處理的js、jsp文件列表,List<String> files
2)遍歷files,逐個加密
for (String file : files) {
if (file 是js文件) {
String jsMinwen = readFile(file);
if(! jsMinwen.startWith(";;;")) { //用;;;開頭表示十分已經加密過
String jsMiwen = jiamiJs(jsMinwen); //加密時,返回串最前面會添加;;;,用於判斷二次加密
writeFile(file, jsMiwen);
}
} else if (file 是jsp文件) {
String fileContent = readFile(file);
String dealContent = 正則匹配,替換 "<script>...</script>","<script type='text/javascript'>...</script>"; //有多個<script>...</script>需要遍歷替換
writeFile(file, dealContent);
}
}
3)調用js加密接口
HttpClient 實現
url: xx.com:20001/obfuscate
參數:json字符串,"{\"code\":\"js明文\"}",可以定義一個Map<String,String>,然後轉換爲json字符串;
請求mimeType:application/json
//
String strResult = HttpClientUtil.post(url, TypeUtil.toJson(para), "application/json",
HttpClientUtil.CHARSET_UTF8, 36000, 36000);
if (strResult.indexOf("\"code\":") > -1) { // success, {"code":"var _0x190d=
Map<String, Object> result = TypeUtil.toObjct(strResult, HashMap.class);
miwen = hanziToUnicode(";;;" + result.get("code")); //漢字轉unicode
} else {
miwen = strResult;
}