假设我编写了一个Web应用程序,该应用程序在其数据库中存储了大量信息,只有具有特权的用户才能访问这些信息。例如,帖子只能由其作者阅读。为了示例,假设帖子中的每个单词都被分配了一个id,并且还必须检查该用户是否确实有权使用该单词。当向服务器发送ajax请求时,必须将所有id发送到服务器以获取请求(详细信息为何不重要)。为了安全起见,我想验证用户是否有权使用每个单词来阻止正在构建自己的ajax请求的攻击者。我可以在SQL数据库中查询每个单词以检查可能涉及一个或多个连接的授权。这导致100次查询。我想避免这么多查询。 (在我的具体实现中,我没有使用帖子和单词,但在某些请求中我需要处理~100个数据库ID。)
我想出了一个可能的解决方案,我想要一些反馈。它不是将整数作为ID传输到Web应用程序,而是在signed-id-placeholder中对id进行编码。签名的工作原理是为每个会话分配一个存储在会话表中但不发送给客户端的密钥。为了对id进行编码,将id,id类型('user_id'等)和秘密密钥附加在一起并通过散列算法进行管道传输。此结果散列的固定长度部分将附加到未编码的ID,然后发送到客户端。为了减少它的长度,它还用0-9,A-Z,a-z或base-62编码。结果是实际的id是明文(虽然被不同的基础略微掩盖),并且附加了签名。这样,更改id将使签名无效,服务器将不会遵循请求。在我目前的实现中,我使用56位的签名长度来获得大约7.2x10 ^ 16个可能的签名。
你对这个计划有什么反应?矫枉过正?有缺陷?是否有可接受的更好的解决方案?
这是php中签名函数的代码snipet(借用魔数的使用,这是一个测试实现):
public function signDbId( $id, $kind )
{
$id_seg = base62( $id );
$hash = md5( $id_seg . $kind . $this->session_key );
$signed = '';
for ( $i = 0; $i < 2; ++$i )
{
$signed .= base62( intval( substr( $hash, $i*8, 7 ), 16 ), 5 );
// pad to 5 chars
}
return $signed . $id_seg;
}
答案 0 :(得分:0)
您所描述的是CSRF令牌(跨站点请求伪造),这是一种常见的做法,但我认为您使它变得比它需要的更复杂。
CSRF令牌可以随机生成并存储在您的数据库中。
修改强>
重新阅读你的问题之后,我意识到典型的CSRF令牌无法解决需要执行许多查询的问题,但我认为执行数百个查询的需要是应用程序设计不良的症状。