📖 清單
- 1、包裝類型導致的NPE
- 2、xxApiWrapper命名
- 3、@see注釋
- 4、MySQL模糊匹配特殊字符bug
整理些平時不好的coding習慣導致的bug📝
1、包裝類型導致的NPE
處理項目的一個bug,看日志是發生了空指針,相關代碼如下:
@Data
public class Dto {private Integer offset;private Integer limit;}
if (dto.getLimit() < 0 || dto.getLimit() > 100) {throw new RuntimeException("參數非法");
}
這里對外API文檔寫的offset和limit有默認值0和20,但實際代碼里并未賦值,這里用的是int的包裝類,不傳時,默認值為null,而下面 < 0 的比較,會觸發自動拆箱,調用Integer對象的intValue()方法,因此,空指針
2、xxApiWrapper命名
發現一個類命名的單詞,wrapper,用它結尾命名一個封裝📦類,很不錯
/*** 封裝調用xx系統的API*/
public class ServiceApiWrapper {}
3、@see注釋
有時候,一些字段是枚舉類型,但Dto類中我們更想用String,此時,可以@see 跟一個全類名,方便點擊跳轉到對應的類上:
/*** @see com.llg.common.SourceTypeEnum*/
private String sourceType;
4、MySQL模糊匹配特殊字符bug
用戶反饋有個模糊查詢,輸入_
下劃線,返回的有帶-
中劃線的結果,debug到對應位置的代碼:
criteria.andCondition("upper(group_id) like upper('%" + searchKey + "%')");
這里很明顯是用戶輸入的下劃線被當成通配符了,作用是匹配單個字符,對于這種情況,要考慮兩個點:
- SQL注入
- 特殊字符
字符 | 類型 | 含義 |
---|---|---|
% | 通配符 | 匹配任意數量字符(包括0個) |
_ | 通配符 | 匹配單個字符 |
\ | 轉義符 | 取消后續字符的特殊含義 |
永遠不要直接拼接用戶輸入到你的SQL中,對于特殊字符,用這個工具類處理一下,加轉義符,取消后面字符的特殊含義:
public class SqlUtil {// https://dev.mysql.com/doc/refman/5.7/en/string-comparison-functions.html#operator_likepublic static String escapeLikeValue(String value) {if (value == null) {return null;}return value.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_");}
}
對于SQL注入,其實最好的就是預處理,SQL模板化,讓SQL和傳入的值分開,但這里項目用了tk mybatis框架,考慮加個正則表達式攔一下,能解決一部分,但并不是最優解:
private static final Pattern RISK_SQL = Pattern.compile("[\\s#/*'\"]");
if (RISK_SQL.matcher(searchKey).find()) {throw new RuntimeException("輸入非法");
}
但這么改其實漏洞🕳?也不少,比如union 或者結束; 搭配Drop table等等:
SELECT * FROM users WHERE id = 1 UNION SELECT password FROM users
'); DROP TABLE x; --
總之,這種拼接SQL的,要特別注意SQL注入導致數據泄漏或者數據被刪的問題。