前言
这个数据脱敏是最近做的一个权限系统的功能,我们这个权限系统包含菜单权限,操作权限,数据权限,字段权限,其中字段权限就是控制字段根据不同的角色隐藏或者显示,这个和数据脱敏也是差不多的,正儿八经的数据脱敏如用户的身份证后几位为**** ,或则如用户电话号码不全部展示,如187 **** 9101,我们做的这种字段权限并不是用****替代,而是这个字段直接不给前端展示!
设计方案
每个接口根据不同的业务模块来控制字段的显示,那么我们可以设计一个注解,这个注解是用来标注当前接口使用哪个业务模块,然后通过业务模块code得到当前接口需要隐藏的字段。然后做一个controller的后置处理即可。这里只是涉及到字段权限控制,后续完整的权限系统涉及会通过其他文章分享出来!
核心代码
权限注解
/**
* @description: 权限二期权限鉴定注解
* @author TAO
* @date 2021/7/13 3:53 下午
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PreAuthorize {
/**
* 角色(多个用英文逗号隔开)
* @return
*/
/**
* 权限
* 注意:格式:moduleName+"_"+permissionName 例如:项目_查看
* @return
*/
/**
* 数据权限模块code设置
* @return
*/
String moduleCode() default "";
/**
* 忽略平台
* @return
*/
}
这里只提供字段权限相关的
Controller使用
@ApiOperation(value = "根据id获取信息", authorizations = @Authorization(value = "token"))
@GetMapping("/{id}")
@PreAuthorize(moduleCode = "project_module")
public ResponseEntity<Project> info(@PathVariable Long id) {
Controller后置处理
@ControllerAdvice
public class DesensitizeResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body == null) {
return null;
}
//得到需要屏蔽的字段
Set<String> fieldAuthority = RequestContext.getCurrentHideFieldS();
if (CollectionUtils.isEmpty(fieldAuthority)) {
return body;
}
if (body instanceof Page) {
return pageDesensitize(body,fieldAuthority);
}else{
return objectDesensitize(body,fieldAuthority);
}
}
//返回值为Page时,数据字段脱敏处理
public Object pageDesensitize(Object page,Set<String> fieldAuthority) {
Page newPage = (Page) page;
List<?> records = newPage.getRecords();
if (CollectionUtils.isEmpty(records)){
return page;
}
SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
fieldAuthority.forEach(field ->{
filter.getExcludes().add(field);
});
Class<?> c = records.get(0).getClass();
newPage.setRecords(JSONObject.parseArray(JSONObject.toJSONString(records, filter),c));
return newPage;
}
//返回值普通对象,数据字段脱敏处理
public Object objectDesensitize(Object object,Set<String> fieldAuthority) {
SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
fieldAuthority.forEach(field ->{
filter.getExcludes().add(field);
});
return JSONObject.parseObject(JSON.toJSONString(object, filter), object.getClass());
}
}
RequestContext.getCurrentHideFieldS();这个数据在请求认证的时候获取用户权限信息的时候就统一查出来存储在ThreadLocal中,关于ThreadLocal这里不过多讲,需要了解的可以看看往期文章ThreadLocal-同一个线程共享数据,这里只需要知道通过RequestContext.getCurrentHideFieldS();能得到需要隐藏的字段!
标签:body,return,Spring,Object,fieldAuthority,JAVA,权限,public,脱敏 From: https://blog.51cto.com/u_15899048/5903414