为什么写这个文章:
最近公司要求编写一个页面,让我们能够在页面填写sql语句,然后将语句传递到后台,存入数据库中,在存入过程中,顺便调用一下我们的这个sql语句,查询数据,将数据转成json格式,顺手存入数据库。
存入过程中发现,from表单对select,where等sql字段做了屏蔽,比如select * from aaa 最后后台接收了一个“”;
经过大佬指点,最后用了一种办法就是,在前台像后台传递sql语句的时候,将sql语句进行二次包装,然后进入后台后,再通过方法转成原本的语句
分为2部分,一个是后台的加密与解密 ,一个是前台的加密(因为前台需要做的只是一个传输,数据库中存的还是正常的sql语句,所以没有解密只有加密)
/** * 加密, * searchFrom:sql语句 * dates:时间 随便一个固定时间例如2011-11-11 11:11:11 * 实际用于加密的也只是时间里的秒。。说白了就是取一个数字用作加密而已 */ public static String ecodeSql(String searchFrom,String dates){ if(Util.isNull(searchFrom)){ return ""; } String dataStr = dates.substring(17,19); int addNum = Integer.parseInt(dataStr); searchFrom = searchFrom.replaceAll("\\-","-992@"); searchFrom = searchFrom.replaceAll("\\+","-991@"); String keyStr = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM=%'"; int i=0; for(String key:keyStr.split("")){ i++; searchFrom = searchFrom.replaceAll(key,"-"+(i+addNum)+"@"); } return searchFrom; }
/** * 解密 * searchFrom 之前加密之后的语句 * dates 加密时所用的时间 */ public static String unecodeSql(String searchFrom,String dates){ if(Util.isNull(searchFrom)){ return ""; } String dataStr = dates.substring(17,19); int addNum = Integer.parseInt(dataStr); searchFrom = searchFrom.replaceAll("-992@","\\-"); searchFrom = searchFrom.replaceAll("-991@","\\+"); String keyStr = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM=%'"; int i=0; if(Util.isNull(searchFrom)){ searchFrom = ""; }else{ for(String key:keyStr.split("")){ i++; searchFrom = searchFrom.replaceAll("-"+(i+addNum)+"@",key); } } return searchFrom; }
接下来给大家看一下调用方法与调用结果
红色为加密之后的sql 蓝色为解密之后的sql
亲自测试,1000个字符的sql语句完全可以正常加密解密,包括子查询,左联,union all,case when,sum,concat,curdate()等都可以加密与解密。。。。。。。。。最晕晕的是我在sql语句里写了一个身份证验证的正则都可以(可以正常作为sql语句跑的正则)
// 自动生成执行语句 public static void main(String[] args){ String kk = UtilSql.ecodeSql( " * from aa ", "2021-11-11 11:11:11"); String ss = UtilSql.unecodeSql(kk,"2021-11-11 11:11:11"); System.out.println(kk); System.out.println(ss); }
// todo 调用的写法,需要在前后加上[#],尽管我也不知道可不可以不加,懒得去测试 // todo 这样生成的语句会在前后会有[#],传到后台之后给.replaceAll("\\[#\\]","")一下就OK了 ecodesd('[#]select * from aaa[#]',"2021-11-11 11:11:11") /** * 前台加密,有一点是前台需要加特殊符号 * searchFrom 加了特殊符号之后的sql语句 * dateTemp 定义一个时间(建议和后台的时间一样) */ function ecodesd(searchFrom,dateTemp){ var dataStr = dateTemp.substring(17,19); var addNum = parseInt(dataStr); searchFrom = searchFrom.replace("-","-992@"); searchFrom = searchFrom.replace("+","-991@"); var keyStr = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM=%'"; var keyList = keyStr.split(""); for(var i=0;i<keyList.length;i++){ var key = keyList[i] var reg = new RegExp(key,"g"); searchFrom = searchFrom.replace(reg,"-"+((i+1)+addNum)+"@"); } return searchFrom; }