- 这里用区域和产品类型来控制工单记录,有区域权限和产品权限才可以查看某一工单记录
- 2024-09-05更新 修改为双重控制而不是某一个权限就能看
- 2024-09-20更新 修改bug-多类型并行问题
- 2024-10-18更新 修改bug-用户只有后面的单角色限制不住数据
package cn.risesun.common.aspectj;
import cn.risesun.common.annotation.DataScope;
import cn.risesun.common.utils.StringUtilsUs;
import cn.risesun.common.domain.BaseEntity;
import cn.risesun.common.domain.entity.SysRole;
import cn.risesun.common.domain.entity.SysUser;
import cn.risesun.common.domain.model.LoginUser;
import cn.risesun.common.text.Convert;
import cn.risesun.common.utils.SecurityUtils;
import cn.risesun.common.security.context.PermissionContextHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Aspect
@Component
public class DataScopeAspect {
public static final String DATA_SCOPE_ALL = "1";
public static final String DATA_SCOPE_CUSTOM = "2";
public static final String DATA_SCOPE_THIS = "3";
public static final String DATA_SCOPE_THIS_AND_CHILD = "4";
public static final String DATA_SCOPE_SELF = "5";
public static final String DATA_SCOPE = "dataScope";
public static final String AREA = "Area";
public static final String PRODUCT_TYPE = "ProductType";
@Before("@annotation(controllerDataScope)")
public void doBefore(JoinPoint point, DataScope controllerDataScope) {
clearDataScope(point);
handleDataScope(point, controllerDataScope);
}
protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtilsUs.isNotNull(loginUser)) {
SysUser currentUser = loginUser.getUser();
if (StringUtilsUs.isNotNull(currentUser) && !currentUser.isAdmin()) {
String permission = StringUtilsUs.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
dataScopeFilter(joinPoint, currentUser, controllerDataScope.productTypeAlias(), controllerDataScope.areaAlias(),
controllerDataScope.userAlias(), permission);
}
}
}
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String productTypeAlias, String areaAlias, String userAlias, String permission) {
ArrayList<String> productTypeCustomIds = new ArrayList<>();
ArrayList<String> areaCustomIds = new ArrayList<>();
List<String> conditions = new ArrayList<>();
List<String> conditions4area = new ArrayList<>();
StringBuilder sqlString = new StringBuilder();
StringBuilder sqlString4area = new StringBuilder();
StringBuilder sqlStringAll = new StringBuilder();
Set<String> allRolesPermissions = new HashSet<>();
boolean hasPermission = false;
user.getRoles().forEach(role -> allRolesPermissions.addAll(role.getPermissions()));
if (StringUtilsUs.isEmpty(permission) || StringUtilsUs.containsAny(allRolesPermissions, Convert.toStrArray(permission))) {
hasPermission = true;
}
boolean finalHasPermission = hasPermission;
user.getRoles().forEach(role -> {
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && PRODUCT_TYPE.equals(role.getScopeAbout())
&& finalHasPermission) {
productTypeCustomIds.add(Convert.toStr(role.getRoleId()));
}
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && AREA.equals(role.getScopeAbout())
&& finalHasPermission) {
areaCustomIds.add(Convert.toStr(role.getRoleId()));
}
});
if (hasPermission) {
for (SysRole role : user.getRoles()) {
String dataScope = role.getDataScope();
if (PRODUCT_TYPE.equals(role.getScopeAbout())) {
if (conditions.contains(dataScope)) {
continue;
}
if (DATA_SCOPE_ALL.equals(dataScope)) {
sqlString.append(StringUtilsUs.format(" OR 1=1 "));
conditions.add(dataScope);
break;
} else if (StringUtilsUs.isNotBlank(productTypeAlias)) {
appendCustomScopeSQL(dataScope, sqlString,
productTypeAlias, "productTypeId", user.getProductTypeId(), PRODUCT_TYPE, productTypeCustomIds, role.getRoleId());
conditions.add(dataScope);
}
}
}
for (SysRole role : user.getRoles()) {
String dataScope = role.getDataScope();
if (AREA.equals(role.getScopeAbout())) {
if (conditions4area.contains(dataScope)) {
continue;
}
if (DATA_SCOPE_ALL.equals(dataScope)) {
sqlString4area.append(StringUtilsUs.format(" OR 1=1 "));
conditions4area.add(dataScope);
break;
} else if (StringUtilsUs.isNotBlank(areaAlias)) {
appendCustomScopeSQL(dataScope, sqlString4area, areaAlias, "areaId", user.getAreaId(), AREA, areaCustomIds, role.getRoleId());
conditions4area.add(dataScope);
}
}
}
sqlString.append(StringUtilsUs.format(" OR {}.userId = {} ", userAlias, user.getUserId()));
}
if (StringUtilsUs.isEmpty(conditions4area) && StringUtilsUs.isEmpty(conditions)) {
sqlString.append(StringUtilsUs.format(" OR {}.userId = 0 ", userAlias));
}
Object params = joinPoint.getArgs()[0];
if (StringUtilsUs.isNotNull(params) && params instanceof BaseEntity) {
if (StringUtilsUs.isNotBlank(sqlString.toString())) {
sqlStringAll.append(" AND (" + sqlString.substring(4) + ")");
}
if (StringUtilsUs.isNotBlank(sqlString4area.toString())) {
sqlStringAll.append(" AND (" + sqlString4area.substring(4) + ")");
}
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, sqlStringAll);
}
}
private static void appendCustomScopeSQL(String dataScope, StringBuilder sqlString, String alias, String idName, Integer idValue, String roleTable, List<String> customIds, Integer roleId) {
if (DATA_SCOPE_CUSTOM.equals(dataScope)) {
if (customIds.size() > 1) {
sqlString.append(StringUtilsUs.format(
" OR {}.{} IN ( SELECT {} FROM Role{} WHERE roleId in ({}) ) ", alias, idName, idName, roleTable, String.join(",", customIds)));
} else {
sqlString.append(StringUtilsUs.format(
" OR {}.{} IN ( SELECT {} FROM Role{} WHERE roleId = {} ) ", alias, idName, idName, roleTable, roleId));
}
} else if (DATA_SCOPE_THIS.equals(dataScope)) {
sqlString.append(StringUtilsUs.format(" OR {}.{} = {} ", alias, idName, idValue));
} else if (DATA_SCOPE_THIS_AND_CHILD.equals(dataScope)) {
sqlString.append(StringUtilsUs.format(
" OR {}.{} IN ( SELECT {} FROM {} WHERE {} = {} or CHARINDEX(',' + '{}' + ',' , ',' + ancestorIds + ',' ) > 0 )",
alias, idName, idName, roleTable, idName, idValue, idValue));
} else {
sqlString.append(StringUtilsUs.format(" OR {}.{} = 0 ", alias, idName));
}
}
private void clearDataScope(final JoinPoint joinPoint) {
Object params = joinPoint.getArgs()[0];
if (StringUtilsUs.isNotNull(params) && params instanceof BaseEntity) {
BaseEntity baseEntity = (BaseEntity) params;
baseEntity.getParams().put(DATA_SCOPE, "");
}
}
}
package cn.risesun.common.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataScope
{
public String productTypeAlias() default "";
public String areaAlias() default "";
public String userAlias() default "u";
public String permission() default "";
}
@Data
public class SysRole extends BaseEntity
{
private static final long serialVersionUID = 1L;
@Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
private Integer roleId;
@Excel(name = "角色名称")
@NotBlank(message = "角色名称不能为空")
private String roleName;
@Excel(name = "权限字符")
@NotBlank(message = "权限字符不能为空")
private String roleKey;
@Excel(name = "角色排序")
private Integer roleSort;
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本级数据权限,4=本级及以下数据权限,5=仅本人数据权限")
private String dataScope;
private String scopeAbout;
private boolean menuCheckStrictly;
private boolean dataCheckStrictly;
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
private String status;
private String delFlag;
private boolean flag = false;
private Integer[] menuIds;
private Integer[] dataIds;
private Set<String> permissions;