一,先创建注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IdEncrypt {
/**
* 是否需要对请求参数进行解密
*
* @return
*/
boolean reqHandle();
/**
* 加密的参数位置
*
* @return
*/
int reqEncryptIndex() default 0;
String encryptPath() default "";
/**
* 解密的参数位置
*
* @return
*/
int reqDecryptIndex() default 0;;
boolean isObject() default false;
/**
* 返回结果处理 -(原id置空或置0处理)
*
* @return
*/
String sourcePath();
/**
* 返回结果处理 - 加密后id的路径
*
* @return
*/
String rewritePath();
/**
* 返回结果处理 - 加密后id的名称
*
* @return
*/
//String rewriteParam();
//业务类型:news,course,sms...
BusinsTypeEnum type() ;
/**
* 看返回的data组装数据是list还是map格式的及是否需要加密unencrypt
* @return
*/
ReturnDataTypeEnum dataType();
}
二,创建切面拦截注解,处理自己的业务
@Aspect
@Component
@Slf4j
public class IdEncryptHandlerAspect {
public static final String PASSWORD = "course:xcc:2022";
//文章ID,大于这个ID的文章获取详情时都要进行解密操作
public static final Long newsId = 6937225l;
@Resource
private EncryptBodyConfig config;
@Pointcut("@annotation(com.dtguai.encrypt.annotation.encrypt.IdEncrypt)")
public void pointCut() {
}
/**
* 处理请求参数,转换为解密后的数据并覆盖请求参数
* @param obj 请求参数
* @param idEncryptHandler 注解类
* @return
*/
private Object[] dealRequestParamData(Object[] obj, IdEncrypt idEncryptHandler){
//业务类型
BusinsTypeEnum businsTypeEnum = idEncryptHandler.type();
if(obj[idEncryptHandler.reqEncryptIndex()] instanceof Long ){//加密参数是Long类型
Long encryptedId = (Long) obj[idEncryptHandler.reqEncryptIndex()];
//如果是文章业务,直接用解密后的文章ID覆盖
if(BusinsTypeEnum.NEWS.getType().equals(businsTypeEnum.getType())){
log.info("文章详情接口输入的加密id值为:"+encryptedId);
//String decryptedId = EncryptBodyMethod.DES.getISecurity().decrypt(String.valueOf(encryptedId), PASSWORD, config);
//不是百度seo收录的旧文章,都要解密UUID
if(encryptedId!= 0 && encryptedId < newsId){
obj[idEncryptHandler.reqDecryptIndex()] = encryptedId;
}else{
Long decryptedId = DeAndEnUtil.decrypt(Long.valueOf(String.valueOf(encryptedId)));
obj[idEncryptHandler.reqDecryptIndex()] = Long.valueOf(decryptedId);
}
}else{
//String decryptedId = EncryptBodyMethod.DES.getISecurity().decrypt(String.valueOf(encryptedId), PASSWORD, config);
Long decryptedId = DeAndEnUtil.decrypt(Long.valueOf(String.valueOf(encryptedId)));
//if(obj[idEncryptHandler.reqDecryptIndex()] instanceof Integer){ //如果入参是 Integer 类型
// obj[idEncryptHandler.reqDecryptIndex()] = decryptedId.intValue();
// }else if(obj[idEncryptHandler.reqDecryptIndex()] instanceof Long){ //如果入参是 Long 类型
obj[idEncryptHandler.reqDecryptIndex()] =decryptedId;
//}
}
}else if(obj[idEncryptHandler.reqEncryptIndex()] instanceof Integer){//加密参数是Integer类型
Integer encryptedId = (Integer) obj[idEncryptHandler.reqEncryptIndex()];
//如果是文章业务,直接用解密后的文章ID覆盖
if(BusinsTypeEnum.NEWS.getType().equals(businsTypeEnum.getType())){
log.info("文章详情接口输入的加密id值为:"+encryptedId);
//不是百度seo收录的旧文章,都要解密UUID
if(encryptedId!= 0 && encryptedId < newsId.intValue()){
obj[idEncryptHandler.reqDecryptIndex()] = encryptedId;
}else{
Long decryptedId = DeAndEnUtil.decrypt(encryptedId.longValue());
obj[idEncryptHandler.reqDecryptIndex()] = decryptedId.intValue();
}
}else{
Long decryptedId = DeAndEnUtil.decrypt(encryptedId.longValue());
obj[idEncryptHandler.reqDecryptIndex()] =decryptedId.intValue();
}
}else if(obj[idEncryptHandler.reqEncryptIndex()] instanceof List){//加密参数是List类型
List<Long> ids = new ArrayList<Long>();
//uuid参数集合
List<Long> encryptedIds = (List) obj[idEncryptHandler.reqEncryptIndex()];
//原ID参数集合
List<Long> orginIds = (List) (obj[idEncryptHandler.reqDecryptIndex()]) ;
if (CollectionUtil.isNotEmpty(encryptedIds)) {
for(int i= 0; i< orginIds.size(); i++){
//如果是文章业务,则判断是否是百度seo收录的旧文章访问,小于特定的旧文章,默认都是被百度seo收录
if(BusinsTypeEnum.NEWS.getType().equals(businsTypeEnum.getType())){
//不是百度seo收录的旧文章,都要解密UUID
if(orginIds.get(i) != 0 && orginIds.get(i) < newsId){
ids.add(orginIds.get(i));
}else{
log.info("文章详情接口输入的文章uuid值为:"+orginIds.get(i));
//String decryptedId = EncryptBodyMethod.DES.getISecurity().decrypt(String.valueOf(encryptedIds.get(i)), PASSWORD, config);
Long decryptedId = DeAndEnUtil.decrypt(orginIds.get(i));
ids.add(decryptedId);
}
}else{
// String decryptedId = EncryptBodyMethod.DES.getISecurity().decrypt(String.valueOf(encryptedIds.get(i)), PASSWORD, config);\
Long decryptedId = DeAndEnUtil.decrypt(orginIds.get(i));
ids.add(decryptedId);
}
}
//if(obj[idEncryptHandler.reqDecryptIndex()] instanceof Integer){
// obj[idEncryptHandler.reqDecryptIndex()] = ids.stream().mapToInt(Long::intValue).boxed().collect(Collectors.toList());
// }else if(obj[idEncryptHandler.reqDecryptIndex()] instanceof Long){
obj[idEncryptHandler.reqDecryptIndex()] = ids;
// }
}
}
return obj;
}
@Around("pointCut()")
public Object pointCut(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
// 获取注解Action
IdEncrypt idEncryptHandler = method.getAnnotation(IdEncrypt.class);
Object[] obj = joinPoint.getArgs();
if (idEncryptHandler.isObject()) {
return joinPoint.proceed(obj);
} else {
if (idEncryptHandler.reqHandle() || (obj.length > 0 && Objects.isNull(obj[idEncryptHandler.reqDecryptIndex()]))) {
//对请求参数解密处理
obj = dealRequestParamData(obj,idEncryptHandler);
}
Object returnObject = joinPoint.proceed(obj);
String jsonString = new ObjectMapper().writeValueAsString(returnObject);
//String jsonString = JSONObject.toJSONString(returnObject,SerializerFeature.WriteDateUseDateFormat);
ReturnDataTypeEnum returnDataTypeEnum = idEncryptHandler.dataType();
//判断返回数据类型
if(ReturnDataTypeEnum.MAP.getType().equals(returnDataTypeEnum.getType())){
if(!jsonString.contains("data")){
return returnObject;
}
Map contentJson = JsonPath.parse(jsonString).read("data");
//如果返回数据为空,不做处理
if(CollectionUtil.isEmpty(contentJson)){
return returnObject;
}
}else if(ReturnDataTypeEnum.LIST.getType().equals(returnDataTypeEnum.getType())){
List contentJson = JsonPath.parse(jsonString).read("data");
//如果返回数据为空,不做处理
if(CollectionUtil.isEmpty(contentJson)){
return returnObject;
}
}else if(ReturnDataTypeEnum.UNENCRYPT.getType().equals(returnDataTypeEnum.getType())){
//返回数据无需处理
return returnObject;
}else if(ReturnDataTypeEnum.DIRECT_LIST.getType().equals(returnDataTypeEnum.getType())){
if("[]".equals(jsonString)){//数据为空,直接返回
return returnObject;
}
}
//对返回数据的文章uuid加密处理
if (idEncryptHandler.rewritePath().contains("*")) {
List<Integer> srcIds = JsonPath.parse(jsonString).read(idEncryptHandler.sourcePath());
LinkedList newIds = new LinkedList();
for (Integer id : srcIds) {
//String nid = EncryptBodyMethod.DES.getISecurity().encrypt(String.valueOf(id), PASSWORD, config);
Long nid = DeAndEnUtil.encrypt(Long.valueOf(String.valueOf(id)));
newIds.add(nid);
}
String returnJsonString = jsonString;
for (int i = 0; i < newIds.size(); i++) {
String accuteRewritePath = idEncryptHandler.rewritePath().replace("*", String.valueOf(i));
String rewritePath = accuteRewritePath + ".id";
// returnJsonString = JsonPath.parse(returnJsonString).set(rewritePath, 0).put(accuteRewritePath, idEncryptHandler.rewriteParam(), newIds.get(i)).jsonString();
returnJsonString = JsonPath.parse(returnJsonString).set(rewritePath, newIds.get(i)).jsonString();
}
returnObject = JSONObject.parseObject(returnJsonString, returnObject.getClass());
} else {
Integer id = (Integer) JsonPath.parse(jsonString).read(idEncryptHandler.sourcePath());
//String returnJsonString = JsonPath.parse(jsonString).set(idEncryptHandler.rewritePath() + ".id", 0).put(idEncryptHandler.rewritePath(), idEncryptHandler.rewriteParam(), EncryptBodyMethod.DES.getISecurity().encrypt(String.valueOf(id), PASSWORD, config)).jsonString();
String returnJsonString = JsonPath.parse(jsonString).set(idEncryptHandler.rewritePath() + ".id", DeAndEnUtil.encrypt(Long.valueOf(String.valueOf(id)))).jsonString();
returnObject = JSONObject.parseObject(returnJsonString, returnObject.getClass());
}
return returnObject;
}
}
private Map<String, Object> getFieldsNameValueMap(JoinPoint joinPoint) throws Exception {
Object[] args = joinPoint.getArgs();
String classType = joinPoint.getTarget().getClass().getName();
Class<?> clazz = Class.forName(classType);
String clazzName = clazz.getName();
String methodName = joinPoint.getSignature().getName(); //获取方法名称
Map<String, Object> map = new HashMap<String, Object>();
ClassPool pool = ClassPool.getDefault();
ClassClassPath classPath = new ClassClassPath(this.getClass());
pool.insertClassPath(classPath);
CtClass cc = pool.get(clazzName);
CtMethod cm = cc.getDeclaredMethod(methodName);
MethodInfo methodInfo = cm.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
if (attr == null) {
throw new RuntimeException();
}
int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
for (int i = 0; i < cm.getParameterTypes().length; i++) {
map.put(attr.variableName(i + pos), args[i]);//paramNames即参数名
}
return map;
}
}
三 使用方法。
@GetMapping("/xxxxxx")
@IdEncrypt(reqHandle = false, sourcePath = "$.data[*].id", rewritePath = "$.data[*]",type = BusinsTypeEnum.NEWS,dataType = ReturnDataTypeEnum.LIST)
public AjaxResult xxxxxx( @RequestParam(value="ids") int[] ids)
{
if(ids != null && ids.length > 0 ){
return AjaxResult.success(appDetailService.selectAppInfoByIds(ids));
}else{
return AjaxResult.success();
}
}
四,其他枚举类
public enum BusinsTypeEnum {
NEWS_AAAA("newsaaa", "xxxx"),
REPORT_AAAA("reportaaa", "xxxxx");
@EnumValue
@JsonValue
private final String type;
private final String message;
public String getType() {
return this.type;
}
public String getMessage() {
return this.message;
}
private BusinsTypeEnum(String type, String message) {
this.type = type;
this.message = message;
}
}
五,返回的数据类型
public enum ReturnDataTypeEnum {
LIST("list", "返回的data组装数据类型是list"),
MAP("map", "返回的data组装数据类型是map"),
DIRECT_LIST("directList", "非data组装直接LIST返回数据类型"),
UNENCRYPT("unencrypt", "返回的数据不需要加密");
@EnumValue
@JsonValue
private final String type;
private final String message;
public String getType() {
return this.type;
}
public String getMessage() {
return this.message;
}
private ReturnDataTypeEnum(String type, String message) {
this.type = type;
this.message = message;
}
}