From c64e1248bfda3ac8c5120e529fd096dfc4846629 Mon Sep 17 00:00:00 2001 From: chenjiahe <763432473@qq.com> Date: 星期四, 13 一月 2022 15:20:24 +0800 Subject: [PATCH] AES加密插件 --- src/main/java/com/hx/mybatis/aes/handler/GenericStringHandler.java | 24 + src/main/java/com/hx/mybatis/aes/springbean/ConstantBean.java | 35 ++ /dev/null | 34 -- src/main/java/com/hx/mybatis/aes/springbean/SqlUtils.java | 481 ++++++++++++++++++++++++++++++++ src/main/java/com/hx/common/annotations/MysqlHexAes.java | 12 src/main/java/com/hx/mybatis/aes/springbean/ExportTableAliasVisitor.java | 53 +++ src/main/java/com/hx/mybatis/aes/springbean/VariableAesKey.java | 126 +++++--- src/main/java/com/hx/mybatis/aes/springbean/MySqlInterceptor.java | 96 ++++++ 8 files changed, 773 insertions(+), 88 deletions(-) diff --git a/src/main/java/com/hx/common/annotations/MysqlHexAes.java b/src/main/java/com/hx/common/annotations/MysqlHexAes.java index a143106..4696b88 100644 --- a/src/main/java/com/hx/common/annotations/MysqlHexAes.java +++ b/src/main/java/com/hx/common/annotations/MysqlHexAes.java @@ -10,11 +10,13 @@ @Retention(RetentionPolicy.RUNTIME) @Documented public @interface MysqlHexAes { - /**绉橀挜瀛楁*/ - String aesKeyField() default ""; - /**绉橀挜*/ - String aesKey(); - /**鏌ヨ瑙e瘑*/ + /**绉橀挜-娌℃湁灏辨槸閰嶇疆鏂囦欢璁剧疆*/ + String aesKey() default ""; + /**xml鐢熸垚鏌ヨ瑙e瘑*/ boolean selectDec() default false; + /**xml鏇存柊鍔犲瘑*/ + boolean updateDec() default false; + /**xml鏂板鍔犲瘑*/ + boolean insertDec() default false; } \ No newline at end of file diff --git a/src/main/java/com/hx/mybatis/handler/aes/GenericStringHandler.java b/src/main/java/com/hx/mybatis/aes/handler/GenericStringHandler.java similarity index 67% rename from src/main/java/com/hx/mybatis/handler/aes/GenericStringHandler.java rename to src/main/java/com/hx/mybatis/aes/handler/GenericStringHandler.java index 39e3fc0..b31fbf1 100644 --- a/src/main/java/com/hx/mybatis/handler/aes/GenericStringHandler.java +++ b/src/main/java/com/hx/mybatis/aes/handler/GenericStringHandler.java @@ -1,6 +1,6 @@ -package com.hx.mybatis.handler.aes; +package com.hx.mybatis.aes.handler; -import com.hx.springbean.VariableAesKey; +import com.hx.mybatis.aes.springbean.VariableAesKey; import com.hx.util.mysql.aes.MysqlHexAes; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; @@ -44,12 +44,28 @@ @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { - return rs.getString(columnIndex); + String data = rs.getString(columnIndex); + if(data != null && data.length()%32==0 && MysqlHexAes.isHexStrValid(data)){ + try{ + data = MysqlHexAes.decryptData(data, VariableAesKey.getAesKey(null),null); + }catch (Exception e){ + //e.printStackTrace(); + } + } + return data; } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { - return cs.getString(columnIndex); + String data = cs.getString(columnIndex); + if(data != null && data.length() < 129 && data.length()%32==0 && MysqlHexAes.isHexStrValid(data)){ + try{ + data = MysqlHexAes.decryptData(data, VariableAesKey.getAesKey(null),null); + }catch (Exception e){ + //e.printStackTrace(); + } + } + return data; } } diff --git a/src/main/java/com/hx/mybatis/aes/springbean/ConstantBean.java b/src/main/java/com/hx/mybatis/aes/springbean/ConstantBean.java new file mode 100644 index 0000000..d64a839 --- /dev/null +++ b/src/main/java/com/hx/mybatis/aes/springbean/ConstantBean.java @@ -0,0 +1,35 @@ +package com.hx.mybatis.aes.springbean; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * 閫氱敤甯搁噺闆嗕腑钀� + * @author CJH + */ +@Component +public class ConstantBean { + + /**鑾峰彇AES绉橀挜鐨勯厤缃紙浠庝粈涔堝寘鑾峰彇鍒帮級*/ + @Value("${mysql.hxe.aes.find.packs:null}") + private String packPath; + /**鍥哄畾AES鐨勭閽�*/ + @Value("${mysql.hxe.aes.fixd.key:null}") + private String fixedAesKey; + + public String getPackPath() { + return packPath; + } + + public void setPackPath(String packPath) { + this.packPath = packPath; + } + + public String getFixedAesKey() { + return fixedAesKey; + } + + public void setFixedAesKey(String fixedAesKey) { + this.fixedAesKey = fixedAesKey; + } +} diff --git a/src/main/java/com/hx/mybatis/aes/springbean/ExportTableAliasVisitor.java b/src/main/java/com/hx/mybatis/aes/springbean/ExportTableAliasVisitor.java new file mode 100644 index 0000000..78d4c32 --- /dev/null +++ b/src/main/java/com/hx/mybatis/aes/springbean/ExportTableAliasVisitor.java @@ -0,0 +1,53 @@ +package com.hx.mybatis.aes.springbean; + +import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; + +import java.util.HashMap; +import java.util.Map; + +/** + * ExportTableAliasVisitor + * @author Mwg + * @date 2020/09/08 23:47 + */ +public class ExportTableAliasVisitor extends SQLASTVisitorAdapter { + + private Map<String,String> tableMap = new HashMap<>(); + + public Map<String, String> getTableMap() { + return tableMap; + } + + public void setTableMap(Map<String, String> tableMap) { + this.tableMap = tableMap; + } + + @Override + public boolean visit(SQLExprTableSource x) { + + //鍒悕锛屽鏋滄湁鍒悕锛屽埆鍚嶄繚鎸佷笉鍙� + //System.out.println("alias:"+x.getAlias());//鍒悕 + //System.out.println("expr:"+x.getExpr());//琛ㄥ悕 + tableMap.put(x.getExpr().toString(),x.getAlias()); + + + //String s = StringUtils.isEmpty(x.getAlias()) ? x.getExpr().toString() : x.getAlias(); + + // 淇敼琛ㄥ悕锛屼笉鍖呭惈鐐规墠鍔� select id from c left join d on c.id = d.id 涓殑c 鍜� d + + /*if(!x.getExpr().toString().contains(".")) { + + x.setExpr("`" + dbName.get() + "`." + x.getExpr()); + + }*/ + //x.setExpr("mymymytable");//淇敼琛ㄥ悕 + //x.setAlias("aa");//淇敼鍒悕 + //x.setAlias(s); + return true; + + } + + + +} \ No newline at end of file diff --git a/src/main/java/com/hx/mybatis/aes/springbean/MySqlInterceptor.java b/src/main/java/com/hx/mybatis/aes/springbean/MySqlInterceptor.java new file mode 100644 index 0000000..67ce671 --- /dev/null +++ b/src/main/java/com/hx/mybatis/aes/springbean/MySqlInterceptor.java @@ -0,0 +1,96 @@ +package com.hx.mybatis.aes.springbean; + +import org.apache.ibatis.executor.statement.StatementHandler; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.ParameterMapping; +import org.apache.ibatis.mapping.SqlCommandType; +import org.apache.ibatis.plugin.*; +import org.apache.ibatis.reflection.DefaultReflectorFactory; +import org.apache.ibatis.reflection.MetaObject; +import org.apache.ibatis.reflection.SystemMetaObject; +import org.apache.ibatis.session.Configuration; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Field; +import java.sql.Connection; +import java.util.List; +import java.util.Properties; + + +@Component +@Intercepts({ + @Signature( + type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class + }) +}) +public class MySqlInterceptor implements Interceptor { + @Override + public Object intercept(Invocation invocation) throws Throwable { + + // 鏂规硶涓� + StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); + MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory()); + //鍏堟嫤鎴埌RoutingStatementHandler锛岄噷闈㈡湁涓猄tatementHandler绫诲瀷鐨刣elegate鍙橀噺锛屽叾瀹炵幇绫绘槸BaseStatementHandler锛岀劧鍚庡氨鍒癇aseStatementHandler鐨勬垚鍛樺彉閲弇appedStatement + MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement"); + //id涓烘墽琛岀殑mapper鏂规硶鐨勫叏璺緞鍚嶏紝濡俢om.uv.dao.UserMapper.insertUser + //String id = mappedStatement.getId(); + //sql璇彞绫诲瀷 select銆乨elete銆乮nsert銆乽pdate + SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); + BoundSql boundSql = statementHandler.getBoundSql(); + + // 鑾峰彇鑺傜偣鐨勯厤缃� + Configuration configuration = mappedStatement.getConfiguration(); + // 鑾峰彇鍙傛暟 + Object parameterObject = boundSql.getParameterObject(); + // MetaObject涓昏鏄皝瑁呬簡originalObject瀵硅薄锛屾彁渚涗簡get鍜宻et鐨勬柟娉曠敤浜庤幏鍙栧拰璁剧疆originalObject鐨勫睘鎬у��,涓昏鏀寔瀵笿avaBean銆丆ollection銆丮ap涓夌绫诲瀷瀵硅薄鐨勬搷浣� + // MetaObject metaObject1 = configuration.newMetaObject(parameterObject); + //鑾峰彇sql涓棶鍙风殑鍩烘湰淇℃伅 + List<ParameterMapping> parameterMappings = boundSql + .getParameterMappings(); + + /*for (ParameterMapping parameterMapping : parameterMappings) { + String propertyName = parameterMapping.getProperty(); + System.out.println("propertyName锛�"+ propertyName); + System.out.println("parameterObject锛�"+ parameterObject); + }*/ + + //杩欓噷鍙互杩涜sql淇敼 + //鑾峰彇鍒板師濮媠ql璇彞 + String sql = boundSql.getSql(); + + //鏂板 + if(sqlCommandType == SqlCommandType.INSERT){ + sql = SqlUtils.insertSql(sql, VariableAesKey.aesKeysTable); + }else if(sqlCommandType == SqlCommandType.UPDATE){ + sql = SqlUtils.updateSql(sql, VariableAesKey.aesKeysTable); + }else if(sqlCommandType == SqlCommandType.SELECT){ + if(VariableAesKey.isRun == 1){ + sql = SqlUtils.selectSql(sql, VariableAesKey.aesKeysTable); + } + }else if(sqlCommandType == SqlCommandType.DELETE){ + sql = SqlUtils.deleteSql(sql, VariableAesKey.aesKeysTable); + } + //閫氳繃鍙嶅皠淇敼sql璇彞 + Field field = boundSql.getClass().getDeclaredField("sql"); + field.setAccessible(true); + field.set(boundSql, sql); + return invocation.proceed(); + + } + + @Override + public Object plugin(Object target) { + if (target instanceof StatementHandler) { + return Plugin.wrap(target, this); + } else { + return target; + } + + } + + @Override + public void setProperties(Properties properties) { + + } +} \ No newline at end of file diff --git a/src/main/java/com/hx/mybatis/aes/springbean/SqlUtils.java b/src/main/java/com/hx/mybatis/aes/springbean/SqlUtils.java new file mode 100644 index 0000000..a2ad79e --- /dev/null +++ b/src/main/java/com/hx/mybatis/aes/springbean/SqlUtils.java @@ -0,0 +1,481 @@ +package com.hx.mybatis.aes.springbean; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.ast.expr.SQLInListExpr; +import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.util.JdbcConstants; +import com.alibaba.druid.util.JdbcUtils; +import com.hx.util.StringUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * sql璇彞澶勭悊宸ュ叿 + * @author CJH 2022-01-12 + */ +public class SqlUtils { + + /**鏌ヨ鍔犲瘑鏁版嵁澶勭悊锛屽彧瀵规煡璇㈠仛澶勭悊锛宻elect杩斿洖涓嶅仛澶勭悊 + * @param sql sql璇彞 + * @param aesKeysTable aes绉橀挜 + * @return + */ + public static String selectSql(String sql,Map<String,Map<String,String>> aesKeysTable){ + + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLSelectStatement sqlStatement = (SQLSelectStatement) parser.parseSelect(); + //鑾峰彇鏍煎紡鍖栫殑slq璇彞 + sql = sqlStatement.toString(); + + //瑙f瀽select鏌ヨ + //SQLSelect sqlSelect = sqlStatement.getSelect() + //鑾峰彇sql鏌ヨ鍧� + SQLSelectQueryBlock sqlSelectQuery = (SQLSelectQueryBlock)sqlStatement.getSelect().getQuery() ; + StringBuffer out = new StringBuffer() ; + //鍒涘缓sql瑙f瀽鐨勬爣鍑嗗寲杈撳嚭 + SQLASTOutputVisitor sqlastOutputVisitor = SQLUtils.createFormatOutputVisitor(out , null , JdbcUtils.MYSQL) ; + + //鑾峰彇琛ㄥ拰鍒悕 + ExportTableAliasVisitor visitorTable = new ExportTableAliasVisitor(); + sqlStatement.accept(visitorTable); + Map<String,String> tableMaps = visitorTable.getTableMap(); + + //鑾峰彇鎵�鏈夌殑瀛楁 + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + sqlStatement.accept(visitor); + //閬嶅巻鎵�鏈夊瓧娈� + Collection<TableStat.Column> columns= visitor.getColumns(); + + StringBuilder sqlWhere = new StringBuilder(); + + StringBuilder sqlSelect = new StringBuilder(); + String expr = null; + sqlSelect.append("SELECT "); + //瑙f瀽select杩斿洖鐨勬暟鎹瓧娈甸」 + for (SQLSelectItem sqlSelectItem : sqlSelectQuery.getSelectList()) { + if(sqlSelect.length() > 7){ + sqlSelect.append(","); + } + expr = sqlSelectItem.getExpr().toString(); + if(expr.indexOf("SELECT") == -1){ + sqlSelect.append(expr); + if(!StringUtils.isEmpty(sqlSelectItem.getAlias())){ + sqlSelect.append(" AS "+sqlSelectItem.getAlias()); + } + }else{ + sqlSelect.append("("); + sqlSelect.append(selectSqlHandle(expr,aesKeysTable,tableMaps,columns)); + sqlSelect.append(")"); + if(!StringUtils.isEmpty(sqlSelectItem.getAlias())){ + sqlSelect.append(" AS "+sqlSelectItem.getAlias()); + } + } + } + + //瑙f瀽from + out.delete(0, out.length()) ; + sqlSelectQuery.getFrom().accept(sqlastOutputVisitor) ; + sqlWhere.append(" FROM "+out); + + //瑙f瀽where + out.delete(0, out.length()) ; + sqlSelectQuery.getWhere().accept(sqlastOutputVisitor) ; + sqlWhere.append(" WHERE "+out+" "); + + if(sqlSelectQuery.getGroupBy() != null){ + out.delete(0, out.length()) ; + sqlSelectQuery.getGroupBy().accept(sqlastOutputVisitor) ; + sqlWhere.append(" "+out); + } + if(sqlSelectQuery.getOrderBy() != null){ + out.delete(0, out.length()) ; + sqlSelectQuery.getOrderBy().accept(sqlastOutputVisitor) ; + sqlWhere.append(" "+out); + } + if(sqlSelectQuery.getLimit() != null){ + out.delete(0, out.length()) ; + sqlSelectQuery.getLimit().accept(sqlastOutputVisitor) ; + sqlWhere.append(" "+out); + } + + //澶勭悊where闇�瑕佸姞瀵嗗緱瀛楁 + sql = sqlWhere.toString(); + if(!StringUtils.isEmpty(sql)){ + Map<String,String> aesKeys = null; + String aeskey = null; + //鎶婂墿涓嬬殑鎷兼帴涓婃潵 + String tableAl = null; + for(TableStat.Column column:columns){ + aesKeys= aesKeysTable.get(column.getTable()); + if(aesKeys == null){ + continue; + } + aeskey = aesKeys.getOrDefault(column.getName(),null); + if(StringUtils.isEmpty(aeskey)){ + continue; + } + tableAl = tableMaps.get(column.getTable()); + if(!StringUtils.isEmpty(tableAl)){ + tableAl = tableAl+"."+column.getName(); + }else{ + tableAl = column.getName(); + } + sql = sql.replaceAll("( |\\n|\\()"+tableAl+"( |\\n|\\))"," AES_DECRYPT(UNHEX("+tableAl+"),'"+aeskey+"') "); + } + } + return sqlSelect.toString()+sql; + } + + public static String selectSqlHandle(String sql,Map<String,Map<String,String>> aesKeysTable + ,Map<String,String> tableMaps,Collection<TableStat.Column> columns){ + + + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLSelectStatement sqlStatement = (SQLSelectStatement) parser.parseSelect(); + //鑾峰彇鏍煎紡鍖栫殑slq璇彞 + sql = sqlStatement.toString(); + + //瑙f瀽select鏌ヨ + //SQLSelect sqlSelect = sqlStatement.getSelect() ; + //鑾峰彇sql鏌ヨ鍧� + SQLSelectQueryBlock sqlSelectQuery = (SQLSelectQueryBlock)sqlStatement.getSelect().getQuery() ; + StringBuffer out = new StringBuffer() ; + //鍒涘缓sql瑙f瀽鐨勬爣鍑嗗寲杈撳嚭 + SQLASTOutputVisitor sqlastOutputVisitor = SQLUtils.createFormatOutputVisitor(out , null , JdbcUtils.MYSQL) ; + + StringBuilder sqlWhere = new StringBuilder(); + + StringBuilder sqlSelect = new StringBuilder(); + String expr = null; + sqlSelect.append("SELECT "); + //瑙f瀽select杩斿洖鐨勬暟鎹瓧娈甸」 + for (SQLSelectItem sqlSelectItem : sqlSelectQuery.getSelectList()) { + if(sqlSelect.length() > 7){ + sqlSelect.append(","); + } + expr = sqlSelectItem.getExpr().toString(); + if(expr.indexOf("SELECT") == -1){ + sqlSelect.append(expr); + if(!StringUtils.isEmpty(sqlSelectItem.getAlias())){ + sqlSelect.append(" AS "+sqlSelectItem.getAlias()); + } + }else{ + sqlSelect.append("("); + selectSqlHandle(expr,aesKeysTable,tableMaps,columns); + sqlSelect.append(")"); + if(!StringUtils.isEmpty(sqlSelectItem.getAlias())){ + sqlSelect.append(" AS "+sqlSelectItem.getAlias()); + } + } + } + + //瑙f瀽from + out.delete(0, out.length()) ; + sqlSelectQuery.getFrom().accept(sqlastOutputVisitor) ; + sqlWhere.append(" FROM "+out); + + //瑙f瀽where + out.delete(0, out.length()) ; + sqlSelectQuery.getWhere().accept(sqlastOutputVisitor) ; + sqlWhere.append(" WHERE "+out+" "); + + if(sqlSelectQuery.getGroupBy() != null){ + out.delete(0, out.length()) ; + sqlSelectQuery.getGroupBy().accept(sqlastOutputVisitor) ; + sqlWhere.append(" "+out); + } + if(sqlSelectQuery.getOrderBy() != null){ + out.delete(0, out.length()) ; + sqlSelectQuery.getOrderBy().accept(sqlastOutputVisitor) ; + sqlWhere.append(" "+out); + } + if(sqlSelectQuery.getLimit() != null){ + out.delete(0, out.length()) ; + sqlSelectQuery.getLimit().accept(sqlastOutputVisitor) ; + sqlWhere.append(" "+out); + } + + sql = sqlWhere.toString(); + if(!StringUtils.isEmpty(sql)){ + Map<String,String> aesKeys = null; + String aeskey = null; + //鎶婂墿涓嬬殑鎷兼帴涓婃潵 + String tableAl = null; + + for(TableStat.Column column:columns){ + aesKeys= aesKeysTable.get(column.getTable()); + if(aesKeys == null){ + continue; + } + aeskey = aesKeys.getOrDefault(column.getName(),null); + if(StringUtils.isEmpty(aeskey)){ + continue; + } + tableAl = tableMaps.get(column.getTable()); + if(!StringUtils.isEmpty(tableAl)){ + tableAl = tableAl+"."+column.getName(); + }else{ + tableAl = column.getName(); + } + sql = sql.replaceAll("( |\\n|\\()"+tableAl+"( |\\n|\\))"," AES_DECRYPT(UNHEX("+tableAl+"),'"+aeskey+"') "); + } + } + return sqlSelect.toString()+sql; + } + + /**鏂板鍔犲瘑鏁版嵁澶勭悊 + * @param sql sql璇彞 + * @param aesKeysTable aes绉橀挜 + * @return + */ + public static String insertSql(String sql,Map<String,Map<String,String>> aesKeysTable){ + //瑁呰浇閲嶅啓鐨剆ql璇彞 + StringBuilder splicingSql = new StringBuilder(); + + sql = SQLUtils.format(sql, JdbcConstants.MYSQL); + String[] datas = sql.split("VALUES",2); + + splicingSql.append(datas[0]+"VALUES "); + + //閲嶆柊鎷兼帴SQL璇彞 + + //瑙f瀽sql璇彞 + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement statement = parser.parseStatement(); + MySqlInsertStatement insert = (MySqlInsertStatement)statement; + + String insertName = insert.getTableName().getSimpleName(); + + //鏍规嵁琛ㄥ悕绉拌幏鍙栧埌AES绉橀挜 + Map<String,String> aesKeys= aesKeysTable.get(insertName); + if(aesKeys == null){ + return sql; + } + + //鑾峰彇鎵�鏈夌殑瀛楁 + List<SQLExpr> columns = insert.getColumns(); + + String fildValue = null; + String aeskey = null; + //閬嶅巻鍊� + List<SQLInsertStatement.ValuesClause> vcl = insert.getValuesList(); + for(int j = 0; j<vcl.size(); j++){ + if( j != 0){ + splicingSql.append(","); + } + for(int i = 0;i < columns.size();i++){ + //鏌ヨ鏀瑰瓧娈垫槸鍚﹂渶瑕佸姞瀵� + aeskey = aesKeys.getOrDefault(columns.get(i).toString(),null); + fildValue = vcl.get(j).getValues().get(i).toString(); + if(i == 0){ + splicingSql.append("("); + if(aeskey != null && fildValue.indexOf("AES_ENCRYPT") == -1){ + splicingSql.append("HEX(AES_ENCRYPT("+fildValue+",'"+aeskey+"'))"); + }else{ + splicingSql.append(fildValue); + } + }else if(i == columns.size()-1){ + splicingSql.append(","); + if(aeskey != null && fildValue.indexOf("AES_ENCRYPT") == -1){ + splicingSql.append("HEX(AES_ENCRYPT("+fildValue+",'"+aeskey+"'))"); + }else{ + splicingSql.append(fildValue); + } + splicingSql.append(")"); + }else{ + splicingSql.append(","); + if(aeskey != null && fildValue.indexOf("AES_ENCRYPT") == -1){ + splicingSql.append("HEX(AES_ENCRYPT("+fildValue+",'"+aeskey+"'))"); + }else{ + splicingSql.append(fildValue); + } + } + } + } + return splicingSql.toString(); + } + + /**鏇存柊鍔犲瘑鏁版嵁澶勭悊 + * @param sql sql璇彞 + * @param aesKeysTable aes绉橀挜 + * @return + */ + public static String updateSql(String sql,Map<String,Map<String,String>> aesKeysTable){ + //瑁呰浇閲嶅啓鐨剆ql璇彞 + StringBuilder splicingSql = new StringBuilder(); + + //sql = SQLUtils.format(sql, JdbcConstants.MYSQL); + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement sqlStatement = parser.parseStatement(); + //鑾峰彇鏍煎紡鍖栫殑slq璇彞 + sql = sqlStatement.toString(); + + + MySqlUpdateStatement updateStatement = (MySqlUpdateStatement)sqlStatement; + + String insertName = updateStatement.getTableName().getSimpleName(); + + String[] datas = sql.split("WHERE",2); + + Map<String,String> aesKeys = aesKeysTable.get(insertName); + + splicingSql.append("UPDATE "+insertName+" SET "); + + String aeskey = null; + String fildValue = null; + List<SQLUpdateSetItem> items = updateStatement.getItems(); + for(int i = 0;i<items.size();i++){ + if(i != 0){ + splicingSql.append(","); + } + + SQLUpdateSetItem item = items.get(i); + + //鏌ヨ鏀瑰瓧娈垫槸鍚﹂渶瑕佸姞瀵� + aeskey = aesKeys.getOrDefault(item.getColumn().toString(),null); + + fildValue = item.getValue().toString(); + if(aeskey != null && fildValue.indexOf("AES_ENCRYPT") == -1){ + splicingSql.append(item.getColumn()+" = HEX(AES_ENCRYPT("+fildValue+",'"+aeskey+"'))"); + }else{ + splicingSql.append(item.getColumn()+" = "+fildValue); + } + } + + String sqlWhere = " WHERE"; + //鎶婂墿涓嬬殑鎷兼帴涓婃潵 + if(datas.length > 1){ + for(int i =1;i<datas.length;i++){ + sqlWhere = sqlWhere+datas[i]; + } + + parser = new MySqlStatementParser("SELECT * FROM "+insertName+" "+sqlWhere); + sqlStatement = parser.parseStatement(); + + ExportTableAliasVisitor visitorTable = new ExportTableAliasVisitor(); + sqlStatement.accept(visitorTable); + + //鑾峰彇琛ㄥ拰鍒悕 + Map<String,String> tableMaps = visitorTable.getTableMap(); + tableMaps.put(insertName,null); + + //鑾峰彇鎵�鏈夌殑瀛楁 + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + sqlStatement.accept(visitor); + + String tableAl = null; + //閬嶅巻鎵�鏈夊瓧娈� + Collection<TableStat.Column> columns= visitor.getColumns(); + for(TableStat.Column column:columns){ + + aesKeys= aesKeysTable.get(column.getTable()); + if(aesKeys == null){ + continue; + } + aeskey = aesKeys.getOrDefault(column.getName(),null); + if(StringUtils.isEmpty(aeskey)){ + continue; + } + tableAl = tableMaps.get(column.getTable()); + if(!StringUtils.isEmpty(tableAl)){ + tableAl = tableAl+"."+column.getName(); + }else{ + tableAl = column.getName(); + } + sqlWhere = sqlWhere.replaceAll("( |\\n|\\()"+tableAl+"( |\\n|\\))"," AES_DECRYPT(UNHEX("+tableAl+"),'"+aeskey+"') "); + } + + } + splicingSql.append(sqlWhere.toString()); + return splicingSql.toString(); + } + + /**鍒犻櫎鍔犲瘑鏁版嵁澶勭悊 + * @param sql sql璇彞 + * @param aesKeysTable aes绉橀挜 + * @return + */ + public static String deleteSql(String sql,Map<String,Map<String,String>> aesKeysTable){ + //瑁呰浇閲嶅啓鐨剆ql璇彞 + StringBuilder splicingSql = new StringBuilder(); + + //sql = SQLUtils.format(sql, JdbcConstants.MYSQL); + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement sqlStatement = parser.parseStatement(); + //鑾峰彇鏍煎紡鍖栫殑slq璇彞 + sql = sqlStatement.toString(); + + MySqlDeleteStatement deleteStatement = (MySqlDeleteStatement)sqlStatement; + + String insertName = deleteStatement.getTableName().getSimpleName(); + + String[] datas = sql.split("WHERE",2); + + Map<String,String> aesKeys = aesKeysTable.get(insertName); + + splicingSql.append("DELETE FROM "+insertName); + + String aeskey = null; + + String sqlWhere = " WHERE"; + //鎶婂墿涓嬬殑鎷兼帴涓婃潵 + if(datas.length > 1){ + for(int i =1;i<datas.length;i++){ + sqlWhere = sqlWhere+datas[i]; + } + + parser = new MySqlStatementParser("SELECT * FROM "+insertName+" "+sqlWhere); + sqlStatement = parser.parseStatement(); + + ExportTableAliasVisitor visitorTable = new ExportTableAliasVisitor(); + sqlStatement.accept(visitorTable); + + //鑾峰彇琛ㄥ拰鍒悕 + Map<String,String> tableMaps = visitorTable.getTableMap(); + tableMaps.put(insertName,null); + + //鑾峰彇鎵�鏈夌殑瀛楁 + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + sqlStatement.accept(visitor); + + String tableAl = null; + //閬嶅巻鎵�鏈夊瓧娈� + Collection<TableStat.Column> columns= visitor.getColumns(); + for(TableStat.Column column:columns){ + + aesKeys= aesKeysTable.get(column.getTable()); + if(aesKeys == null){ + continue; + } + aeskey = aesKeys.getOrDefault(column.getName(),null); + if(StringUtils.isEmpty(aeskey)){ + continue; + } + tableAl = tableMaps.get(column.getTable()); + if(!StringUtils.isEmpty(tableAl)){ + tableAl = tableAl+"."+column.getName(); + }else{ + tableAl = column.getName(); + } + sqlWhere = sqlWhere.replaceAll("( |\\n|\\()"+tableAl+"( |\\n|\\))"," AES_DECRYPT(UNHEX("+tableAl+"),'"+aeskey+"') "); + } + + } + splicingSql.append(sqlWhere.toString()); + return splicingSql.toString(); + } + +} diff --git a/src/main/java/com/hx/springbean/VariableAesKey.java b/src/main/java/com/hx/mybatis/aes/springbean/VariableAesKey.java similarity index 60% rename from src/main/java/com/hx/springbean/VariableAesKey.java rename to src/main/java/com/hx/mybatis/aes/springbean/VariableAesKey.java index f9168c0..835cb5e 100644 --- a/src/main/java/com/hx/springbean/VariableAesKey.java +++ b/src/main/java/com/hx/mybatis/aes/springbean/VariableAesKey.java @@ -1,8 +1,8 @@ -package com.hx.springbean; +package com.hx.mybatis.aes.springbean; +import com.gitee.sunchenbin.mybatis.actable.annotation.Table; import com.hx.common.annotations.MysqlHexAes; import com.hx.util.StringUtils; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @@ -24,8 +24,16 @@ @Resource private ConstantBean constantBean; - /**瀛樺偍AES鐨勭閽�*/ + /**鏄惁宸茬粡鍚姩瀹�*/ + public static int isRun = 0; + + /**瀛樺偍鎵�鏈堿ES鐨勭閽�*/ public static Map<String,String> aesKeys = new HashMap<>(); + /**鏍规嵁琛ㄦ槑鏉ュ瓨鍌ˋES绉橀挜*/ + public static Map<String,Map<String,String>> aesKeysTable = new HashMap<>(); + + /**鍥哄畾鐨刟es绉橀挜*/ + public static String AES_KEY = null; /**瀛樺偍AES绉橀挜*/ public static void setAesKey(String aesKeyFild,String aesKey){ @@ -33,7 +41,14 @@ } /**鑾峰彇AES绉橀挜*/ public static String getAesKey(String aesKeyFild){ - return aesKeys.get(aesKeyFild); + if(aesKeyFild == null){ + return AES_KEY; + } + if(StringUtils.isEmpty(aesKeys.get(aesKeyFild))){ + return AES_KEY; + }else { + return aesKeys.get(aesKeyFild); + } } /** @@ -41,11 +56,29 @@ */ @PostConstruct public void VariableAesKey(){ + + isRun = 1; //椤圭洰鍚姩鐨勬椂鍊欏~鍏� System.err.println("鎵弿鑾峰彇AES:" + constantBean.getPackPath()); + AES_KEY = constantBean.getFixedAesKey(); if(StringUtils.noNull(constantBean.getPackPath())){ Set<Class<?>> classes = classData(constantBean.getPackPath()); + + Map<String,String> aesKeysFild = new HashMap<>(); + boolean isAes = false; + String tableName = null; + for(Class<?> cl:classes){ + //琛ㄥ悕绉� + Table table = cl.getAnnotation(Table.class); + if(table == null){ + continue; + } + tableName = table.name(); + + aesKeysFild = new HashMap<>(); + isAes = false; + // 鍙栧緱鏈被鐨勫叏閮ㄥ睘鎬� Field[] fields = cl.getDeclaredFields(); fields = getPatentFields(fields,cl); @@ -56,32 +89,31 @@ // 鏍规嵁娉ㄨВ绫诲瀷杩斿洖鏂规硶鐨勬寚瀹氱被鍨嬫敞瑙� MysqlHexAes mysqlHexAes = field.getAnnotation(MysqlHexAes.class); - String aesKeyField = mysqlHexAes.aesKeyField(); + //String aesKeyField = mysqlHexAes.aesKeyField(); String aesKey = mysqlHexAes.aesKey(); if(StringUtils.isEmpty(aesKey)){ - throw new RuntimeException("mysql鐨凙ES绉橀挜涓嶈兘涓虹┖:"+field.getName()); - } - if(StringUtils.noNull(aesKeyField)){ - String key = aesKeys.get(aesKeyField); - if(StringUtils.isEmpty(key)){ - aesKeys.put(aesKeyField,aesKey); - }else{ - if(!aesKey.equals(key)){ - throw new RuntimeException("瀛楁/瀹氫箟鐨凙ES绉橀挜瀛楁銆�"+field.getName()+"銆戝涓竴鏍凤紝浣嗘槸AES绉橀挜涓嶄竴鏍�"); - } + aesKey = constantBean.getFixedAesKey(); + if(StringUtils.isEmpty(aesKey)){ + throw new RuntimeException("mysql鐨凙ES绉橀挜涓嶈兘涓虹┖:"+field.getName()); } + } + String key = aesKeys.get(field.getName()); + if(StringUtils.isEmpty(key)){ + aesKeys.put(field.getName(),aesKey); + aesKeysFild.put(field.getName(),aesKey); + isAes = true; }else{ - String key = aesKeys.get(field.getName()); - if(StringUtils.isEmpty(key)){ - aesKeys.put(field.getName(),aesKey); - }else{ - if(!aesKey.equals(key)){ - throw new RuntimeException("瀛楁/瀹氫箟鐨凙ES绉橀挜瀛楁銆�"+field.getName()+"銆戝涓竴鏍凤紝浣嗘槸AES绉橀挜涓嶄竴鏍�"); - } + isAes = true; + aesKeysFild.put(field.getName(),aesKey); + if(!aesKey.equals(key)){ + throw new RuntimeException("瀛楁/瀹氫箟鐨凙ES绉橀挜瀛楁銆�"+field.getName()+"銆戝涓竴鏍凤紝浣嗘槸AES绉橀挜涓嶄竴鏍�"); } } } + } + if(isAes){ + aesKeysTable.put(tableName,aesKeysFild); } } } @@ -90,31 +122,35 @@ /**鑾峰彇鍖呬笅闈㈢殑鎵�鏈夋枃浠�*/ public static Set<Class<?>> classData(String packPath){ Set<Class<?>> classes = new LinkedHashSet<Class<?>>(); - // 鏄惁寰幆杩唬 - boolean recursive = true; - // 鑾峰彇鍖呯殑鍚嶅瓧 骞惰繘琛屾浛鎹� - String packageName = packPath; - String packageDirName = packageName.replace('.', '/'); - // 瀹氫箟涓�涓灇涓剧殑闆嗗悎 骞惰繘琛屽惊鐜潵澶勭悊杩欎釜鐩綍涓嬬殑things - Enumeration<URL> dirs; - try{ - dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); - // 寰幆杩唬涓嬪幓 - while (dirs.hasMoreElements()){ - // 鑾峰彇涓嬩竴涓厓绱� - URL url = dirs.nextElement(); - // 寰楀埌鍗忚鐨勫悕绉� - String protocol = url.getProtocol(); - // 濡傛灉鏄互鏂囦欢鐨勫舰寮忎繚瀛樺湪鏈嶅姟鍣ㄤ笂 - if ("file".equals(protocol)) { - // 鑾峰彇鍖呯殑鐗╃悊璺緞 - String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); - // 浠ユ枃浠剁殑鏂瑰紡鎵弿鏁翠釜鍖呬笅鐨勬枃浠� 骞舵坊鍔犲埌闆嗗悎涓� - findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); + + //鎴彇 + String[] packPaths = packPath.split(";|,"); + for( String packageName : packPaths){ + // 鏄惁寰幆杩唬 + boolean recursive = true; + // 鑾峰彇鍖呯殑鍚嶅瓧 骞惰繘琛屾浛鎹� + String packageDirName = packageName.replace('.', '/'); + // 瀹氫箟涓�涓灇涓剧殑闆嗗悎 骞惰繘琛屽惊鐜潵澶勭悊杩欎釜鐩綍涓嬬殑things + Enumeration<URL> dirs; + try{ + dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName); + // 寰幆杩唬涓嬪幓 + while (dirs.hasMoreElements()){ + // 鑾峰彇涓嬩竴涓厓绱� + URL url = dirs.nextElement(); + // 寰楀埌鍗忚鐨勫悕绉� + String protocol = url.getProtocol(); + // 濡傛灉鏄互鏂囦欢鐨勫舰寮忎繚瀛樺湪鏈嶅姟鍣ㄤ笂 + if ("file".equals(protocol)) { + // 鑾峰彇鍖呯殑鐗╃悊璺緞 + String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); + // 浠ユ枃浠剁殑鏂瑰紡鎵弿鏁翠釜鍖呬笅鐨勬枃浠� 骞舵坊鍔犲埌闆嗗悎涓� + findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes); + } } + }catch (IOException e){ + e.printStackTrace(); } - }catch (IOException e){ - e.printStackTrace(); } return classes; } diff --git a/src/main/java/com/hx/springbean/ConstantBean.java b/src/main/java/com/hx/springbean/ConstantBean.java deleted file mode 100644 index e36d5cd..0000000 --- a/src/main/java/com/hx/springbean/ConstantBean.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.hx.springbean; - -import com.hx.common.annotations.MysqlHexAes; -import com.hx.util.StringUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.URL; -import java.net.URLDecoder; -import java.util.*; - -/** - * 閫氱敤甯搁噺闆嗕腑钀� - * @author CJH - */ -@Component -public class ConstantBean { - - /**鑾峰彇AES绉橀挜鐨勯厤缃紙浠庝粈涔堝寘鑾峰彇鍒帮級*/ - @Value("${mysql.hxe.aex.find.packs:null}") - private String packPath; - - public String getPackPath() { - return packPath; - } - - public void setPackPath(String packPath) { - this.packPath = packPath; - } -} -- Gitblit v1.8.0