Mybatis-plus通過添加攔截器實(shí)現(xiàn)簡(jiǎn)單數(shù)據(jù)權(quán)限
1 配置文件中的配置
# 數(shù)據(jù)權(quán)限配置 data-permission: # 不再數(shù)據(jù)權(quán)限的表,目前主要是公司信息表,和一些關(guān)聯(lián)表 not-control-tables: role_menu,user_company,user_role # 權(quán)限控制表,即基于哪個(gè)表的數(shù)據(jù)來(lái)做權(quán)限區(qū)分,目前是公司信息表 base-table: company_info # 特殊的uri,不進(jìn)行數(shù)據(jù)權(quán)限控制 not-control-uri: /checkCompany-post
2 在權(quán)限處理時(shí),將請(qǐng)求 uri 放入到內(nèi)存中
/**
* 自定義權(quán)限處理
*/
@Component
@Slf4j
public class CustomAuthorizationManager implements AuthorizationManager<RequestAuthorizationContext> {
@Override
public AuthorizationDecision check(
Supplier<Authentication> authentication,
RequestAuthorizationContext requestAuthorizationContext
) {
// ……
HttpServletRequest request = requestAuthorizationContext.getRequest();
String method = request.getMethod();
String path = request.getRequestURI();
// 將當(dāng)前的請(qǐng)求的信息,放入到user中,用戶后面的數(shù)據(jù)權(quán)限
LoginUser loginUser = (LoginUser) authentication.get().getPrincipal();
loginUser.setUri(path + "-" + method.toLowerCase());
// ……
}
}另外,用戶在的登錄系統(tǒng)之后,有一個(gè)選擇公司的動(dòng)作,這時(shí)將用戶選擇的公司信息放入緩存中:
// …… // 緩存用戶選擇的公司 RBucket<String> bucket = redissonClient.getBucket(OPERATION_COMPANY + loginUserId); bucket.set(companyId, Duration.ofHours(2)); // ……
3 攔截器中的配置
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
/**
* 數(shù)據(jù)權(quán)限控制
*/
@Data
@Component
@Slf4j
public class DataPermissionInterceptor implements InnerInterceptor {
@Autowired
private RedissonClient redissonClient;
@Value("${data-permission.not-control-tables}")
public String notControlTables;
@Value("${data-permission.base-table}")
public String baseTable;
@Value("${data-permission.not-control-uri}")
public String notControlUri;
@Override
public boolean willDoQuery(
Executor executor,
MappedStatement ms,
Object parameter,
RowBounds rowBounds,
ResultHandler resultHandler,
BoundSql boundSql
) throws SQLException {
return InnerInterceptor.super.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
}
@Override
public void beforeQuery(
Executor executor,
MappedStatement ms,
Object parameter,
RowBounds rowBounds,
ResultHandler resultHandler,
BoundSql boundSql
) throws SQLException {
log.debug("數(shù)據(jù)權(quán)限處理……");
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (ObjectUtil.isNull(authentication)) {
log.debug("數(shù)據(jù)權(quán)限處理, 未登錄!");
return;
}
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
LoginUser loginUser = (LoginUser) principal;
String username = loginUser.getUsername();
// 如果是系統(tǒng)管理員,不需做作權(quán)限處理
if (SYSTEM_ADMINISTRATOR_ACCOUNT.equals(username)) {
log.debug("數(shù)據(jù)權(quán)限處理,當(dāng)前為管理員,不需要處理數(shù)據(jù)權(quán)限。");
return;
}
String uri = loginUser.getUri();
log.debug("數(shù)據(jù)權(quán)限處理,當(dāng)前uri為:{}", uri);
if (notControlUri.contains(uri)) {
log.debug("數(shù)據(jù)權(quán)限處理,當(dāng)前uri,不需要處理數(shù)據(jù)權(quán)限。");
return;
}
String sql = boundSql.getSql();
Select select;
try {
select = (Select) CCJSqlParserUtil.parse(sql);
} catch (JSQLParserException e) {
throw new RuntimeException(e);
}
// 系統(tǒng)自動(dòng)生成的sql,一般都是單表查詢,所以這里暫時(shí)不考慮復(fù)雜的情況
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
net.sf.jsqlparser.schema.Table table = (net.sf.jsqlparser.schema.Table) plainSelect.getFromItem();
String tableName = table.getName();
// 排除一些不需要控制的表
List<String> notControlTablesList = Arrays.asList(notControlTables.split(","));
if (notControlTablesList.contains(tableName.toLowerCase())) {
log.debug("數(shù)據(jù)權(quán)限處理,當(dāng)前表不做權(quán)限控制,table is {}", tableName);
return;
}
String userId = loginUser.getUser().getPkId();
RBucket<String> bucket = redissonClient.getBucket(OPERATION_COMPANY + userId);
String companyId = bucket.get();
if (StrUtil.isBlank(companyId)) {
throw new BaseException("公司id不存在!");
}
// 處理SQL語(yǔ)句
// 基礎(chǔ)表,根據(jù)主鍵進(jìn)行控制
log.debug("數(shù)據(jù)權(quán)限處理,處理之前的sql為: {}", sql);
Expression where = plainSelect.getWhere();
Expression envCondition;
try {
if (baseTable.equals(tableName.toLowerCase())) {
envCondition = CCJSqlParserUtil.parseCondExpression("PK_ID = " + companyId);
} else {
envCondition = CCJSqlParserUtil.parseCondExpression("COMPANY_ID = " + companyId);
}
} catch (JSQLParserException e) {
throw new RuntimeException(e);
}
if (where == null) {
plainSelect.setWhere(envCondition);
} else {
AndExpression andExpression = new AndExpression(where, envCondition);
plainSelect.setWhere(andExpression);
}
sql = plainSelect.toString();
log.debug("數(shù)據(jù)權(quán)限處理,處理之后的sql為: {}", sql);
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
mpBs.sql(sql);
}
}4 啟用插件
@Configuration
@MapperScan("xxx.xxx.xx.mapper")
public class MybatisPlusConfig {
@Autowired
private DataPermissionInterceptor dataPermissionInterceptor;
/**
* 新的分頁(yè)插件,一緩和二緩遵循mybatis的規(guī)則,需要設(shè)置 MybatisConfiguration#useDeprecatedExecutor = false 避免緩存出現(xiàn)問題(該屬性會(huì)在舊插件移除后一同移除)
*/ @Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(dataPermissionInterceptor);
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}到此這篇關(guān)于Mybatis-plus通過添加攔截器實(shí)現(xiàn)簡(jiǎn)單數(shù)據(jù)權(quán)限的文章就介紹到這了,更多相關(guān)Mybatis-plus實(shí)現(xiàn)簡(jiǎn)單數(shù)據(jù)權(quán)限內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MybatisPlus攔截器如何實(shí)現(xiàn)數(shù)據(jù)表分表
- mybatis-plus配置攔截器實(shí)現(xiàn)sql完整打印的代碼設(shè)計(jì)
- MyBatis-Plus攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限控制的方法
- MybatisPlusInterceptor實(shí)現(xiàn)sql攔截器超詳細(xì)教程
- MyBatis-Plus攔截器實(shí)現(xiàn)數(shù)據(jù)權(quán)限控制的示例
- mybatis-plus 攔截器敏感字段加解密的實(shí)現(xiàn)
- MyBatis-Plus攔截器對(duì)敏感數(shù)據(jù)實(shí)現(xiàn)加密
- mybatis-plus攔截器、字段填充器、類型處理器、表名替換、SqlInjector(聯(lián)合主鍵處理)
- mybatisplus 的SQL攔截器實(shí)現(xiàn)關(guān)聯(lián)查詢功能
- Mybatis Plus 3.4.0分頁(yè)攔截器的用法小結(jié)
相關(guān)文章
詳解SpringBoot如何自定義一個(gè)Starter
小伙伴們?cè)?jīng)可能都經(jīng)歷過整天寫著CURD的業(yè)務(wù),都沒寫過一些組件相關(guān)的東西,這篇文章記錄一下SpringBoot如何自定義一個(gè)Starter。原理和理論就不用多說了,可以在網(wǎng)上找到很多關(guān)于該方面的資料,這里主要分享如何自定義2022-11-11
java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實(shí)現(xiàn)
這篇文章主要介紹了java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Java之a(chǎn)pi網(wǎng)關(guān)斷言及過濾器案例講解
這篇文章主要介紹了Java之a(chǎn)pi網(wǎng)關(guān)斷言及過濾器案例講解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
Java中高效的判斷數(shù)組中某個(gè)元素是否存在詳解
相信大家在操作Java的時(shí)候,經(jīng)常會(huì)要檢查一個(gè)數(shù)組(無(wú)序)是否包含一個(gè)特定的值?這是一個(gè)在Java中經(jīng)常用到的并且非常有用的操作。同時(shí),這個(gè)問題在Stack Overflow中也是一個(gè)非常熱門的問題。本文將分析幾種常見用法及其時(shí)間成本,有需要的朋友們可以參考借鑒。2016-11-11
JavaWeb實(shí)現(xiàn)簡(jiǎn)單查詢商品功能
這篇文章主要為大家詳細(xì)介紹了JavaWeb實(shí)現(xiàn)簡(jiǎn)單查詢商品功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
5分鐘快速搭建SpringBoot3?+?MyBatis-Plus工程/項(xiàng)目的實(shí)現(xiàn)示例
本文主要介紹了使用IntelliJ?IDEA創(chuàng)建Spring?Boot工程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01
實(shí)例解析Java的Jackson庫(kù)中的數(shù)據(jù)綁定
這篇文章主要介紹了Java的Jackson庫(kù)中的數(shù)據(jù)綁定,這里分為通常的簡(jiǎn)單數(shù)據(jù)綁定與全數(shù)據(jù)綁定兩種情況來(lái)講,需要的朋友可以參考下2016-01-01

