AspectJ支持5种类型的通知注解
@Before:前置通知,在方法执行之前执行
@After:后置通知,在方法执行之后执行
@AfterRunning:返回通知,在方法返回结果之后执行
@AfterThrowing:异常通知,在方法抛出异常之后执行
@Around:环绕通知,围绕着方法执行 (可以不声明,若果声明返回值要用Object,否则返回为空,可以改变返回值慎用)
单切面中各通知方法执行顺序
Around->Before->切入点method->Around->After->afterReturning/afterThrowing
环绕前置----普通前置----环绕返回/异常----环绕后置----普通后置----普通返回/异常
HttpServletRequest常用获取URL的方法
request.getRequestURL()
返回完整的url,包括Http协议,端口号,servlet名字和映射路径,但它不包含请求参数
String getRequestURI():获取请求URI,等于项目名+Servlet路径:/Example/AServle
HttpServletRequest常用获取URL的方法_gris0509的博客-CSDN博客_request获取请求url
写切面
- 自定义注解类
定义注解格式:
public @interface 注解名 {定义体}
注解参数的可支持数据类型:
1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组
元注解
@Target,说明了Annotation所修饰的对象范围 【属性,方法,类等】
@Retention,定义了该Annotation生命周期(编译/运行)
- SOURCE:在源文件中有效(即源文件保留)
- CLASS:在class文件中有效(即class保留) 默认策略,
- RUNTIME:在运行时有效(即运行时保留)
@Documented注解是否将包含在JavaDoc中
@Inherited,是否允许子类继承该注解。
package com.sun.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
public @interface First {
String value() default "";
int num();
}
修改出参,给某些参数值加密
环绕切面,重写后必须有返回值,不能返回空
package com.csc.komodo.research.aop;
import com.baomidou.mybatisplus.plugins.Page;
import com.csc.komodo.research.common.Result;
import com.csc.komodo.research.utils.SM4Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
/**
* @author
* @date
* @description 加密敏感信息
*/
@Component
@Aspect
@Slf4j
public class SensitiveDataAspect {
/**
* 加密key
*/
private static final String KEY = "research@csc";
/**
* 敏感参数集合
*/
private static final List<String> RESPONSE_PARAMETER_LIST = new ArrayList<>();
/**
* 工号集合 内容以”csc“开头的,加密内容
*/
private static final List<String> EMPLOYEE_ID_LIST = new ArrayList<>();
/**
* 员工编号
*/
private static final String EMPLOYEE_ID_CONTENT_START = "CSC";
static {
RESPONSE_PARAMETER_LIST.add("mobilephone");
RESPONSE_PARAMETER_LIST.add("phone");
RESPONSE_PARAMETER_LIST.add("officeemail");
RESPONSE_PARAMETER_LIST.add("email");
EMPLOYEE_ID_LIST.add("id");
EMPLOYEE_ID_LIST.add("objId");
EMPLOYEE_ID_LIST.add("creatorId");
EMPLOYEE_ID_LIST.add("employeeid");
EMPLOYEE_ID_LIST.add("correspondingSellId");
EMPLOYEE_ID_LIST.add("empId");
EMPLOYEE_ID_LIST.add("employeeId");
}
/**
* 拦截注解方法
*/
@Pointcut("@annotation(com.csc.komodo.research.annotation.SensitiveData)")
public void sensitiveDataPointCut() {
}
@AfterReturning(value = "sensitiveDataPointCut()", returning = "response")
public void doSensitiveDataAfterReturning(JoinPoint joinPoint, Object response) {
try {
if (response instanceof Result) {
Result result = (Result) response;
Object object = result.getData();
if (object instanceof Page) {
Page pageList = (Page) object;
Object records = pageList.getRecords();
if (records instanceof List) {
changListValue((List<Object>) records);
}
} else if (object instanceof List) {
changListValue((List<Object>) object);
} else if (object instanceof Map) {
changeMapValue(object, SM4Utils.ENCRYPT);
} else if (object instanceof Object) {
changObjectValue(object, SM4Utils.ENCRYPT);
}
}
} catch (Exception e) {
log.error("SensitiveDataAspect-doSensitiveDataAfterReturning:", e);
}
}
/**
* @param objects
* @throws IllegalAccessException
*/
private void changListValue(List<Object> objects) throws IllegalAccessException {
List<Object> list = objects;
for (Object obj : list) {
changObjectValue(obj, SM4Utils.ENCRYPT);
}
}
/**
* 修改Object对象field的值
*
* @param obj
* @param flag
* @return
* @throws IllegalAccessException
*/
private Object changObjectValue(Object obj, int flag) throws IllegalAccessException {
Class<?> resultClz = obj.getClass();
//获取class里的所有字段
Field[] fieldInfo = resultClz.getDeclaredFields();
for (Field field : fieldInfo) {
//成员变量为private,必须进行此操作
field.setAccessible(true);
Object fieldValue = field.get(obj);
Object fieldName = field.getName();
if (RESPONSE_PARAMETER_LIST.contains(fieldName) && null != fieldValue) {
String afterValue = crypto(fieldValue, flag);
if (StringUtils.isNotEmpty(afterValue)) {
field.set(obj, afterValue);
}
}
if (EMPLOYEE_ID_LIST.contains(fieldName) && null != fieldValue) {
String id = String.valueOf(fieldValue);
if (id.length() > 3) {
if (id.startsWith(EMPLOYEE_ID_CONTENT_START) || id.startsWith(EMPLOYEE_ID_CONTENT_START.toLowerCase())) {
String afterValue = crypto(fieldValue, flag);
if (StringUtils.isNotEmpty(afterValue)) {
field.set(obj, afterValue);
}
}
}
}
long parameterNum = RESPONSE_PARAMETER_LIST.stream().filter(x -> String.valueOf(fieldValue).contains(x)).count();
long idNum = EMPLOYEE_ID_LIST.stream().filter(x -> String.valueOf(fieldValue).contains(x)).count();
if (parameterNum + idNum > 0) {
if (field.get(obj) instanceof List) {
changListValue((List<Object>) field.get(obj));
} else if (field.get(obj) instanceof List) {
changListValue((List<Object>) field.get(obj));
} else if (field.get(obj) instanceof Map) {
changeMapValue(field.get(obj), SM4Utils.ENCRYPT);
} else if (field.get(obj) instanceof Object) {
changObjectValue(field.get(obj), SM4Utils.ENCRYPT);
}
}
}
return obj;
}
/**
* 当对象为Map 修改key的值
*
* @param obj
* @param flag
* @return
*/
private Object changeMapValue(Object obj, int flag) {
Map<String, Object> map = (Map<String, Object>) obj;
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (RESPONSE_PARAMETER_LIST.contains(entry.getKey()) && null != entry.getValue()) {
Object fieldValue = map.get(entry.getKey());
String afterValue = crypto(fieldValue, flag);
if (StringUtils.isNotEmpty(afterValue)) {
map.put(entry.getKey(), afterValue);
}
}
if (EMPLOYEE_ID_LIST.contains(entry.getKey()) && null != entry.getValue()) {
String id = String.valueOf(entry.getValue());
if (id.length() > 3) {
if (id.startsWith(EMPLOYEE_ID_CONTENT_START) || id.startsWith(EMPLOYEE_ID_CONTENT_START.toLowerCase())) {
String afterValue = crypto(id, flag);
if (StringUtils.isNotEmpty(afterValue)) {
map.put(entry.getKey(), afterValue);
}
}
}
}
}
return obj;
}
/**
* 加密解密操作
*
* @param value
* @param flag 1加密 0解密
* @return
*/
private String crypto(Object value, int flag) {
String result = null;
if (null == value) {
return null;
}
try {
if (SM4Utils.ENCRYPT == flag) {
result = SM4Utils.encode(String.valueOf(value), KEY);
}
if (SM4Utils.DECRYPT == flag) {
result = SM4Utils.decode(String.valueOf(value), KEY);
}
} catch (IOException e) {
log.info("SensitiveDataAspect:加解密失败:{}" + e);
}
return result;
}
}