1、新建註解數據庫
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface HandleField { //方法參數加密字段(順序與方法參數順序一致;字段類型爲string) public String[] encrypFieldNameInfo(); //解密方法返回值字段(支持 map的key domain 和list<domain>) 字段類型爲string public String decrypResultFieldName() default ""; }
2、創建切面app
@Component("changeIdNoAopHandler") public class ChangeIdNoAopHandler { private static Logger logger = LoggerFactory.getLogger(ChangeIdNoAopHandler.class); private static final String SECRET_KEY = "12345678"; //祕鑰 private String HANDLE_FIELD_NAME = "idNo"; //加密解密字段 private static final String ENCRYPT_FLAG = "encrypt"; //加密標識 (判斷對值進行加密或者解密的操做) private static final String DECRYPT_FLAG = "decrypt"; //解密標識(判斷對值進行加密或者解密的操做) @Autowired private InetxValDualService netxValDualService; @Autowired private IThemisCryptoIdnoService themisCryptoIdnoService; /*** * * @Description(功能描述) : 切面方法 (修改目標方法參數中帶有 idNo字段的值;修改目標方法返回值帶有idNo的字段) * @author(做者) : * @date (開發日期) : 2017-9-13 下午5:30:24 * @exception : * @param joinPoint * @return * @throws Throwable Object */ public Object parameterCheck(ProceedingJoinPoint joinPoint) throws Throwable{ logger.info("開始執行aop方法修改參數。。。"); Object target = joinPoint.getTarget();//返回被織入加強處理的目標對象 getThis:返回AOP框架爲目標對象生成的代理對象 Object[] args = joinPoint.getArgs(); //獲取目標對象方法參數 //遍歷參數 修改帶有idNo字段對象的值 (map list<domain> domain) for (Object _obj : args) { try{ changValue(_obj,ENCRYPT_FLAG); //加密參數 }catch (Exception e) { //使用異常機制來驗證 _obj中 是否有idNo 字段 logger.error("修改目標方法參數字段值異常。目標類:" +target.getClass()+"方法:"+joinPoint.getSignature().getName()+"修改的值:"+_obj,e); } } //執行方法,以新的參數(若是不帶args就是用原先的參數;這裏帶不帶均可以是,上面方法獲取原先參數的引用作的修改) Object returnValue = joinPoint.proceed(args); //若未設置,則不須要解密 if(!ObjectIsNullUtil.isNullOrEmpty(returnValue)){ try{ //修改 returnValue = changValue(returnValue,DECRYPT_FLAG); //解密參數 }catch (Exception e) { //使用異常機制來驗證 _obj中 是否有idNo 字段 logger.error("修改目標方法返回值異常。目標類:" +target.getClass()+"方法:"+joinPoint.getSignature().getName()+"修改的值:"+returnValue,e); } } return returnValue; } /*** * * @Description(功能描述) : 修改對象idNo字段的值 * @author(做者) : * @date (開發日期) : 2017-9-13 下午5:30:07 * @exception : * @param _obj * @param flag 加密解密字段 * @throws Exception void */ private Object changValue(Object _obj, String flag) throws Exception{ //基本類型不做操做 if(_obj instanceof Map){ changeMapValue(_obj,flag); }else if(_obj instanceof List){ @SuppressWarnings("unchecked") List<Object> list = (List<Object>) _obj; for (Object obj : list) { if(obj instanceof Map){ changeMapValue(_obj,flag); }else{ changObjectValue(_obj,flag); } } }else{ changObjectValue(_obj,flag); } return _obj; } /** * * @Description(功能描述) : 當對象爲Map 修改key的值 * @author(做者) : 吳桂鎮 * @date (開發日期) : 2017-9-14 上午11:17:50 * @exception : * @param _obj * @param flag * @return Object * @throws Exception */ @SuppressWarnings("unchecked") private Object changeMapValue(Object _obj, String flag) throws Exception{ Map<String,Object> map = (Map<String,Object>) _obj; if(map.containsKey(HANDLE_FIELD_NAME)){ Object fieldValue = map.get(HANDLE_FIELD_NAME); String afterValue = crypto(fieldValue, flag); if(!ObjectIsNullUtil.isNullOrEmpty(afterValue)){ map.put(HANDLE_FIELD_NAME, afterValue); } } return _obj; } /*** * * @Description(功能描述) : 修改Object對象field的值 * @author(做者) : * @date (開發日期) : 2017-9-14 上午11:37:07 * @exception : * @param _obj * @param flag * @return * @throws Exception Object */ private Object changObjectValue(Object _obj, String flag) throws Exception{ Class<?> resultClz = _obj.getClass(); Field[] fieldInfo = resultClz.getDeclaredFields(); //獲取class裏的全部字段 父類字段獲取不到 注:若是出現加密解密失敗 請先查看idno是否在父類中 for (Field field : fieldInfo) { if(HANDLE_FIELD_NAME.equals(field.getName())){ field.setAccessible(true); //成員變量爲private,故必須進行此操 Object fieldValue = field.get(_obj); String afterValue = crypto(fieldValue, flag); if(!ObjectIsNullUtil.isNullOrEmpty(afterValue)){ field.set(_obj, afterValue); } break; } } return _obj; } /*** * * @Description(功能描述) : 加密操做 * @author(做者) : * @date (開發日期) : 2017-9-14 下午3:20:32 * @exception : * @param value * @param flag * @return String * @throws Exception */ private String crypto(Object value,String flag) throws Exception{ if(ObjectIsNullUtil.isNullOrEmpty(value)){ return null; } //加密操做;加密以前先去查詢一下數據庫 有沒有 若是沒有 則insert if (ENCRYPT_FLAG.equals(flag)) { String encodeValue = Encryption.encode(SECRET_KEY, value.toString()); //加密 ThemisCryptoIdno idnoDomain = new ThemisCryptoIdno(); idnoDomain.setCryptoIdno(encodeValue); idnoDomain = themisCryptoIdnoService.selectOneByObject(idnoDomain); if(ObjectIsNullUtil.isNullOrEmpty(idnoDomain)){ //若空 則生成 seq 而後入庫 返回seq String tr_date = DateOperation.convertToDateStr2(DateOperation.currentTimeMills()); //獲取有流水號 String inextValDual=netxValDualService.findIdNoSeq(); //組流水:日期+ 7位流水 其餘表儲存的就是這個idnoSeq String idnoSeq=(tr_date+DateOperation.fill(inextValDual, '0', 7, true)).replaceAll("-", ""); idnoDomain = new ThemisCryptoIdno(); idnoDomain.setOptTime(DateOperation.convertToDateStr1(DateOperation.currentTimeMills())); idnoDomain.setCryptoIdno(encodeValue); idnoDomain.setCryptoSeq(idnoSeq); themisCryptoIdnoService.insert(idnoDomain); return idnoSeq; }else{ //不爲空 直接返回seq return idnoDomain.getCryptoSeq(); } }else{ //解密操做 經過seq 查詢 而後解密返回明文 ThemisCryptoIdno idnoDomain = new ThemisCryptoIdno(); idnoDomain.setCryptoSeq(value.toString()); idnoDomain = themisCryptoIdnoService.selectOneByObject(idnoDomain); if(!ObjectIsNullUtil.isNullOrEmpty(idnoDomain)){ return Encryption.decodeValue(SECRET_KEY, idnoDomain.getCryptoIdno()); //解密 } } return null; } public static void main(String[] args) throws Exception { System.out.println(Encryption.encode(SECRET_KEY, "142701197605091275")); } }
3、註解使用框架
@Component public class SusrService implements ISusrService{ @Autowired private SusrDao susrDao; @Override @HandleField(encrypFieldNameInfo={"usrCde"},decrypResultFieldName="usrCde") public sUsr selectOneByObject(sUsr su) { return susrDao.selectOneByObject(su); } }