java controller 根据权限控制返回前端字段

根据权限控制返回前端字段

该方案通过 AOP切面 + 注解 处理控制返回字段信息

controller注解定义

该注解在controller层方法上使用,用于需要进行字段过滤的接口

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

/**
 * 字段权限认证
 * 使用于方法级别
 * 于运行时解析使用
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAuthorize {

}

字段注解定义

该注解在字段Field上使用,用于需要进行权限控制的字段

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

/**
 * 字段校验权限
 * 使用于字段级别
 * 于运行时解析使用
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckAuth {

    /**
     * 权限名称
     * @return
     */
    String value() default "";
}

切面处理定义

AOP切面对标有注解的方法及字段进行过滤,在切面内自定义业务逻辑对返回字段进行处理

import com.test.annotation.field.CheckAuth;
import com.test.utils.PageResult;
import com.test.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
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.springframework.http.ResponseEntity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

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

/**
 * 字段权限校验切面处理
 */
@Slf4j
@Aspect
@Component
public class FieldAuthorizeAspect {

    private static List<String> PERMISSIONS = new ArrayList<>();

	/**
	 * 切面注解,过滤有FieldAuthorize注解的controller方法
	 */
    @Pointcut("@annotation(com.test.annotation.field.FieldAuthorize)")
    public void pointCut() {

    }
    
	/**
	 * 切面处理,获取controller方法返回的数据信息并进行处理
	 */
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws IllegalAccessException {
        Object reData = null;
        // 获取参数列表
        Object[] args = joinPoint.getArgs();

        try {
        	// 解析响应数据
            reData = joinPoint.proceed(args);
        } catch (Throwable throwable){
            log.error("切面解析响应数据异常", throwable);
            throw new RuntimeException(throwable);
        }
        if (reData != null){
        	// 获取当前用户所有权限
            PERMISSIONS = SecurityUtils.getCurrentUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
            // 处理响应数据
            handleReData(reData);
        }

        return reData;
    }

    private void handleReData(Object reData) throws IllegalAccessException {
    	// 根据自己controller接口返回数据类型进行解析处理
        if (reData instanceof ResponseEntity) {
            Object body = ((ResponseEntity<?>) reData).getBody();
            if (body instanceof PageResult){
                List<?> content = ((PageResult<?>) body).getContent();
                for (Object o : content) {
                    this.handleObject(o);
                }
            }
        }
    }

    private void handleListObject(Object obj) throws IllegalAccessException {
        if (obj instanceof ArrayList) {
            for (Object o : (List<?>) obj) {
                this.handleObject(o);
            }
        }
    }

    private void handleObject(Object obj) throws IllegalAccessException {
    	// 获取返回数据对象所有字段
        List<Field> fields = this.listAllFields(obj);
        for (Field field : fields) {
            if (field.getType().equals(List.class)){
                field.setAccessible(true);
                Object fieldObject = field.get(obj);
                this.handleListObject(fieldObject);
                continue;
            }

			// 判断字段上是否有权限校验注解CheckAuth
            boolean checkAuth = field.isAnnotationPresent(CheckAuth.class);

            if (checkAuth){
                field.setAccessible(true);
                // 获取权限校验名称
                String auth = field.getAnnotation(CheckAuth.class).value();
                // 判断当前用户无该权限,则将该字段内容置空
                if (!PERMISSIONS.stream().anyMatch(item -> item.equals(auth))){
                    field.set(obj, null);
                }
            }
        }
    }

    /**
     * 获取本类和超类字段
     *
     * @param obj
     */
    private List<Field> listAllFields(Object obj) {
        List fieldList = new ArrayList();
        Class tmpClass = obj.getClass();
        while (tmpClass != null) {
            fieldList.addAll(Arrays.asList(tmpClass.getDeclaredFields()));
            tmpClass = tmpClass.getSuperclass();
        }
        return fieldList;
    }
}

controller使用示例

@RestController
public class TestController {
	
	@GetMapping(value = "/list")
	@FieldAuthorize
    public ResponseEntity<PageResult<BaseInfo>> queryBaseInfo(BaseInfoQueryCriteria criteria, Page<Object> page){
        return new ResponseEntity<>(baseInfoService.queryAll(criteria,page),HttpStatus.OK);
    }
    
}

实体类使用示例

@Data
@TableName("base_info")
public class BaseInfo implements Serializable {

	@CheckAuth("baseInfo:amount")
    private BigDecimal voucherAmount;

	@CheckAuth("baseInfo:customer")
	private String customerName;
	
}

功能设计参考:
https://www.jianshu.com/p/04d506592e1b

你可能感兴趣的:(#,java工具类,java,权限,controller,web,aop切面)