




下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】怎么用Springboot+mybatis-plus+注解实现数据权限隔离
今天在下给大家分享一下怎么用Springboot+mybatis-plus+注解实现数据权限隔离的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。当此注解打在类上,不需要传参,该类下所有查询接口开启数据隔离;打在方法上默认开启数据隔离,传参为false则该方法关闭验证/**
*
数据权限验证注解
*
@author
xiaohua
*
@date
2021/6/23
*/
@Documented
@Target({METHOD,
ANNOTATION_TYPE,
TYPE})
@Retention(RUNTIME)
public
@interface
DataPermission
{
/**
*
是否要进行数据权限隔离
*/
boolean
isPermi()
default
true;
}@Component
@Intercepts({@Signature(type
=
StatementHandler.class,
method
=
"prepare",
args
=
{Connection.class,
Integer.class})})
public
class
DataPermissionInterceptor
implements
Interceptor
{
private
static
final
Logger
logger
=
LoggerFactory.getLogger(DataPermissionInterceptor.class);
@Autowired
private
TokenService
tokenService;
//扫描的包路径(根据自己的项目路径来),这里是取的配置里的包路径
@Value("${permission.package-path}")
private
String
packagePath;
private
final
static
String
DEPT_ID
=
"dept_id";
private
final
static
String
USER_ID
=
"create_user";
private
static
List<String>
classNames;
@Override
public
Object
intercept(Invocation
invocation)
throws
Throwable
{
try
{
LoginInfo
user
=
tokenService.getLoginInfo();
if
(user
==
null){
return
ceed();
}
List<Long>
deptIds
=
(List<Long>)
Convert.toList(user.getDataScope());
if
(deptIds
==
null){
deptIds
=
new
ArrayList<>();
}
//反射扫包会比较慢,这里做了个懒加载
if
(classNames
==
null)
{
synchronized
(LazyInit.class){
if
(classNames
==
null){
//扫描指定包路径下所有包含指定注解的类
Set<Class<?>>
classSet
=
ClassUtil.scanPackageByAnnotation(packagePath,
DataPermission.class);
if
(classSet
==
null
&&
classSet.size()
==
0){
classNames
=
new
ArrayList<>();
}
else
{
//取得类全名
classNames
=
classSet.stream().map(Class::getName).collect(Collectors.toList());
}
}
}
}
//
拿到mybatis的一些对象
StatementHandler
statementHandler
=
PluginUtils.realTarget(invocation.getTarget());
MetaObject
metaObject
=
SystemMetaObject.forObject(statementHandler);
MappedStatement
mappedStatement
=
(MappedStatement)
metaObject.getValue("delegate.mappedStatement");
//
mappedStatement.getId()为执行的mapper方法的全路径名,newId为执行的mapper方法的类全名
String
newId
=
mappedStatement.getId().substring(0,
mappedStatement.getId().lastIndexOf("."));
//
如果不是指定的方法,直接结束拦截
if
(!classNames.contains(newId))
{
return
ceed();
}
String
newName
=
mappedStatement.getId().substring(mappedStatement.getId().lastIndexOf(".")
+
1,
mappedStatement.getId().length());
//是否开启数据权限
boolean
isPermi
=
true;
Class<?>
clazz
=
Class.forName(newId);
//遍历方法
for
(Method
method
:
clazz.getDeclaredMethods())
{
//方法是否含有DataPermission注解,如果含有注解则将数据结果过滤
if
(method.isAnnotationPresent(DataPermission.class)
&&
newName.equals(method.getName()))
{
DataPermission
dataPermission
=
method.getAnnotation(DataPermission.class);
if
(dataPermission
!=
null)
{
//不验证
if
(!dataPermission.isPermi())
{
isPermi
=
false;
}
else
{
//开启验证
isPermi
=
true;
}
}
}
}
if
(isPermi){
//
获取到原始sql语句
String
sql
=
statementHandler.getBoundSql().getSql();
//
解析并返回新的SQL语句,只处理查询sql
if
(mappedStatement.getSqlCommandType().toString().equals("SELECT"))
{
//
String
newSql
=
getNewSql(sql,deptIds,user.getUserId());
sql
=
getSql(sql,deptIds,user.getUserId());
}
//
修改sql
metaObject.setValue("delegate.boundSql.sql",
sql);
}
return
ceed();
}
catch
(Exception
e){
logger.error("数据权限隔离异常:",
e);
return
ceed();
}
}
/**
*
解析SQL语句,并返回新的SQL语句
*
注意,该方法使用了JSqlParser来操作SQL,该依赖包Mybatis-plus已经集成了。如果要单独使用,请先自行导入依赖
*
*
@param
sql
原SQL
*
@return
新SQL
*/
private
String
getSql(String
sql,List<Long>
deptIds,Long
userId)
{
try
{
String
condition
=
"";
String
permissionSql
=
"(";
if
(deptIds.size()
>
0){
for
(Long
deptId
:
deptIds)
{
if
("(".equals(permissionSql)){
permissionSql
=
permissionSql
+
deptId;
}
else
{
permissionSql
=
permissionSql
+
","
+
deptId;
}
}
permissionSql
=
permissionSql
+
")";
//
修改原语句
condition
=
DEPT_ID
+"
in
"
+
permissionSql;
}
else
{
condition
=
USER_ID
+"
=
"
+
userId;
}
if
(StringUtils.isBlank(condition)){
return
sql;
}
Select
select
=
(Select)CCJSqlParserUtil.parse(sql);
PlainSelect
plainSelect
=
(PlainSelect)select.getSelectBody();
//取得原SQL的where条件
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 饭店股份分配协议书
- 共建大数据学院协议书
- 金属回收调价协议书
- 醉酒死亡补偿协议书
- 销户车辆卖车协议书
- 解除制作合同协议书
- 尿痛护理措施
- 遣散员工补偿协议书
- 酒店合作框架协议书
- 银行终止扣款协议书
- 心理咨询的面谈技术
- DBJ∕T13-374-2021 福建省钢筋桁架叠合楼板技术标准
- 事故池管理的有关规定
- (word完整版)污水处理厂安全评价报告
- DB50∕T 867.6-2019 安全生产技术规范 第6部分:黑色金属冶炼企业
- 新产品开发流程课件
- 高中语文部编版选择性必修下册第四单元 单元学习导航 课件 (8张PPT)
- 化妆品原料-PPT课件
- 重庆市参加企业职工基本养老保险人员退休审批表
- 混凝土结构课程设计244
- 跨国道防护棚方案
评论
0/150
提交评论