以前玩一款新出的遊戲,找到了一個充值漏洞,在充值會員的時候在充值數量輸入框中先輸入-999999,提交後再輸入正數的充值數,就可以不用花錢而得到金幣,那段時間在遊戲裏真是揮金如土,什麼神獸神兵,武功祕籍,隨便買,從而虐遍全服~~雖然很不幸,不到半個月就被封號……
來模擬下單業務邏輯:
<pre name="code" class="java">public class Client {
public final static int LIMIT = 2000;// 可擁有產品的最大數量
public static void main(String[] args) {
int cur = 1000;// 目前擁有產品數量
Scanner input = new Scanner(System.in);
System.out.print("輸入預訂數量:");
while (input.hasNextInt()) {
int order = input.nextInt();
if (order > 0 && order + cur <= LIMIT) {
System.out.println("你已經成功預訂" + (cur + order) + "個產品");
} else {
System.out.println("超過限額,預訂失敗!");
}
}
}
}
這是一個很簡單的訂單處理程序,看似沒有問題,但是請看輸出結果:輸入預訂數量:800
你已經成功預訂1800個產品
2147483647
你已經成功預訂-2147482649個產品
這個2147483647是不是很眼熟?沒錯,這是int類型的最大值,因爲這個值再加上1000的時候超出了int類型的範圍,所以結果反而變成了負的。一句話歸結其原因:數字越界使校驗條件失效。
所以在單元測試中,有一項測試叫做邊界測試(也有叫做臨界測試),如果一個方法接受的是int類型,那麼以下三個值是必測的:0、正最大、負最小。如果這三個值都沒問題,這個方法纔是比較安全可靠的。
就算你再Web界面做出了嚴格嚴謹的校驗,但其實也只能防普通用戶(這裏普通用戶指不懂HTML、不懂HTTP、不懂Java的簡單使用者),而對於高手,這些校驗基本上就是擺設,通過對數據進行攔截分析,再寫個模擬器進行發送,一切的前段校驗就都變成了浮雲!!
所以,必要的數據驗證要放在服務端進行。
來源:《編寫高質量代碼:改善Java程序的151個建議》