================================
©Copyright Patate Douce Yao2022-04-25
Blogue de Sweet Potato Yao - Blogue du RPSC
1. Annotations de rôle personnalisées
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HasRoles {
String[] value() default {};
HasType hasType() default HasType.OR;
//跳过检查,当类有注解,而类中某个方法不需要校验时,可以设置为true跳过检查
boolean skipCheck() default false;
}
Deuxièmement, l'annotation de rôle personnalisée AOP
import java.lang.reflect.Method;
import javax.annotation.Resource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import com.zj31mep.biz.system.annotation.HasRoles;
import com.zj31mep.biz.system.annotation.HasType;
import com.zj31mep.biz.system.service.SysRoleService;
import com.zj31mep.exception.BizException;
import com.zj31mep.utils.ContextUtil;
import com.zj31mep.utils.RequestUtils;
@Component
@Aspect
public class HasRoleAop {
private static final Logger log = LoggerFactory.getLogger(HasRoleAop.class);
@Resource
private SysRoleService sysRoleService;
private final static String POINT_CUT = "pointCut()";
//@annotation:用于匹配当前执行方法持有指定注解的方法
//@within:用于匹配所有持有指定注解类型内的方法:target.getClass().equals(within表达式中指定的类型)
//@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
//execution:用于匹配方法执行的连接点
//@within和@target针对类的注解,@annotation是针对方法的注解
//使用:
//@Pointcut(value = "@within(com.zj31mep.biz.system.annotation.HasRoles) || @annotation(com.zj31mep.biz.system.annotation.HasRoles)")
//@Pointcut(value = "@annotation(com.zj31mep.biz.system.annotation.HasRoles) && @annotation(hasRoles)")
//@within不能注入@annotation(hasRoles),不然@within会失效,获取注解通过反射
//@annotation:只使用@annotation,能注入注解对象,如下:
/*
* @Around(value = "@annotation(com.zj31mep.biz.system.annotation.HasRoles) && @annotation(hasRoles)", argNames="hasRoles")
* public Object around(ProceedingJoinPoint proceedingJoinPoint, HasRoles hasRoles) throws Throwable {
*/
//@Pointcut("@annotation(com.zj31mep.biz.system.annotation.HasRoles)")
@Pointcut(value = "@within(com.zj31mep.biz.system.annotation.HasRoles) "
+ "|| @annotation(com.zj31mep.biz.system.annotation.HasRoles)")
public void pointCut() {}
@Around(value = POINT_CUT)
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//log.info("proceedingJoinPoint = {}", proceedingJoinPoint);
HasRoles hasRoles = null;
Method targetMethod = getMethod(proceedingJoinPoint);
if(targetMethod.isAnnotationPresent(HasRoles.class)){
hasRoles = getMethodAnnotation(proceedingJoinPoint);
}else {
hasRoles = getClassAnnotation(proceedingJoinPoint);
}
if(hasRoles.skipCheck()) {
return proceedingJoinPoint.proceed();
}
String[] values = hasRoles.value();
if(values == null || values.length < 1) {
BizException.error("@HasRoles value不能为空");
}
HasType hasType = hasRoles.hasType();
if(!sysRoleService.hasRoleByRedis(values, hasType)) {
//BizException.error("无权限访问");
log.error("用户无权限访问Url:{} ,用户:{}", RequestUtils.getUrl(false), ContextUtil.getUser());
return RequestUtils.response403();
}
return proceedingJoinPoint.proceed();
}
private Method getMethod(ProceedingJoinPoint joinPoint) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
return methodSignature.getMethod();
}
private HasRoles getMethodAnnotation(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
Method method = getMethod(joinPoint);
return method.getAnnotation(HasRoles.class);
}
private HasRoles getClassAnnotation(ProceedingJoinPoint joinPoint) {
return AnnotationUtils.findAnnotation(joinPoint.getTarget().getClass(), HasRoles.class);
}
}
@within和@target针对类的注解,@annotation是针对方法的注解
@annotation:用于匹配当前执行方法持有指定注解的方法
@within:用于匹配所有持有指定注解类型内的方法:target.getClass().equals(within表达式中指定的类型)
@target:用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解
execution:用于匹配方法执行的连接点
@within和@target的区别,主要是在继承中存在区别
3. Utilisation des annotations de rôle @HasRoles
L'annotation sur la méthode est prioritaire sur l'annotation sur la classe. Lorsque la classe a des annotations et que la méthode a également des annotations, les annotations de méthode prennent effet, mais les annotations de classe ne prennent pas effet.
1. Utilisation sur la classe
@HasRoles ({Role.ADMIN, Role.SUPER_ADMIN})
@HasRoles({Role.ADMIN, Role.SUPER_ADMIN})
public class SysDictController {}
2. Utilisation dans la méthode
@HasRoles(valeur = Rôle.SUPER_ADMIN)
@HasRoles(value = Role.SUPER_ADMIN)
@RequestMapping("/add")
public ModelAndView add() {}
3. Passer la vérification
@HasRoles (skipCheck = true)
@HasRoles(skipCheck = true)
@RequestMapping("/select")
public ModelAndView select() {}
(Le temps est précieux, le partage n'est pas facile, donnez et rendez, ^_^)
================================
©Copyright Patate Douce Yao2022-04-25