为了对某些接口访问进行权限校验,尝试用通过自定义注解对需要校验的Controller方法进行拦截,可获取方法上的参数、@requestMapping注解参数(uri、method等),根据这些参数确定唯一资源,通过校验逻辑来管理是否执行该方法的执行以及自定义返回消息提示给前端。
1.定义切点,自定义一个名为ValidateOnAccess 的注解
package com.weiller.utils.annotation;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValidateOnAccess {
}
2. 定义切面,利用环绕通知进行方法拦截和校验逻辑处理
@Component
@Aspect
public class ValidateInterceptor {
@Pointcut("@annotation(com.weiller.utils.annotation.ValidateOnAccess)")
public void validate(){
}
@Around("validate()")
public Object around(ProceedingJoinPoint pjp){
Msg msg = new Msg();
try {
// 1.捕获资源信息
String methodName = pjp.getSignature().getName();
Object[] args = pjp.getArgs(); // 请求接收的参数args
Class<?> targetClass = pjp.getTarget().getClass();
Class[] parameterTypes = ((MethodSignature) pjp.getSignature()).getParameterTypes();
Method methodClass = targetClass.getMethod(methodName, parameterTypes);
Annotation[] annotations = methodClass.getAnnotations();
String uri = ""; // 请求路径
String method = ""; // 请求方法
loop:for(Annotation annotation:annotations) {
Class<? extends Annotation> aClass = annotation.annotationType();
String simpleName = aClass.getSimpleName();
switch (simpleName){
case "GetMapping":
GetMapping getMapping = (GetMapping)annotation;
uri = getMapping.value()[0];
method = "GET";
break loop;
case "PostMapping":
PostMapping postMapping = (PostMapping)annotation;
uri = postMapping.value()[0];
method = "POST";
break loop;
case "PutMapping":
PutMapping putMapping = (PutMapping)annotation;
uri = putMapping.value()[0];
method = "PUT";
break loop;
case "DeleteMapping":
DeleteMapping deleteMapping = (DeleteMapping)annotation;
uri = deleteMapping.value()[0];
method = "DELETE";
break loop;
case "RequestMapping":
RequestMapping requestMapping = (RequestMapping)annotation;
uri = requestMapping.value()[0];
RequestMethod[] requestMethods = requestMapping.method();
if(requestMethods.length >0){
method = requestMethods[0].name();
}
break loop;
}
}
// 2.获取当前登录用户信息,此处省略调用逻辑
String userId = null;
HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//根据request可以获取userInfo
//如果调用成功 获取用户编号,如果调用失败返回错误消息,直接return msg
// 3.权限校验逻辑,此处省略校验调用逻辑
// 如果调用失败,则返回错误信息,直接return msg
// 如果校验通过则执行该方法,获取数据,封装到返回消息中,并return msg
Object data = pjp.proceed();
msg.setCode("200");
msg.setMsg("允许访问");
msg.setData(data);
} catch (Throwable throwable) {
throwable.printStackTrace();
msg.setMsg("内部异常,访问失败");
msg.setCode("500");
}
return msg;
}
}
/**
* Msg 响应消息实体
*/
public class Msg implements Serializable {
private static final long serialVersionUID = 1L;
// 状态码
private String code;
// 返回信息
private String msg ="操作失败!";
// 返回的数据
private Object data;
public Msg(){
}
// 省略getter setter
}