網站首頁 編程語言 正文
前言
最近在搞個安全需求,需要對敏感字段做加密存儲。于是,,于是我就躺了個坑。
方案梳理
方案一:基于Mybatis的攔截器Interceptor
我的第一個反應其實是基于Mybatis的攔截器Interceptor機制實現,在設置參數的時候對參數進行攔截并加密,而在查詢的時候對返回值進行解密。當然,不管是那種方案都需要對敏感字段進行標記。
實現可參考mybatis-plus實現數據字段加解密
PS: 該博客可以滿足絕大部分場景了,但Map、List<String>
沒有考慮。不過這也是基于Interceptor的弊端,就是你需要考慮更多的細節。
方案二:基于Mybatis的TypeHandler
Mybatis支持針對特定字段的類型進行特殊處理,這為字段的加解密提供了可能。關于Mybatis的TypeHandler,大家可以看看官方的【類型處理器(typeHandlers)】
簡單來說就一句話:在執行SQL之前對入參和返回值進行處理。
而Mybatis本身通過這個進行類型轉換。想知道其自帶了多少TypeHandler可以看看mybatis的這個包:org.apache.ibatis.type
基于這個特點,我們就可以利用來實現字段的加解密功能。為了不影響那些不需要加解密的字段,我們就必須要在在特定的字段上進行指定。
對于select,可以通<resultMap>
標簽來指定,例如:
<resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2">
<result column="roundingMode" property="roundingMode" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
</resultMap>
對于入參,則不需要區分是什么語句,只需要在取值的時候指定就行:
<insert id="insert2">
insert into users2 (id, name, funkyNumber, roundingMode)
values(#{id}, #{name}, #{funkyNumber},
#{roundingMode, typeHandler= org.apache.ibatis.type.EnumTypeHandler})
</insert>
這便是我們基于Mybatis實現加解密的理論基礎。
MybatisPlus優雅實現加解密
眾所周知,MybatisPlus并不準備取代Mybatis,而是對Mybatis的增強,增加一些便于使用的特性。
以TypeHandler為例:
@TableName(value = "foo_user", autoResultMap = true)
public class User {
private String username;
/**
* 通過mp的@TableField注解指定TypeHandler。
* PS: 這里的MyTypeHandler,是需要自己實現TypeHandler接口的哈。
* 由于我這里沒有邏輯,就不給大伙看了
*/
@TableField(typeHandler = MyTypeHandler.class)
private String mobile;
}
public interface UserMapper extends BaseMapper<User> {
}
就這樣,我們就完成了MybatisPlus(官方源碼縮寫為mp)的配置。我們可以很方便的調用UserMapper#insert方法,通過上面指定的typeHandler來執行我們需要對mobile字段的加密邏輯。
調用UserMapper#selectById方法,也會自動的執行typeHandler的解密邏輯。后者,通過@TableName的autoResultMap = true
配置生效,他會自動向Mybatis中注入一個ResultMap,其效果等同于我們在xml文件中書寫的resultMap。
感興趣的同學,可以參考這篇文章:
基于MybatisPlus的實現
MybatisPlus真的這么優雅絲滑?
事情并沒有這么簡單!前面我們大致了解了Mybatis本身提供的TypeHandler組件,也知道MybatisPlus的基于TypeHandler為我們提供的簡單易用的優雅的使用方式??墒?,各位同學想過沒有,我們自己在xml中寫的SQL呢?MybatisPlus也能如此智能、方便地達到我們的目的呢???
很顯然,不能夠。我們在xml中寫update語句,沒有指定typeHandler的話,是MybatisPlus也是無能為力的。這是因為他不能掌握我們的SQL了,更不能為我們添加指定typeHandler。這對于select語句也是如此!
事實上,MybatisPlus在其注解之上也有說明:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableField {
/**
* JDBC類型 (該默認值不代表會按照該值生效),
* 只生效于 mp 自動注入的 method,
* 建議配合 {@link TableName#autoResultMap()} 一起使用
* <p>
* {@link ResultMapping#jdbcType} and {@link ParameterMapping#jdbcType}
*
* @since 3.1.2
*/
JdbcType jdbcType() default JdbcType.UNDEFINED;
/**
* 類型處理器 (該默認值不代表會按照該值生效),
* 只生效于 mp 自動注入的 method,
* 建議配合 {@link TableName#autoResultMap()} 一起使用
* <p>
* {@link ResultMapping#typeHandler} and {@link ParameterMapping#typeHandler}
*
* @since 3.1.2
*/
Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface TableName {
/**
* 是否自動構建 resultMap 并使用,
* 只生效于 mp 自動注入的 method,
* 如果設置 resultMap 則不會進行 resultMap 的自動構建并注入,
* 只適合個別字段 設置了 typeHandler 或 jdbcType 的情況
*
* @since 3.1.2
*/
boolean autoResultMap() default false;
}
清楚明白地寫著只支持自動生成的方法。
要命的是,我們在實際項目中,不可能只使用單表查詢,這樣一來,我們就不得不自己寫SQL。然而,當你使用MybatisPlus這么方便愉快地寫代碼的時候,你還會深入源碼看注釋嗎?還會深入源碼了解其實現原理嗎?不,你不會,本來就是因為懶才使用MybatisPlus的。這就使得很多同學陷入迷茫,排查問題不知所措:為什么就是不生效,為什么這個方法可以?想想都崩潰!
總結
- MybatisPlus的@TableField注解的部分字段只使用于自動生成的方法,因為它可以掌控和改造目標SQL的生成。本質上還是在使用Mybatis的功能。例如:指定typeHandler、javaType。
- Mybatis本身提供了TypeHandler組件,我們可以基于這個來實現敏感字段的加解密。
后記
給大家個建議,如果你想偷懶,而且你的項目足夠簡單,簡單到通過單表操作就能夠解決問題,那么可以使用MybatisPlus。否則,我不建議大家使用MybatisPlus,尤其不建議使用這種半吊子的功能。實際上,MybatisPlus主要還是希望基于Mybatis給大家提供一些好用的特性。但是,隨著我使用地越多,就越不想使用它。上一個躺坑的是,我需要通過mockito來mock這些Mapper,來做單元測試。簡直麻了,因為它自動生成的方法太靈活了,尤其是鏈式方法。
原文鏈接:https://blog.csdn.net/Evan_L/article/details/138761755
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-02-26 微信小程序 - 將頁面可分享到朋友圈功能(兩步完成)
- 2022-09-03 Matplotlib中文亂碼的兩種詳細解決方案_python
- 2022-08-04 使用systemd部署服務的過程解析_python
- 2022-07-13 FileInputStream與BufferedInputStream的區別
- 2022-04-28 Python可視化學習之seaborn繪制線型回歸曲線_python
- 2022-11-06 Go+Redis實現延遲隊列實操_Golang
- 2022-12-16 簡單聊聊Go語言里面的閉包_Golang
- 2022-08-21 golang數組內存分配原理_Golang
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支