Mybatis-plus通過添加攔截器實現(xià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)限控制表,即基于哪個表的數(shù)據(jù)來做權(quán)限區(qū)分,目前是公司信息表 base-table: company_info # 特殊的uri,不進行數(shù)據(jù)權(quán)限控制 not-control-uri: /checkCompany-post
2 在權(quán)限處理時,將請求 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)前的請求的信息,放入到user中,用戶后面的數(shù)據(jù)權(quán)限 LoginUser loginUser = (LoginUser) authentication.get().getPrincipal(); loginUser.setUri(path + "-" + method.toLowerCase()); // …… } }
另外,用戶在的登錄系統(tǒng)之后,有一個選擇公司的動作,這時將用戶選擇的公司信息放入緩存中:
// …… // 緩存用戶選擇的公司 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)自動生成的sql,一般都是單表查詢,所以這里暫時不考慮復(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語句 // 基礎(chǔ)表,根據(jù)主鍵進行控制 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; /** * 新的分頁插件,一緩和二緩遵循mybatis的規(guī)則,需要設(shè)置 MybatisConfiguration#useDeprecatedExecutor = false 避免緩存出現(xiàn)問題(該屬性會在舊插件移除后一同移除) */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(dataPermissionInterceptor); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
到此這篇關(guān)于Mybatis-plus通過添加攔截器實現(xiàn)簡單數(shù)據(jù)權(quán)限的文章就介紹到這了,更多相關(guān)Mybatis-plus實現(xiàn)簡單數(shù)據(jù)權(quán)限內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MybatisPlus攔截器如何實現(xiàn)數(shù)據(jù)表分表
- mybatis-plus配置攔截器實現(xiàn)sql完整打印的代碼設(shè)計
- MyBatis-Plus攔截器實現(xiàn)數(shù)據(jù)權(quán)限控制的方法
- MybatisPlusInterceptor實現(xiàn)sql攔截器超詳細(xì)教程
- MyBatis-Plus攔截器實現(xiàn)數(shù)據(jù)權(quán)限控制的示例
- mybatis-plus 攔截器敏感字段加解密的實現(xiàn)
- MyBatis-Plus攔截器對敏感數(shù)據(jù)實現(xiàn)加密
- mybatis-plus攔截器、字段填充器、類型處理器、表名替換、SqlInjector(聯(lián)合主鍵處理)
- mybatisplus 的SQL攔截器實現(xiàn)關(guān)聯(lián)查詢功能
- Mybatis Plus 3.4.0分頁攔截器的用法小結(jié)
相關(guān)文章
java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實現(xiàn)
這篇文章主要介紹了java poi設(shè)置生成的word的圖片為上下型環(huán)繞以及其位置的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Java之a(chǎn)pi網(wǎng)關(guān)斷言及過濾器案例講解
這篇文章主要介紹了Java之a(chǎn)pi網(wǎng)關(guān)斷言及過濾器案例講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-085分鐘快速搭建SpringBoot3?+?MyBatis-Plus工程/項目的實現(xiàn)示例
本文主要介紹了使用IntelliJ?IDEA創(chuàng)建Spring?Boot工程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01實例解析Java的Jackson庫中的數(shù)據(jù)綁定
這篇文章主要介紹了Java的Jackson庫中的數(shù)據(jù)綁定,這里分為通常的簡單數(shù)據(jù)綁定與全數(shù)據(jù)綁定兩種情況來講,需要的朋友可以參考下2016-01-01