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

这篇具有很好参考价值的文章主要介绍了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文章来源地址https://www.toymoban.com/news/detail-684351.html

到了这里,关于java controller 根据权限控制返回前端字段的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mongodb 控制查询返回字段

    使用关系型数据库时,用户在select命令后添加字段名称控制返回字段。mongodb中也支持对查询返回字段的控制。默认返回文档的所有字段。为了限制返回数据量,提高网络传输速率。用户可以通过投射(projection)来指定返回字段或在返回结果中排除一些字段。 与本系列其他文

    2024年01月23日
    浏览(27)
  • element ui根据复选框控制字段显示和隐藏

    复选框值为true和false,我这是默认为true,所有字段都显示,不勾选,则显示两个字段,根据if-else来控制,取值判断是否为true,true的话则显示,false则隐藏。 前端代码如下: template div class=\\\"app-container\\\" div class=\\\"mainbox\\\" div class=\\\"table-container table-fullscreen\\\" div class=\\\"table-opt-container

    2024年01月25日
    浏览(27)
  • SpringBoot中如果字段为空就不返回给前端

    大概内容: SpringBoot中如果字段为空就不返回给前端,可以使用@JsonInclud()来实现这个功能,可用的参数如下。 JsonInclude.Include.ALWAYS 这个是默认策略 ,任何情况下都序列化该字段,跟没加一样。 JsonInclude.Include.NON_NULL 这个最常用 ,为null或者属性没有默认值。 JsonInclude.Include

    2024年02月07日
    浏览(33)
  • 面对根据角色和单子状态如何有效的进行按钮权限的控制

    当阁下看到这个按钮权限控制时,该如何应对 问题1: 举个🌰,对于【待分配】这个工单状态的申请撤回按钮进行解析 问题2:举2个🌰对于【科室待接受】这个节点的申请撤回按钮进行解析 问题3:有些按钮 在多个节点要显示,比如【申请撤回、追加信息、催办】,像这种

    2024年01月19日
    浏览(31)
  • SpringBoot返回前端Long类型字段丢失精度问题及解决方案

    Java服务端返回Long整型数据给前端,JS会自动转换为Number类型。而Long类型能表示的最大值为(),当数值超过JS中Number类型的最大值()时,就会丢失精度。 首先,引入依赖。 新建一个自定义大数据序列化类,如下: 新建Jackson配置类 本文针对Java服务端返回Long整型数据给前端时

    2024年03月22日
    浏览(48)
  • 【前端】根据后端返回的url进行下载并设置文件下载名称

            在我们项目当中存储文件是存储到厂商的服务器上的,然后厂商返回一个可以直接下载url地址,但是前端使用这个url下载的时候永远都是保存一个名字,这时候我们就需要设置文件保存的名称,         那么如何实现呢?使用了fetch将url转换成了blob即可。 代码

    2024年02月04日
    浏览(43)
  • 【Spring Boot项目】根据用户的角色控制数据库访问权限

    在一些特定的业务需求下,要求创建只读用户,但是由于一些查询请求使用的是POST方法,因此在网关层面配置只允许请求GET方法又无法满足。所以就想到了是否可以在 JDBC 层面控制,判断角色并且只允许执行 SELECT 类型的SQL语句。 在Spring Boot项目中,我们可以通过结合网关和

    2024年02月06日
    浏览(48)
  • Java list集合中根据其中两个字段去重

    可以使用Java 8的Stream API和Collectors.toSet()方法来实现根据其中两个字段去重。 首先,使用Stream API将List转换为Stream,然后使用distinct()方法进行去重。distinct()方法默认使用元素的equals()和hashCode()方法进行去重。如果想要根据其中两个字段进行去重,需要重写equals()和hashCode()方法

    2024年02月16日
    浏览(38)
  • 数据安全之数据库字段加解密检索和前端返回脱敏?看看我这个最强解决方案

    数据安全一直是我们老生常谈的话题了,随着国产化的日渐推进和数字化信息改革,数据安全越来越被人们所重视。数据库作为存储、管理和检索数据的核心基础设施,其中可能包含着大量的敏感信息,如个人手机号、身份证号码、银行账户、家庭地址等信息。为了保障这些敏

    2024年02月13日
    浏览(36)
  • java stream distinct根据list某个字段去重

    java stream distinct根据list某个字段去重,普通List简单去重: 很显然这种满足不了需求,我们List里的是实体对象,这里的是字符串。 首先创建了一个Student类,该类包含id、name、age三个字段,使用了注解@Data,我们想根据学生的name去重。 一、Stream流 + TreeSet(推荐) 根据学生的

    2024年01月17日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包