SpringBoot custom annotation, Springboot permission role annotation

================================

©Copyright Sweet Potato Yao2022-04-25

Sweet Potato Yao's Blog - CSDN Blog

1. Custom role annotations


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;
    
}

Second, the custom role annotation 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. Use of @HasRoles role annotations

The annotation on the method takes precedence over the annotation on the class. When the class has annotations and the method also has annotations, the method annotations take effect, but the class annotations do not take effect.

1. Use on the class

@HasRoles ({Role.ADMIN, Role.SUPER_ADMIN})

@HasRoles({Role.ADMIN, Role.SUPER_ADMIN})
public class SysDictController {}

2. Use in the method

@HasRoles(value = Role.SUPER_ADMIN)

@HasRoles(value = Role.SUPER_ADMIN)
@RequestMapping("/add")
public ModelAndView add() {}

3. Skip the check

@HasRoles (skipCheck = true)

@HasRoles(skipCheck = true)
@RequestMapping("/select")
public ModelAndView select() {}

 

 (Time is precious, sharing is not easy, donate and give back, ^_^)

================================

©Copyright Sweet Potato Yao2022-04-25

Sweet Potato Yao's Blog - CSDN Blog

Guess you like

Origin blog.csdn.net/w995223851/article/details/124407612