日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mybatis整合数据权限

發(fā)布時(shí)間:2024/7/5 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mybatis整合数据权限 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

現(xiàn)在很多企業(yè)級(jí)應(yīng)用都需要攔截?cái)?shù)據(jù)權(quán)限, 只有配置了相應(yīng)數(shù)據(jù)權(quán)限的人才能看到該數(shù)據(jù)

關(guān)于數(shù)據(jù)權(quán)限的實(shí)現(xiàn), 個(gè)人想了兩種實(shí)現(xiàn)方式

第一種是基于AOP, 配置相應(yīng)的注解, 在切面中將數(shù)據(jù)權(quán)限的參數(shù)值強(qiáng)制設(shè)置到請(qǐng)求參數(shù)中去, 然后dao層利用mybatis的動(dòng)態(tài)sql, 將權(quán)限值拼接進(jìn)去, 該方案有前提條件, 數(shù)據(jù)權(quán)限控制的字段必須放到基類中, 其他的對(duì)象要繼承該基類, Mapper.xml必須抽取一個(gè)公用的, 其他的Mapper需要引用該mapper文件作為權(quán)限控制(否則每個(gè)類和Mapper.xml都要獨(dú)自維護(hù)一套, 不便于后續(xù)擴(kuò)展和維護(hù))

第二種是基于mybatis的攔截器, 攔截sql后將數(shù)據(jù)權(quán)限控制的sql拼接進(jìn)去, 基于mybatis攔截器拼接sql的難點(diǎn)在于數(shù)據(jù)權(quán)限sql和原sql的拼接, 網(wǎng)上很多版本都是select * from (原sql) where 數(shù)據(jù)權(quán)限sql, 這種實(shí)際上并不可取, 一旦出現(xiàn)分頁, 或者最終查出的結(jié)果集不包含權(quán)限控制字段的話, 就會(huì)出現(xiàn)bug

這里使用的是正則表達(dá)式去匹配后拼接權(quán)限sql, 其他的可以參考網(wǎng)上mybatis攔截器的方案

/*** sql解析器** @author wang.js on 2019/5/8.* @version 1.0*/ public class SqlParser {private SqlParser() {}private static final String SQL_WHERE = "WHERE";private static final String SQL_LEFT_JOIN = "LEFT JOIN ";/*** 將數(shù)據(jù)權(quán)限的sql拼進(jìn)原sql中** @param originSql 原sql* @param privilegeSql 數(shù)據(jù)權(quán)限sql* @return String*/public static String handlerSql(String originSql, String privilegeSql) {if (originSql.endsWith(";")) {originSql = originSql.substring(0, originSql.lastIndexOf(";"));}originSql = originSql.replace("\t", " ").replace("\n", " ");originSql = originSql.replaceAll(" {2,}", " ");originSql = originSql.replaceAll(" where ", " " + SQL_WHERE + " ");originSql = addWhere(originSql);originSql = originSql.replace("left", "LEFT");originSql = originSql.replace("join", "JOIN");originSql = originSql.replaceAll("LEFT[ ]+JOIN[ ]+", SQL_LEFT_JOIN);List<String> matcherList = matcherTableSql(originSql);for (String matcherSql : matcherList) {if (originSql.contains(SQL_LEFT_JOIN + matcherSql)) {continue;}String newMatcherSql = mergeSql(matcherSql, privilegeSql);originSql = originSql.replace(matcherSql, newMatcherSql);}return originSql;}/*** 添加where關(guān)鍵字** @param originSql 原始sql* @return String*/private static String addWhere(String originSql) {if (originSql.contains("WHERE")) {return originSql;}String[] split = originSql.split(" ");for (int i = 0; i < split.length; i++) {if (split[i].equalsIgnoreCase("GROUP") && (i + 1) < split.length && split[i + 1].equalsIgnoreCase("BY")) {return originSql.replaceAll(split[i], "WHERE 1=1 GROUP");}if (split[i].equalsIgnoreCase("ORDER") && (i + 1) < split.length && split[i + 1].equalsIgnoreCase("BY")) {return originSql.replaceAll(split[i], "WHERE 1=1 ORDER");}if (split[i].equalsIgnoreCase("LIMIT")) {return originSql.replaceAll(split[i], "WHERE 1=1 LIMIT");}}return originSql + " WHERE 1=1";}/*** 合并sql** @param originSql 原sql* @param privilegeSql 數(shù)據(jù)權(quán)限sql* @return String*/private static String mergeSql(String originSql, String privilegeSql) {return originSql.replace(SQL_WHERE, SQL_WHERE + " " + privilegeSql);}/*** 配置符合** @param originSql 原sql* @return List<String>*/private static List<String> matcherTableSql(String originSql) {List<String> matcharList = new ArrayList<>();String regex = "\\w[ ,](.*?)WHERE";Pattern pattern = Pattern.compile(regex);Matcher matcher = pattern.matcher(originSql);while (matcher.find()) {matcharList.add(matcher.group());}return matcharList;}}

寫個(gè)測(cè)試類

@Test public void t1() {String privilegeSql = " brand_code in (1, 2, 3) and region_code in (2, 3) and";String originSql = "select * from (select t1, t2, t3 from tableA where 1=1) t1, (select t1, t2, t3 from tableB s where 1=1) t2";// String originSql = "select t1, t2, t3 from tableA";System.out.println(SqlParser.handlerSql(originSql, privilegeSql)); }

測(cè)試后輸出的結(jié)果為 select * from (select t1, t2, t3 from tableA WHERE brandcode in (1, 2, 3) and regioncode in (2, 3) and 1=1) t1, (select t1, t2, t3 from tableB s WHERE brandcode in (1, 2, 3) and regioncode in (2, 3) and 1=1) t2

這里需要強(qiáng)調(diào)的是, 必須保證每條需要權(quán)限控制的語句都含有where關(guān)鍵字, 否則數(shù)據(jù)權(quán)限sql拼接不進(jìn)去

總結(jié) 第一種基于AOP的方案需要維護(hù)基類和Mapper的通用代碼, 其他的必須繼承或引用這兩個(gè)文件, 但是好處是不容易出現(xiàn)bug

第二種基于mybatis攔截器的方案需要保證每條需要權(quán)限控制的sql都有where關(guān)鍵字, 好處是mapper.xml和基類都沒有強(qiáng)制性要求

具體使用哪一種就看實(shí)際項(xiàng)目需要了

轉(zhuǎn)載于:https://www.cnblogs.com/shanzhai/p/10885401.html

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的mybatis整合数据权限的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。