✨ 添加新特性。数据权限,统一异常包装处理

This commit is contained in:
冷冷 committed 2018-08-30 14:55:50 +08:00
1 parent 018a625f56
commit fe9283ddc2
11 files changed
+273 -15

No files matched your search

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.core.datascope;
import lombok.Data;
import java.util.HashMap;
import java.util.List;
/**
* @author lengleng
* @date 2018/8/30
* 数据权限查询参数
*/
@Data
public class DataScope extends HashMap {
/**
* 限制范围的字段名称
*/
private String scopeName = "deptId";
/**
* 具体的数据范围
*/
private List<Integer> deptIds;
/**
* 是否只查询本部门
*/
private Boolean isOnly = false;
}
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.core.datascope;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.plugins.SqlParserHandler;
import com.baomidou.mybatisplus.toolkit.PluginUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* @author lengleng
* @date 2018/8/30
* <p>
* mybatis 数据权限拦截器
*/
@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DataScopeInterceptor extends SqlParserHandler implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
this.sqlParser(metaObject);
// 先判断是不是SELECT操作
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
return invocation.proceed();
}
BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
String originalSql = boundSql.getSql();
Object parameterObject = boundSql.getParameterObject();
//查找参数中包含DataScope类型的参数
DataScope dataScope = findDataScopeObject(parameterObject);
if (dataScope == null) {
return invocation.proceed();
} else {
String scopeName = dataScope.getScopeName();
List<Integer> deptIds = dataScope.getDeptIds();
if (StrUtil.isNotBlank(scopeName) && CollectionUtil.isNotEmpty(deptIds)) {
String join = CollectionUtil.join(deptIds, ",");
originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName + " in (" + join + ")";
metaObject.setValue("delegate.boundSql.sql", originalSql);
}
return invocation.proceed();
}
}
/**
* 生成拦截对象的代理
*
* @param target 目标对象
* @return 代理对象
*/
@Override
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
}
return target;
}
/**
* mybatis配置的属性
*
* @param properties mybatis配置的属性
*/
@Override
public void setProperties(Properties properties) {
}
/**
* 查找参数是否包括DataScope对象
*
* @param parameterObj 参数列表
* @return DataScope
*/
private DataScope findDataScopeObject(Object parameterObj) {
if (parameterObj instanceof DataScope) {
return (DataScope) parameterObj;
} else if (parameterObj instanceof Map) {
for (Object val : ((Map<?, ?>) parameterObj).values()) {
if (val instanceof DataScope) {
return (DataScope) val;
}
}
}
return null;
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
package com.pig4cloud.pigx.common.core.exception;
import com.pig4cloud.pigx.common.core.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @author lengleng
* @date 2018/8/30
* 全局的的异常处理器
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
/**
* 全局异常.
*
* @param e the e
* @return R
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public R exception(Exception e) {
log.info("全局异常信息 ex={}", e.getMessage(), e);
return new R<>(e);
}
}
@@ -2,4 +2,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.pig4cloud.pigx.common.core.config.JacksonConfig,\
com.pig4cloud.pigx.common.core.config.RedisConfig,\
com.pig4cloud.pigx.common.core.config.RestTemplateConfig,\
com.pig4cloud.pigx.common.core.exception.GlobalExceptionHandler,\
com.pig4cloud.pigx.common.core.util.SpringContextHolder
@@ -38,7 +38,7 @@ import org.aspectj.lang.annotation.Aspect;
public class SysLogAspect {
@Around("@annotation(sysLog)")
public Object aroundWxApi(ProceedingJoinPoint point, SysLog sysLog) throws Throwable {
public Object around(ProceedingJoinPoint point, SysLog sysLog) throws Throwable {
String strClassName = point.getTarget().getClass().getName();
String strMethodName = point.getSignature().getName();
log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName);
@@ -2,8 +2,8 @@
security:
oauth2:
client:
client-id: ENC(xD1AY92cohwLfefsXett5Q==)
client-secret: ENC(xD1AY92cohwLfefsXett5Q==)
client-id: ENC(gPFcUOmJm8WqM3k3eSqS0Q==)
client-secret: ENC(gPFcUOmJm8WqM3k3eSqS0Q==)
scope: server
# 数据源配置
@@ -2,8 +2,8 @@
security:
oauth2:
client:
client-id: ENC(Y91StLXT8tX5TwpcTSR2kg==)
client-secret: ENC(Y91StLXT8tX5TwpcTSR2kg==)
client-id: ENC(tz2NM4GcmnE7sNJTYL8ZSg==)
client-secret: ENC(tz2NM4GcmnE7sNJTYL8ZSg==)
scope: server
## 定时任务
@@ -2,8 +2,8 @@
security:
oauth2:
client:
client-id: ENC(iVEZk4Gdt0UXDlX7ZN9J5g==)
client-secret: ENC(iVEZk4Gdt0UXDlX7ZN9J5g==)
client-id: ENC(ltJPpR50wT0oIY9kfOe1Iw==)
client-secret: ENC(ltJPpR50wT0oIY9kfOe1Iw==)
scope: server
# 数据源
@@ -20,6 +20,7 @@
package com.pig4cloud.pigx.admin.config;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.pig4cloud.pigx.common.core.datascope.DataScopeInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -40,4 +41,14 @@ public class MybatisPlusConfigurer {
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
/**
* 数据权限插件
*
* @return DataScopeInterceptor
*/
@Bean
public DataScopeInterceptor dataScopeInterceptor() {
return new DataScopeInterceptor();
}
}
@@ -22,6 +22,7 @@ package com.pig4cloud.pigx.admin.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.vo.UserVO;
import com.pig4cloud.pigx.common.core.datascope.DataScope;
import com.pig4cloud.pigx.common.core.util.Query;
import org.apache.ibatis.annotations.Param;
@@ -49,9 +50,10 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
*
* @param query 查询条件
* @param username 用户名
* @param dataScope
* @return list
*/
List selectUserVoPage(Query query, @Param("username") Object username);
List selectUserVoPage(Query query, @Param("username") Object username, DataScope dataScope);
/**
* 通过ID查询用户信息
@@ -27,19 +27,19 @@ import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.pig4cloud.pigx.admin.api.dto.UserDTO;
import com.pig4cloud.pigx.admin.api.dto.UserInfo;
import com.pig4cloud.pigx.admin.api.entity.SysDeptRelation;
import com.pig4cloud.pigx.admin.api.entity.SysRole;
import com.pig4cloud.pigx.admin.api.entity.SysUser;
import com.pig4cloud.pigx.admin.api.entity.SysUserRole;
import com.pig4cloud.pigx.admin.api.vo.MenuVO;
import com.pig4cloud.pigx.admin.api.vo.UserVO;
import com.pig4cloud.pigx.admin.mapper.SysUserMapper;
import com.pig4cloud.pigx.admin.service.SysMenuService;
import com.pig4cloud.pigx.admin.service.SysRoleService;
import com.pig4cloud.pigx.admin.service.SysUserRoleService;
import com.pig4cloud.pigx.admin.service.SysUserService;
import com.pig4cloud.pigx.admin.service.*;
import com.pig4cloud.pigx.common.core.constant.enums.EnumLoginType;
import com.pig4cloud.pigx.common.core.datascope.DataScope;
import com.pig4cloud.pigx.common.core.util.Query;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
@@ -69,6 +69,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
private final SysUserMapper sysUserMapper;
private final SysRoleService sysRoleService;
private final SysUserRoleService sysUserRoleService;
private final SysDeptRelationService sysDeptRelationService;
/**
* 通过用户名查用户的全部信息
@@ -121,8 +122,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
@Override
public Page selectWithRolePage(Query query) {
DataScope dataScope = new DataScope();
dataScope.setScopeName("deptId");
dataScope.setIsOnly(true);
dataScope.setDeptIds(getChildDepts());
Object username = query.getCondition().get("username");
query.setRecords(sysUserMapper.selectUserVoPage(query, username));
query.setRecords(sysUserMapper.selectUserVoPage(query, username, dataScope));
return query;
}
@@ -151,13 +156,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
/**
* 根据用户名删除用户(真实删除)
*
* @param username
* @return
*/
@Override
public Boolean deleteSysUserByUsernameAndUserId(String username,Integer userId) {
public Boolean deleteSysUserByUsernameAndUserId(String username, Integer userId) {
sysUserMapper.deleteSysUserByUsernameAndUserId(username,userId);
sysUserMapper.deleteSysUserByUsernameAndUserId(username, userId);
SysUserRole condition = new SysUserRole();
condition.setUserId(userId);
sysUserRoleService.delete(new EntityWrapper<>(condition));
@@ -218,4 +224,23 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
return Boolean.TRUE;
}
/**
* 获取当前用户的子部门信息
*
* @return 子部门列表
*/
private List<Integer> getChildDepts() {
Integer deptId = SecurityUtils.getUser().getDeptId();
//获取当前部门的子部门
SysDeptRelation deptRelation = new SysDeptRelation();
deptRelation.setAncestor(deptId);
List<SysDeptRelation> deptRelationList = sysDeptRelationService.selectList(new EntityWrapper<>(deptRelation));
List<Integer> deptIds = new ArrayList<>();
for (SysDeptRelation sysDeptRelation : deptRelationList) {
deptIds.add(sysDeptRelation.getDescendant());
}
return deptIds;
}
}