我有一种情况,脚本从用户接收一些数据,然后返回一个哈希。在一段时间内,比如X秒,哈希是有效的,当与原始数据一起提供回脚本时,在指定的时间范围内,允许访问某些功能。
我这样做是通过在哈希中包含一个时间戳。我可以通过调用说floor(time()/X);
来获取时间戳,但这不是在X秒后过期,而是在1到X秒之间到期。我通过保存time()%X
并将其附加到哈希来解决这个问题,然后当我收到它,解析它并从time()
中减去它时,所以我的哈希函数看起来有点像这样: / p>
function hash($oldhash='') {
static $hash;
if(!$hash) {
$time = time();
$expoff = explode('!', $oldhash, 2);
$expoff = $expoff[0] ? $expoff[0] : $time%$this->_cfg['hashexpire'];
$hash = $expoff.'!'.sha1($this->_data.floor(($time-$expoff)/$this->_cfg['hashexpire']));
}
return $hash;
}
Theres也是一块盐,但我为了清楚起见将其删除了。
这有效,但我认为可能有更好的方法来实现我在此之后的想法,并想知道你是否有任何建议。
答案 0 :(得分:3)
嗯,你希望它在一定的秒数后过期,对吗?那么,为什么不预先计算过期时间,然后通过呢?你只是在谈论一些额外的字节传输:
function makeHash() {
$expire = time() + $this->_cfg['hashexpire'];
$hash = $expire . ':' . hash_hmac('sha1', $this->_data, $expire);
return $hash;
}
然后验证:
function verifyHash($hash) {
if(!strpos($hash, ':')) return false;
list ($expire, $rawhash) = explode(':', $hash, 2);
$testhash = hash_hmac('sha1', $this->_data, $expire);
if ($expire < time() && $testhash == $rawhash) {
return true;
}
return false;
}
请注意,它使用HMAC来“签署”数据有效负载。
如果您对数据大小非常偏执,只需将base_convert($expire, 10, 36)
发送到客户端,然后在验证时对其进行解码。
编辑:因为我正在重读你的问题,我不确定。您是否正在寻找生成的哈希值,在$x
秒后无效?或者您是否希望为$x
秒的绝对时间窗口生成相同的哈希值(之后哈希值会发生变化)?如果先前,上述解决方案将起作用。如果是后者,那么你可以尝试这样的事情:
function makeHash() {
$time = time();
$startTime = $time - ($time % $this->_cfg['hashexpire']);
return hash_hmac('sha1', $this->_data, $startTime);
}
这个工作的原因是,它使用当前窗口的第一个有效秒的时间戳进行哈希处理。这将永远保持不变,所以没有必要存储它或更进一步......
请注意,生成的哈希值只会每$_cfg['hashexpire']
秒更改一次。但它可能会在创建后的第二秒失效。因此,只有在您真正需要的时候才使用它。
}
答案 1 :(得分:2)
由于您使用安全性对此进行了标记,因此将时间附加到哈希并提取它并不是非常安全。攻击者可以撤消您的代码并提供不同的时间戳。您需要一种方法(如服务器上的数据库或平面文件构造)将哈希与用户无法修改的时间戳相关联。
另一种选择是在代码中使用密码加密时间戳,这样即使用户提取时间戳部分,她也无法加密新的时间戳。如果你的意思是'盐',那么你的问题就不清楚你是否腌制了哈希值或时间戳。
答案 2 :(得分:0)
考虑到问题,我认为你的解决方案很好。我认为cookie(以及扩展会话)是不可能的,否则你不会为此烦恼。
类似的方法是跳过向哈希附加任何内容,而是尝试当前时段和最后时段。