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头像
最近浏览
stedian  LV4 2023年12月20日
fengzf  LV16 2023年7月19日
小骆驼  LV3 2023年2月28日
itiswm 2023年2月27日
暂无贡献等级
欠踹de背影  LV25 2023年2月8日
wsh564494062  LV8 2023年1月28日
lonesafe  LV11 2022年12月22日
ssk123 2022年12月15日
暂无贡献等级
八九不如意十  LV2 2022年11月25日
best2018  LV46 2022年11月18日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友