led灯网站建设案例,dw网页设计素材包免费下载,vps 网站打不开,免费查询公司springBoot项目使用切面编程实现数据权限管理什么是数据权限管理如何实现数据权限管理什么是数据权限管理
不同用户在某页面看到数据不一致#xff0c;实现每个用户之间数据隔离的效果。 如以下场景#xff1a; ● 页面期望展示当前登录人所在部门的数据。 ● 页面期望展示当…
springBoot项目使用切面编程实现数据权限管理什么是数据权限管理如何实现数据权限管理什么是数据权限管理
不同用户在某页面看到数据不一致实现每个用户之间数据隔离的效果。 如以下场景 ● 页面期望展示当前登录人所在部门的数据。 ● 页面期望展示当前登录人所在部门及下级部门的数据。 ● 页面期望展示当前登录人创建的数据。
如何实现数据权限管理
接下来我们实现一个简单的数据权限控制规则只包括自定义sql目的是在需要的时候将自定义sql拼接到sql中并将变量替换成对应的值。 1、首先确定用户-角色-菜单-数据权限的关系 菜单有多个数据权限 角色可以绑定多个菜单的绑定菜单时可以绑定数据权限 用户与角色绑定。 2、定义注解在方法上使用注解标识当前接口对应的菜单为了查询数据权限规则同时该注解可以作为切面的切入点。
/*** 数据权限注解* Author taoyan* Date 2019年4月11日*/
Retention(RetentionPolicy.RUNTIME)
Target({ElementType.TYPE,ElementType.METHOD})
Documented
public interface PermissionData {/*** 配置菜单的组件路径,用于数据权限*/String permissionId() default ;
}3、定义数据权限规则信息对象
Data
Accessors(chain true)
EqualsAndHashCode(callSuper true)
ApiModel(value 菜单权限规则表对象, description 菜单权限规则表)
public class SysPermissionDataRule extends BaseEntity {private static final long serialVersionUID 1L;ApiModelProperty(value id, required true)TableId(value id, type IdType.ASSIGN_ID)private Long id;ApiModelProperty(value 对应的菜单id, required true)NotNull(message 对应的菜单id不能为空)private Long permissionId;ApiModelProperty(value 规则名称)private String ruleName;ApiModelProperty(value 规则值)private String ruleValue;ApiModelProperty(value 状态;1有效0无效)private String status;
}4、定义切面将用户信息和数据权限规则缓存再request中。 切面
package com.sinosoft.springbootplus.datapermission.aspect;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.sinosoft.springbootplus.datapermission.aspect.annotation.PermissionData;
import com.sinosoft.springbootplus.core.context.RequestContext;
import com.sinosoft.springbootplus.datapermission.handler.PermissionDataDepInfoHandler;
import com.sinosoft.springbootplus.datapermission.handler.PermissionDataInfoHandler;
import com.sinosoft.springbootplus.system.domain.entity.SysPermissionDataRule;
import com.sinosoft.springbootplus.system.domain.service.SysPermissionDataRuleDomain;
import com.sinosoft.springbootplus.system.util.DataAutorUtils;
import com.sinosoft.springbootplus.util.HttpServletRequestUtil;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;/*** 数据权限切面处理类* 当被请求的方法有注解PermissionData时,会在往当前request中写入数据权限信息* Date 2019年4月10日* Version: 1.0* author: jeecg-boot*/
Aspect
Component
Slf4j
public class PermissionDataAspect {Pointcut(annotation(com.sinosoft.springbootplus.datapermission.aspect.annotation.PermissionData))public void pointCut() {}Around(pointCut())public Object arround(ProceedingJoinPoint point) throws Throwable{HttpServletRequest request HttpServletRequestUtil.getRequest();//将用户信息放在request请求中MethodSignature signature (MethodSignature) point.getSignature();Method method signature.getMethod();PermissionData pd method.getAnnotation(PermissionData.class);String permissionId pd.permissionId();//根据userId和菜单id获取绑定的角色对应的数据权限ListSysPermissionDataRule dataRules sysPermissionDataRuleDomain.getPermissionDataRulesByCompentAndUserId(permissionId,loginUserId);if(dataRules ! null dataRules.size()0){//将权限信息暂存在request中DataAutorUtils.installDataSearchConditon(request,dataRules);}//将用户信息存储在request中DataPermissionContext dataPermissionContext new DataPermissionContext();//从handler中获取用户部门信息if(ObjectUtil.isNotEmpty(permissionDataDepInfoHandler)){MapString, Object userInfo permissionDataDepInfoHandler.getUserInfo(request, loginUserId);dataPermissionContext.putAll(userInfo);}//从handler中获取用户其他信息if (CollUtil.isNotEmpty(permissionDataInfoHandlers)) {for (PermissionDataInfoHandler permissionDataInfoHandler:permissionDataInfoHandlers) {MapString, Object userInfo permissionDataInfoHandler.getUserInfo(request, loginUserId);if (null ! userInfo) {dataPermissionContext.putAll(userInfo);}}}DataAutorUtils.installUserInfo(dataPermissionContext);return point.proceed();}
}
切面中往request中放和取用户信息、数据权限的工具类
public class DataAutorUtils {public static final String MENU_DATA_AUTHOR_RULES MENU_DATA_AUTHOR_RULES;public static final String SYS_USER_INFO SYS_USER_INFO;/*** 往链接请求里面传入数据查询条件*/public static synchronized void installDataSearchConditon(HttpServletRequest request, ListSysPermissionDataRule dataRules) {request.setAttribute(MENU_DATA_AUTHOR_RULES, dataRules);}/*** 获取请求对应的数据权限规则*/SuppressWarnings(unchecked)public static synchronized ListSysPermissionDataRule loadDataSearchConditon() {return (ListSysPermissionDataRule) HttpServletRequestUtil.getRequest().getAttribute(MENU_DATA_AUTHOR_RULES);}/*** 将用户信息存到request*/public static synchronized void installUserInfo(DataPermissionContext dataPermissionContext) {HttpServletRequestUtil.getRequest().setAttribute(SYS_USER_INFO, dataPermissionContext);}/*** 从request获取用户信息*/public static synchronized DataPermissionContext loadUserInfo() {return (DataPermissionContext) HttpServletRequestUtil.getRequest().getAttribute(SYS_USER_INFO);}
}5、在需要拼数据权限的接口上增加注解并初始化queryWrapper将request中的参数传进去包括了该菜单的数据权限和用户信息 4、初始化queryWrapper将数据权限规则拼接到sql中拼接时会将用户信息map中的信息替换成自定义sql #{ }中的值因此放用户信息时map中的key与自定义sql中#{ }的值要对应。
/*** 查询生成器*/
Slf4j
public class QueryGenerator {public static final String SQL_RULES_COLUMN SQL_RULES_COLUMN;/*** 获取查询条件构造器QueryWrapper实例 通用查询条件已被封装完成* param searchObj 查询实体* param parameterMap request.getParameterMap()* return QueryWrapper实例*/public static T QueryWrapperT initQueryWrapper(T searchObj, MapString, String[] parameterMap){long start System.currentTimeMillis();QueryWrapperT queryWrapper new QueryWrapperT();installMplus(queryWrapper, searchObj, parameterMap);log.debug(---查询条件构造器初始化完成,耗时:(System.currentTimeMillis()-start)毫秒----);return queryWrapper;}/*** 组装Mybatis Plus 查询条件* p使用此方法 需要有如下几点注意:* br1.使用QueryWrapper 而非LambdaQueryWrapper;* br2.实例化QueryWrapper时不可将实体传入参数* br错误示例:如QueryWrapperJeecgDemo queryWrapper new QueryWrapperJeecgDemo(jeecgDemo);* br正确示例:QueryWrapperJeecgDemo queryWrapper new QueryWrapperJeecgDemo();* br3.也可以不使用这个方法直接调用 {link #initQueryWrapper}直接获取实例*/private static void installMplus(QueryWrapper? queryWrapper,Object searchObj,MapString, String[] parameterMap) {MapString,SysPermissionDataRule ruleMap getRuleMap();//权限规则自定义SQL表达式for (String c : ruleMap.keySet()) {if(c.startsWith(SQL_RULES_COLUMN)){queryWrapper.and(i -i.apply(getSqlRuleValue(ruleMap.get(c).getRuleValue())));}}}/*** 获取请求对应的数据权限规则*/public static MapString, SysPermissionDataRule getRuleMap() {MapString, SysPermissionDataRule ruleMap new HashMap(5);ListSysPermissionDataRule list DataAutorUtils.loadDataSearchConditon();if(list ! nulllist.size()0){if(list.get(0)null){return ruleMap;}for (SysPermissionDataRule rule : list) {String column SQL_RULES_COLUMNrule.getId();ruleMap.put(column, rule);}}return ruleMap;}public static String getSqlRuleValue(String sqlRule){try {SetString varParams getSqlRuleParams(sqlRule);for(String var:varParams){String tempValue converRuleValue(var);sqlRule sqlRule.replace(#{var},tempValue);}} catch (Exception e) {log.error(e.getMessage(), e);}return sqlRule;}/*** 获取sql中的#{key} 这个key组成的set*/public static SetString getSqlRuleParams(String sql) {if(StringUtils.isEmpty(sql)){return null;}SetString varParams new HashSetString();String regex \\#\\{\\w\\};Pattern p Pattern.compile(regex);Matcher m p.matcher(sql);while(m.find()){String var m.group();varParams.add(var.substring(var.indexOf({)1,var.indexOf(})));}return varParams;}public static String converRuleValue(String ruleValue) {String value getUserSystemData(ruleValue);return value! null ? value : ruleValue;}/*** 从当前用户中获取变量*/public static String getUserSystemData(String key) {DataPermissionContext dataPermissionContext DataAutorUtils.loadUserInfo();Object o dataPermissionContext.get(key);if(o instanceof String){return dataPermissionContext.get(key).toString();}if(o instanceof List){ListString result new ArrayList();for (Object item : (List?) o){result.add((String) item);}return ( String.join(,, result) );}return null;}}