项目需求:第三方生成一个带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("有效");
}
}
欢迎关注本人个人公众号,交流更多技术信息