天天看點

SpringBoot自定義注解,Springboot權限角色注解

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

©Copyright 蕃薯耀 2022-04-25

https://www.cnblogs.com/fanshuyao/

一、自定義角色注解

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

https://www.cnblogs.com/fanshuyao/

今天越懶,明天要做的事越多。

繼續閱讀