AOP自定义注解权限管理

定义redis缓存权限对象userSession

package com.yasinyt.admin.web.vo;

import java.util.List;

import com.yasinyt.admin.entity.Emplyee;
import com.yasinyt.admin.entity.Permission;
import com.yasinyt.admin.entity.Role;
import com.yasinyt.admin.entity.User;

import lombok.Data;
import lombok.ToString;

/**
 * @author TangLingYun
 * @describe 分布式Session对象--用于存储Redis
 */
@Data
@ToString
public class UserSessionVO {
    private User user;
    private Emplyee emlpyee;
    private List roles;
    private List> permissions;
}

定义权限注解放置某个方法的头上(表示该方法需要权限才能访问):

package com.yasinyt.admin.base.annotation;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

/**
 * @author TangLingYun
 * @describe 访问接口权限验证(特定的用戶不需要权限直接访问)
 */
@Target({ METHOD })
@Retention(RUNTIME)
public @interface RequiresPermission {
    /** 需要的权限 */
    String[] permisson() default {};

    /** 是否指定特定的用戶 默認false */
    boolean isSpecific() default false;

    /** 特定的用戶 默认admin用户 */
    String[] specificUsers() default { "admin" };
}

定义切面编程AOP类进行权限验证(通过redis缓存获取权限对象userSession)

package com.yasinyt.admin.base.aspect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.ArrayUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.aop.framework.ReflectiveMethodInvocation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.yasinyt.admin.base.annotation.RequiresPermission;
import com.yasinyt.admin.base.constant.CookieConstant;
import com.yasinyt.admin.base.exception.AuthorizeException;
import com.yasinyt.admin.base.exception.OpsException;
import com.yasinyt.admin.entity.Permission;
import com.yasinyt.admin.entity.User;
import com.yasinyt.admin.enums.ActiveStatusEnum;
import com.yasinyt.admin.enums.ResultEnum;
import com.yasinyt.admin.util.ArrayUtil;
import com.yasinyt.admin.util.CookieUtil;
import com.yasinyt.admin.util.redis.RedisClient;
import com.yasinyt.admin.util.redis.UserSessionKey;
import com.yasinyt.admin.web.vo.UserSessionVO;

/**
 * @author TangLingYun
 * @describe 权限验证AOP
 */
@Aspect
@Component
public class PermissionAspect {

    @Autowired
    private RedisClient redisClient;


    @Pointcut("@annotation(com.yasinyt.admin.base.annotation.RequiresPermission)")
    public void verify() {
    }

    @Before("verify()")
    public void doVerify(JoinPoint point) {
        RequiresPermission requiresPermission = getRequiresPermission(point);
        if(requiresPermission==null) return;
        String[] permisson = requiresPermission.permisson();
        UserSessionVO userSession = getUserSession();
        if(userSession == null) throw new AuthorizeException();
        User user = userSession.getUser();
        if(requiresPermission.isSpecific() && Arrays.asList(requiresPermission.specificUsers()).contains("admin")) return;
        if(requiresPermission.isSpecific() && Arrays.asList(requiresPermission.specificUsers()).contains(user.getUserName())) return;
        List> permissions = userSession.getPermissions();
        String[] userPermissions = new String[]{};
        for (int i = 0; i < permissions.size(); i++) {
            List list = permissions.get(i);
            String[] userpermission = list.stream().filter(e -> ActiveStatusEnum.ACTIVE.getCode().equals(e.getStatus())).map(Permission::getPermission).collect(Collectors.toList()).toArray(new String[0]);
            userPermissions = ArrayUtils.addAll(userPermissions,userpermission);
        }
        String[] intersect = ArrayUtil.intersect(userPermissions, permisson);
        if(intersect.length != permisson.length) throw new OpsException(ResultEnum.NOT_AUTHORIZATION);
    }

    /**获取需要查询的权限*/
    private RequiresPermission getRequiresPermission(JoinPoint point) {
        MethodInvocationProceedingJoinPoint methodPoint = (MethodInvocationProceedingJoinPoint) point;
        try {
            Field proxy = methodPoint.getClass().getDeclaredField("methodInvocation");
            proxy.setAccessible(true);
            ReflectiveMethodInvocation j = (ReflectiveMethodInvocation) proxy.get(methodPoint);
            Method method = j.getMethod();
            return method.getAnnotation(RequiresPermission.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**获取当前用户的权限session*/
    private UserSessionVO getUserSession(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        //查询Cookie
        Cookie cookie = CookieUtil.getCookie(request, CookieConstant.TOKEN_KEY);
        if(cookie==null){
            throw new AuthorizeException();
        }
        UserSessionVO userSessionVO = redisClient.get(UserSessionKey.generateKeyByToken,cookie.getValue(), UserSessionVO.class);
        return userSessionVO;
    }

}

注解使用(对控制器的权限控制 注意方法上的权限"RequiresPermission"注解):

@GetMapping("findOne")
    @RequiresPermission(permisson={"user:findOne"})
    public @ResponseBody User findOne(){
        System.err.println("findOne");
        return null;
    }

@GetMapping("userDel")
    @RequiresPermission(isSpecific=true,specificUsers={"tanglingyun"})
    public @ResponseBody User userDel(){
        System.err.println("userDel");
        return null;
    }

本人才疏学浅,shiro看不懂。故自己写了个简单权限管理类。

具体项目GitHub地址:
github.com/clockworm/ops

你可能感兴趣的:(AOP自定义注解权限管理)