使用AOP来进行权限鉴定

使用AOP来进行权限鉴定

  • 什么是AOP

aop是面向切面编程,是oop的一种补充,可以对某些事务进行统一管理,比如(权限校验、日志、事务管理),将共性需求的代码抽离出来,通过配置的方式,声明这些代码什么时候调用,还不用修改原有的代码。

  • 为什么要进行权限鉴定

我们在开发一个系统的时候,对于不同的用户会有不同的操作权限,比如管理员和普通用户。不能让普通用户也能去调用一些只能管理员调用的接口。那样系统的安全性就很低。总的来说,需要提高系统安全性就需要权限校验。

  • 为什么要使用AOP来进行权限鉴定

还是我们对aop的解释中说到,aop能将共性代码抽离,通过配置的方式声明什么时候调用,还不用修改原有代码。

  • 怎么使用AOP来进行权限鉴定

pom.xml导入aop依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

我们此次通过注解的方式来实现aop

先定义一个权限校验注解

AuthCheck

package com.xc.project.annotation;

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

/**
 * 权限校验
 * @author xc
 */
// 该注解表示我们自定义的这个注解能用到那些地方,ElementType.METHOD表示能用到方法上
@Target(ElementType.METHOD)
// 表明注解的生命周期,在运行时有效,所以可以通过反射获取
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {

    /**
     * 必须有某个权限
     *
     * @return
     */
    String mustRole() default "";

}

定义权限枚举类UserRoleEnum

package com.xc.project.model.enums;

import org.apache.commons.lang3.ObjectUtils;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户角色枚举
 * @author xc
 */
public enum UserRoleEnum {

    USER("用户", "user"),
    ADMIN("管理员", "admin"),
    BAN("被封号", "ban");

    private final String text;

    private final String value;

    UserRoleEnum(String text, String value) {
        this.text = text;
        this.value = value;
    }

    /**
     * 获取值列表
     *
     * @return
     */
    public static List<String> getValues() {
        return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());
    }

    /**
     * 根据 value 获取枚举
     *
     * @param value
     * @return
     */
    public static UserRoleEnum getEnumByValue(String value) {
        if (ObjectUtils.isEmpty(value)) {
            return null;
        }
        for (UserRoleEnum anEnum : UserRoleEnum.values()) {
            if (anEnum.value.equals(value)) {
                return anEnum;
            }
        }
        return null;
    }

    public String getValue() {
        return value;
    }

    public String getText() {
        return text;
    }
}

再定义一个权限校验的aop类

AuthInterceptor

package com.xc.project.aop;

import com.xc.project.annotation.AuthCheck;
import com.xc.project.common.ErrorCode;
import com.xc.project.exception.BusinessException;
import com.xc.project.model.enums.UserRoleEnum;
import com.xc.project.service.UserService;
import com.xc.xcapicommon.model.entity.User;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * 权限校验 AOP
 * @author xc
 */
// 用于定义一个切面。它将通知织入到目标对象的指定连接点
@Aspect
// 注册成spring管理的组件
@Component
public class AuthInterceptor {

    @Resource
    private UserService userService;

    /**
     * 执行拦截
     *
     * @param joinPoint
     * @param authCheck
     * @return
     */
    // 表示在注解AuthCheck调用前后完成权限鉴定
    @Around("@annotation(authCheck)")
    public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
        // 先获取自定义需求权限
        String mustRole = authCheck.mustRole();
        //获取当前登录用户
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        User loginUser = userService.getLoginUser(request);
        // 如果定义了权限
        if (StringUtils.isNotBlank(mustRole)) {
            // 从自定义的枚举类中拿到定义的权限
            UserRoleEnum mustUserRoleEnum = UserRoleEnum.getEnumByValue(mustRole);
            // 如果没定义该权限,则抛出异常
            if (mustUserRoleEnum == null) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
            // 拿到当前登录用户的权限
            String userRole = loginUser.getUserRole();
            // 如果被封号,直接拒绝
            if (UserRoleEnum.BAN.equals(mustUserRoleEnum)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
            }
            // 必须有管理员权限
            if (UserRoleEnum.ADMIN.equals(mustUserRoleEnum)) {
                if (!mustRole.equals(userRole)) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
                }
            }
        }
        // 通过权限校验,放行
        return joinPoint.proceed();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值