数据权限,主要进行数据的过滤,没相应的数据权限,则不能查询、操作相应的数
据。
数据权限实现方式如下:
- 用户登录后,获取部门 ID 数据权限列表
- 根据部门 ID 列表进行数据过滤,数据过滤表,都需要有部门 ID 字段
一、自定义权限过滤注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataFilter {
/**
* 表的别名
*/
String tableAlias() default "";
/**
* 用户ID
*/
String userId() default "creator";
/**
* 部门ID
*/
String deptId() default "dept_id";
}
二、数据过滤,切面处理类
@Aspect
@Component
public class DataFilterAspect {
@Before("dataFilterCut(datafilter)")
public void dataFilter(JoinPoint point,DataFilter datafilter) {
Object params = point.getArgs()[0];
if(params != null && params instanceof Map){
UserDetail user = SecurityUser.getUser();
//如果是超级管理员或超级租户,则不进行数据过滤
if(user.getSuperAdmin() == SuperAdminEnum.YES.value() ||
user.getSuperTenant() == SuperTenantEnum.YES.value()) {
return ;
}
try {
//否则进行数据过滤
Map map = (Map)params;
String sqlFilter = getSqlFilter(user, point);
map.put(Constant.SQL_FILTER, new DataScope(sqlFilter));
}catch (Exception e){
}
return ;
}
throw new RenException(ErrorCode.DATA_SCOPE_PARAMS_ERROR);
}
/**
* 获取数据过滤的SQL
*/
private String getSqlFilter(UserDetail user, JoinPoint point) throws Exception {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = point.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes());
DataFilter dataFilter = method.getAnnotation(DataFilter.class);
//获取表的别名
String tableAlias = dataFilter.tableAlias();
if(StringUtils.isNotBlank(tableAlias)){
tableAlias += ".";
}
StringBuilder sqlFilter = new StringBuilder();
sqlFilter.append(" (");
//部门ID列表
List<Long> deptIdList = user.getDeptIdList();
if(CollUtil.isNotEmpty(deptIdList)){
sqlFilter.append(tableAlias).append(dataFilter.deptId());
sqlFilter.append(" in(").append(StringUtils.join(deptIdList, ",")).append(")");
}
//查询本人数据
if(CollUtil.isNotEmpty(deptIdList)){
sqlFilter.append(" or ");
}
sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getId());
sqlFilter.append(")");
return sqlFilter.toString();
}
}
三、数据过滤
public class DataFilterInterceptor implements InnerInterceptor {
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
DataScope scope = getDataScope(parameter);
// 不进行数据过滤
if(scope == null || StrUtil.isBlank(scope.getSqlFilter())){
return;
}
// 拼接新SQL
String buildSql = getSelect(boundSql.getSql(), scope);
// 重写SQL
PluginUtils.mpBoundSql(boundSql).sql(buildSql);
}
private DataScope getDataScope(Object parameter){
if (parameter == null){
return null;
}
// 判断参数里是否有DataScope对象
if (parameter instanceof Map) {
Map<?, ?> parameterMap = (Map<?, ?>) parameter;
for (Map.Entry entry : parameterMap.entrySet()) {
if (entry.getValue() != null && entry.getValue() instanceof DataScope) {
return (DataScope) entry.getValue();
}
}
} else if (parameter instanceof DataScope) {
return (DataScope) parameter;
}
return null;
}
private String getSelect(String buildSql, DataScope scope){
try {
Select select = (Select) CCJSqlParserUtil.parse(buildSql);
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
Expression expression = plainSelect.getWhere();
if(expression == null){
plainSelect.setWhere(new StringValue(scope.getSqlFilter()));
}else{
AndExpression andExpression = new AndExpression(expression, new StringValue(scope.getSqlFilter()));
plainSelect.setWhere(andExpression);
}
return select.toString().replaceAll("'", "");
}catch (JSQLParserException e){
return buildSql;
}
}
}
四、配置类
@Configuration
public class DataScopeConfig {
@Bean
public InnerInterceptor dataFilterInterceptor() {
return new DataFilterInterceptor();
}
}
评论 (0)