SpringBoot自定义注解,Springboot权限角色注解

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

©Copyright 蕃薯耀 2022-04-25

蕃薯耀的博客_CSDN博客

一、自定义角色注解


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

二、自定义角色注解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的区别,主要是在继承中存在区别

三、@HasRoles角色注解使用

方法上的注解优先于类上的注解,当类有注解,方法也有注解时,方法的注解生效,类的注解不生效。

1、在类上使用

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

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

2、在方法上使用

@HasRoles(value = Role.SUPER_ADMIN)

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

3、跳过检查

@HasRoles(skipCheck = true)

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

 

 (时间宝贵,分享不易,捐赠回馈,^_^)

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

©Copyright 蕃薯耀 2022-04-25

蕃薯耀的博客_CSDN博客

猜你喜欢

转载自blog.csdn.net/w995223851/article/details/124407612