【全栈之路】springboot+自定义注解实现权限验证

应小型网站和app后台管理系统权限框架需要,本文通过自定义注解实现方法上面的实现接口权限验证。

首先定义权限注解

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;

/**
 * 权限
 *
 * @author zhaohaiyuan
 *
 */
//标注这个类它可以标注的位置
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
//标注这个注解的注解保留时期
@Retention(RetentionPolicy.RUNTIME)
//是否生成注解文档
@Documented
public @interface Permission {
    public String role() default "";//默认的角色
    public String value() default "";//默认的权限标示
}

其次定义 AOP

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
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.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.shuogesha.common.util.JsonResult;
import com.shuogesha.common.util.ResultCode;
import com.shuogesha.platform.entity.Role;
import com.shuogesha.platform.entity.User;
import com.shuogesha.platform.filter.AdminInterceptor;
import com.shuogesha.platform.web.CmsUtils;

/**
 * 权限拦截切面
 *
 * @author zhaohaiyuan
 *
 */
@Aspect
@Component
public class PermissionAspect {

    private final static Logger logger = LoggerFactory.getLogger(PermissionAspect.class);

    // 切入点表达式决定了用注解方式的方法切还是针对某个路径下的所有类和方法进行切,方法必须是返回void类型
    @Pointcut(value = "@annotation(com.shuogesha.platform.version.Permission)")
    private void permissionCut() {
    };

    // 定义了切面的处理逻辑。即方法上加了@PermissionCheck
    @Around("permissionCut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        try {
            // 获取request方便获取当前登录用户
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            HttpServletResponse response = attributes.getResponse();
            String requestURI = request.getRequestURI();
            // 1.记录日志信息
            Signature signature = pjp.getSignature();
            String className = pjp.getTarget().getClass().getSimpleName();
            String methodName = signature.getName();
            logger.info("className:{},methodName:{},URL:{}", className, methodName, requestURI);
            // 2.角色权限校验
            MethodSignature methodSignature = (MethodSignature) signature;
            Method targetMethod = methodSignature.getMethod();
            if (targetMethod.isAnnotationPresent(Permission.class)) {
                // 获取方法上注解中表明的权限
                Permission permission = targetMethod.getAnnotation(Permission.class);
                String perm = permission.value();
                // 获取管理员用户
                User user = CmsUtils.getUser(request);
                if (StringUtils.isNotEmpty(perm)) {
                    String[] perms = perm.split(",");// 接口允许的权限
                    List<String> list = Arrays.asList(perms);
                    if (!checkPerm(list, user)) {// 没有权限进行访问操作
                        return new JsonResult(ResultCode.NOT_SUPPORTED,ResultCode.NOT_SUPPORTED.msg(), null);
                    }
                    // 执行业务逻辑,放行
                    return pjp.proceed();
                }
            }
        }catch (Exception e) {
         }
        // 执行业务逻辑,放行
        return pjp.proceed();
    }

    /**
     * 判断是否有权限
     *
     * @param list
     * @param user
     * @return
     */
    public boolean checkPerm(List<String> url, User user) {
        boolean result = false;
        if (user != null) {
            if (user.getUsername().equals(AdminInterceptor.admin)) {// 如果是特殊的管理员

            } else if (user.isAdmin()) {// 如果是超级管理员
                result = true;
            } else {
                if (user.getRoles() != null) {//循环角色是否有拥有全部权限
                    for (Role role : user.getRoles()) {
                        if (role.isAllperms()) {
                            result = true;
                            break;
                        }
                    }
                }
                List<String> list = user.getPerms();
                if (list != null) {
                    for (int i = 0; i < list.size(); i++) {
                        if (url.contains(list.get(i))) {// 只要权限其中一个满足即可
                            result = true;
                            break;
                        }
                    }
                }
            }
        }
        return result;
    }
}

注意:本次通过用户登录以后把用户的登录信息放在request里面,顾aop里面需要获取request获取当前登录用户,用户登录以后把权限和角色信息放在的用户信息中,所以直接验证是否有权限。

测试例子使用

@RequestMapping(value = "/save", method = RequestMethod.POST)
    @Permission(value = "sys:adsense:add")
    public @ResponseBody Object o_save(Adsense bean) {
        adsenseService.save(bean);
        return new JsonResult(ResultCode.SUCCESS, bean);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千年板蓝根

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值