数据权限和菜单权限不一样
菜单权限:
根据不同的性质的用户,显示不同的菜单。
数据权限:
设置权限,不同的用户只能访问本用户的数据,或者本部门的数据。当然对于特殊的领导可以跨部门访问数据。这些都是可以设置权限。
此代码的数据权限是基于若依框架,基于部门权限的简单数据权限设置。
本系统针对多个幼儿园,不同的幼儿园园长,只能增删查改属于本幼儿园的儿童信息。但是所有的儿童信息都储存在同一个表中。此时就需要对不同的幼儿园园长设置数据权限。
<sql id="selectKinChildrenInfoVo">
select U.CHILDREN_ID, U.CHILDREN_NAME, U.SEX, BIRTHDAY, U.REGION_CODE, U.HOME_ADDRESS, U.NATION_ID, U.PARENT_NAME, U.PARENT_PHONE ,U.dept_id from kin_children_info U
sql>
<select id="selectKinChildrenInfoList" parameterType="KinChildrenInfo" resultMap="KinChildrenInfoResult">
<include refid="selectKinChildrenInfoVo"/>
${params.dataScope}
<if test="childrenName != null and childrenName != ''"> and CHILDREN_NAME like concat('%', #{childrenName}, '%')if>
<if test="SEX != null and SEX != ''"> and SEX = #{SEX}if>
<if test="BIRTHDAY != null "> and BIRTHDAY = #{BIRTHDAY}if>
<if test="regionCode != null and regionCode != ''"> and REGION_CODE = #{regionCode}if>
<if test="homeAddress != null and homeAddress != ''"> and HOME_ADDRESS = #{homeAddress}if>
<if test="nationId != null "> and NATION_ID = #{nationId}if>
<if test="parentName != null and parentName != ''"> and PARENT_NAME like concat('%', #{parentName}, '%')if>
<if test="parentPhone != null and parentPhone != ''"> and PARENT_PHONE = #{parentPhone}if>
select>
/**
* 查询儿童信息列表
* U是儿童信息表的别名
* @param kinChildrenInfo 儿童信息
* @return 儿童信息
*
*/
@Override
@DataScope(deptAlias = "U")
public List<KinChildrenInfo> selectKinChildrenInfoList(KinChildrenInfo kinChildrenInfo)
{
return kinChildrenInfoMapper.selectKinChildrenInfoList(kinChildrenInfo);
}
上述了过后已经实现了我需要的,基于部门的数据权限访问。
当然,这不能帮助我们弄清楚,具体的实现机制。
这就需要我们去看若依框架中DataScopeAspect.java这个类(用来进行数据过滤处理的 基于切面编程)
package com.ruoyi.framework.aspectj;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.util.ShiroUtils;
import com.ruoyi.system.domain.SysRole;
import com.ruoyi.system.domain.SysUser;
/**
* 数据过滤处理
*
* @author ruoyi
*/
@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_DEPT = "3";
/**
* 部门及以下数据权限
*/
public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
/**
* 仅本人数据权限
*/
public static final String DATA_SCOPE_SELF = "5";
/**
* 数据权限过滤关键字
*/
public static final String DATA_SCOPE = "dataScope";
// 配置织入点
@Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)")
public void dataScopePointCut()
{
}
@Before("dataScopePointCut()")
public void doBefore(JoinPoint point) throws Throwable
{
handleDataScope(point);
}
protected void handleDataScope(final JoinPoint joinPoint)
{
// 获得注解
DataScope controllerDataScope = getAnnotationLog(joinPoint);
if (controllerDataScope == null)
{
return;
}
// 获取当前的用户
SysUser currentUser = ShiroUtils.getSysUser();
if (currentUser != null)
{
// 如果是超级管理员,则不过滤数据
if (!currentUser.isAdmin())
{
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias());
}
}
}
/**
* 数据范围过滤
*
* @param joinPoint 切点
* @param user 用户
* @param deptAlias 部门别名
* @param userAlias 用户别名
*/
public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias)
{
StringBuilder sqlString = new StringBuilder();
for (SysRole role : user.getRoles())
{
String dataScope = role.getDataScope();
//判断数据权限是否为全部数据
if (DATA_SCOPE_ALL.equals(dataScope))
{
sqlString = new StringBuilder();
break;
}
//判断数据权限是否为自定数据权限
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
{
sqlString.append(StringUtils.format(
" AND ({}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} )) ", deptAlias,
role.getRoleId()));
}
//判断数据权限是否为部门权限,我所需要的
else if (DATA_SCOPE_DEPT.equals(dataScope))
{
//将DataScope注解里表别名,用户的部门id代替占位符 编程字符串
sqlString.append(StringUtils.format(" WHERE {}.dept_id = {} ", deptAlias, user.getDeptId()));
}
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
{
sqlString.append(StringUtils.format(
" AND ({}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) ))",
deptAlias, user.getDeptId(), user.getDeptId()));
}
else if (DATA_SCOPE_SELF.equals(dataScope))
{
if (StringUtils.isNotBlank(userAlias))
{
sqlString.append(StringUtils.format(" AND ({}.user_id = {} )", userAlias, user.getUserId()));
}
else
{
// 数据权限为仅本人且没有userAlias别名不查询任何数据
sqlString.append(" AND (1=0) ");
}
}
}
if (StringUtils.isNotBlank(sqlString.toString()))
{
Object params = joinPoint.getArgs()[0];
if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
{
BaseEntity baseEntity = (BaseEntity) params;
// baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
//将刚才添加的语句添加到关键字dataScope,从第一位开始
//用于MyBaits文件中${params.dataScope}附加SQL语句
baseEntity.getParams().put(DATA_SCOPE, sqlString.substring(1) );
}
}
}
/**
* 是否存在注解,如果存在就获取
*/
private DataScope getAnnotationLog(JoinPoint joinPoint)
{
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
return method.getAnnotation(DataScope.class);
}
return null;
}
}
当然如果想附加不同的SQL语句,就需要对上述dataScopeFilter函数进行修改。
PS:
对于开发者而言,多看源码,看懂源码,方便我们更好的去改代码,去实现功能。