fengzf的gravatar头像
fengzf 2022-06-21 16:44:59
服务器时间与数据库时间差导致逻辑上的漏洞

1、背景:

表结构如下表,逻辑上用户存在以下几种情况:

(1)、不参加任何活动,数据库中没有记录

(2)、只能参加一种活动,即活动一、活动二、活动三有效的记录只能存在1条

需求:根据记录判断当前用户属于何种身份,如果是活动三,返回活动倒计时的毫秒值。

CREATE TABLE `activity_record` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `type` tinyint(2) DEFAULT NULL COMMENT '1-活动一 2-活动二  3-活动三',
  `uid` int(11) DEFAULT NULL COMMENT '用户id',
  `createTime` datetime DEFAULT NULL COMMENT '创建时间',
  `startTime` datetime DEFAULT NULL COMMENT '起始时间',
  `endTime` datetime DEFAULT NULL COMMENT '结束时间',
  `activityId` int(11) DEFAULT NULL COMMENT '活动id',
  `isvalid` tinyint(1) DEFAULT '1' COMMENT '是否生效 1-生效 0-失效',
  `expirationTime` datetime DEFAULT NULL COMMENT '失效时间',
  `clientType` int(2) DEFAULT NULL COMMENT '客户端类型'
  PRIMARY KEY (`id`),
  KEY `idx_uid` (`uid`) USING BTREE,
  KEY `idx_startTime` (`statTime`) USING BTREE,
  KEY `idx_endTime` (`endTime`) USING BTREE,
  KEY `idx_type` (`type`) USING BTREE,
  KEY `idx_activityId` (`activityId`) USING BTREE,
  KEY `idx_isvalid` (`isvalid`) USING BTREE,
  KEY `idx_createTime` (`createTime`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8mb4;

2、有漏洞的逻辑:

(1)、查询判断用户身份,并查询出有效记录最后的结束时间

select type,endTime from activity_record where startTime <= now() and endTime >now() limit 1 ;

(2)、如果是活动三(有记录,type=3)

Integer countDownTime = (validEndTime.getTime() - System.currentTimeMillis()) > 0?(validEndTime.getTime() - System.currentTimeMillis()):0;

结果发现

validEndTime.getTime() - System.currentTimeMillis() < 0,countDownTime=0,与活动三的身份相悖

 

原因是validEndTime.getTime() 是数据库记录的活动结束时间毫秒值,System.currentTimeMillis()是服务器当前的毫秒值,并不等于数据的当前时间,System.currentTimeMillis()与数据库的now()存在一定的时间差,可能存在System.currentTimeMillis() < now(),且代码的执行也有一定的时间。此种情况出现在活动即将结束的较短的时间内。

 

3、调整方案:

(1)、第一种,在2的基础上,以服务器时间为标杆,countDownTime=0逻辑上判定为活动过期,当前未参加任何活动,countDownTime > 0 && type=3,输出倒计时。

(2)、有二种,直接select数据库的记录算差值,type=3,countDownTime即为当前时间的倒计时(最优方案)

select type,TIMESTAMPDIFF(MICROSECOND,NOW(),endTime) as countDownTime from activity_record where startTime <= now() and endTime > now() limit 1;

 


打赏

已有1人打赏

最代码官方的gravatar头像
最近浏览
guixin  LV15 8月2日
请跟我走  LV1 7月30日
__起飞的猪  LV10 7月25日
szy0077  LV3 7月21日
随便取个名字_哈哈  LV26 7月21日
依然在路上  LV17 7月5日
jackychen1012  LV2 7月5日
cuijunjie  LV3 7月2日
jeety太阳雨  LV14 7月1日
最代码官方  LV163 6月26日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友