項目需求:第三方生成一個帶13位
時間戳
參數的二維碼,掃碼後進入我的網站,我根據二維碼中時間戳(二維碼生成時間),和當前時間戳進行比較,如果詳相減後大於某個值(10分鐘、1天這種變量),則系統會提示二維碼失效,否則,將會正常訪問。
初步設計方案
獲取二維碼中的13位時間戳,用當前時間戳減去二維碼中生成的時間戳(單位是毫秒),如果大於失效時間,則認位二維碼失效,那麼會返回一個錯誤頁面。代碼如下:
public class QrTest {
public static void main(String[] args) {
// 獲得二維碼的生成時間戳
String qct = “1566447946620”;
String failTime = "1" ; // 這裏默認失效爲1秒
// 二維碼失效控制(單位:秒)
long currentTime = System.currentTimeMillis();
Long crTime = Long.parseLong(qct);
// 如果失效,則返回錯誤信息
if( (currentTime - crTime ) / 1000 > Long.parseLong(failTime)) {
System.out.println("失效");
}else {
System.out.println("有效");
}
System.out.println("當前時間戳:" + currentTime);
System.out.println("二維碼生成時間戳:" + crTime);
System.out.println("失效時間:" + failTime);
System.out.println("當前時間減去創建時間:" + (currentTime - crTime) );
System.out.println("當前時間減去創建時間(單位秒):" + (currentTime - crTime ) / 1000);
System.out.println("是否失效:" + ((currentTime - crTime ) / 1000 > Long.parseLong(failTime)) );
}
}
這樣看起來是沒有問題的,程序也可以正常處理。但是在做測試的時候,發現如果用一個未來的時間戳,或者用年月日時分秒這種格式的字符串,就可以失效繞過。代碼如下:
// 獲得二維碼的生成時間戳
//String qct = "1566447946620";
String qct = "1766556549896";//未來時間
// String qct = "2019082113211";//2.2019082113211
// String qct = "20190821132113";//3.20190821132113
// 查詢該銀行的失效時間
String failTime = "1" ; // 默認失效爲1秒
// 二維碼失效控制(單位:秒)
long currentTime = System.currentTimeMillis();
Long crTime = Long.parseLong(qct);
// 如果失效,則返回錯誤信息
if( (currentTime - crTime ) / 1000 > Long.parseLong(failTime)) {
System.out.println("失效");
}else {
System.out.println("有效");
}
System.out.println("當前時間戳:" + currentTime);
System.out.println("二維碼生成時間戳:" + crTime);
System.out.println("失效時間:" + failTime);
System.out.println("當前時間減去創建時間:" + (currentTime - crTime) );
System.out.println("當前時間減去創建時間(單位秒):" + (currentTime - crTime ) / 1000);
運行結果:
發現,上面三種情況均可以實現繞過失效的控制,隨後發現,問題在於
"當前時間減去創建時間:" (currentTime - crTime)
,上面三種情況下,相減結果必然是負數
,那麼根據這個思路進行優化。代碼如下:
//非法時間戳: 都會、造成currentTime - crTime爲負數,這樣和當前時間戳比較後均可以繞過,實現繞過
//1.未來時間的時間戳
//2.時間格式的日期:2019082113211
//3..時間格式的日期:20190821132113
public static void main(String[] args) {
// 獲得二維碼的生成時間戳
//String qct = "1566447946620";
String qct = "1766556549896";//未來時間
// String qct = "2019082113211";//2.2019082113211
// String qct = "20190821132113";//3.20190821132113
// 查詢該銀行的失效時間
String failTime = "1" ; // 默認失效爲1秒
// 二維碼失效控制(單位:秒)
long currentTime = System.currentTimeMillis();
Long crTime = Long.parseLong(qct);
// 如果失效,則返回錯誤信息
if( (currentTime - crTime ) / 1000 > Long.parseLong(failTime)) {
System.out.println("失效");
}else {
System.out.println("有效");
}
System.out.println("當前時間戳:" + currentTime);
System.out.println("二維碼生成時間戳:" + crTime);
System.out.println("失效時間:" + failTime);
System.out.println("當前時間減去創建時間:" + (currentTime - crTime) );
System.out.println("當前時間減去創建時間(單位秒):" + (currentTime - crTime ) / 1000);
System.out.println("是否失效:" + ((currentTime - crTime ) / 1000 > Long.parseLong(failTime)) );
//優化方案:"當前時間減去創建時間:" + (currentTime - crTime) 爲負數,則存在繞過嫌疑,將直接判定爲失效
// 如果失效,則返回錯誤信息
// 如果失效,則返回錯誤信息
if( (currentTime - crTime ) / 1000 < 0) {
System.out.println("優化後失效");
} else if( (currentTime - crTime ) / 1000 > Long.parseLong(failTime) ) {
System.out.println("失效");
} else {
System.out.println("有效");
}
}
歡迎關注本人個人公衆號,交流更多技術信息