【移动应用开发技术】怎么用Springboot+mybatis-plus+注解实现数据权限隔离_第1页
【移动应用开发技术】怎么用Springboot+mybatis-plus+注解实现数据权限隔离_第2页
【移动应用开发技术】怎么用Springboot+mybatis-plus+注解实现数据权限隔离_第3页
【移动应用开发技术】怎么用Springboot+mybatis-plus+注解实现数据权限隔离_第4页
【移动应用开发技术】怎么用Springboot+mybatis-plus+注解实现数据权限隔离_第5页
免费预览已结束,剩余2页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】怎么用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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论