一、新建注解
@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 ""; }
二、建立切面
@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"));
}
}
三、注解使用
@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); } }
