根据权限控制返回前端字段
该方案通过 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切面对标有注解的方法及字段进行过滤,在切面内自定义业务逻辑对返回字段进行处理文章来源:https://www.toymoban.com/news/detail-684351.html
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模板网!