我正在考虑写一个网页,为客户提供反馈表 我希望客户能够使用任何特定订单的唯一URL访问此表单;一个简单的例子是http://www.example.com/feedback/012345。
的格式旁注:我已经熟悉URL重写了。在给定语言或给定服务器上创建/重定向URL超出了此问题的范围
客户必须进行身份验证(或者,就此而言,甚至拥有帐户)才能访问反馈表单,这是不可接受的。但是,出于对统计正确性的关注,我对example.com/feedback/[order_id]上面的明显解决方案不满意。这允许任何人更改URL中的ID并访问另一个订单的反馈。
另一方面,我希望能够从打印输出(例如收据)输入这些URL,因此提供类似很多“重置密码”链接的长哈希不是有效选项。
基于此,我有以下标准:
我的想法是我应该在URL中放入两个数据。客户记录中有很多人类可读的数据可以帮助解决这个问题,例如客户ID,订单的联系电话号码,姓氏......虽然这样就无法更改一两个数字,但我看不到它显着改善了给无聊攻击者的给定URL的“可猜测性”。
采用/ feedback / [surname] / [id]的简单示例,您可以通过简单的字典攻击页面来接收一组有效的URL:
for x in range(00000,99999):
for name in ["jones","smith", ....]:
url = "http://www.example.com/feedback/"+name+"/"+x
if exists(url):
print(url)
我考虑过的下一件事,就像tinyurl这样的服务,是对ID号进行散列并以/ feedback / [hash] / [id]的形式提供一个URL
我已经做了一些研究,并了解到URL缩短服务实际上可能使用自动增量ID记录而不是实际的数学哈希。
如果使用实际的哈希函数,重要的是哈希显然不是从ID号派生的。提供像/ feedback / trpxq / 53192这样的URL是没用的,因为在看到其中的一个或两个之后,您可以轻松地拉出以前的记录:/ feedback / trpxp / 53191
我当时正在考虑,如果哈希包含一个盐,那么即使知道使用了什么哈希函数,也不可能散列任何旧的有效订单ID并提出一个有效的网址。
所以,最后,这是实际的问题:
什么函数最适合用来创建一个基于7-10位整数ID和任意盐的哈希的短,非显而易见,相对独特的字母数字表示?
这不是一个URL缩短问题本身,所以如果散列部分与ID部分的长度相同,我会感到满意:减少到10个字母数字字符是可以接受的。
此外,每次访问URL时都不一定需要计算哈希值。无论是在创建订单记录时,还是在首次访问该订单ID的页面时,都可以对其进行计算。这意味着哈希函数不一定非常快。
虽然有可能基本上为查找目的创建哈希表,但是这个问题与哈希表没有相同的限制:查找是基于已经唯一的值完成的,因此冲突解决不是严格必要的对于给定的散列,找到具有相同散列的另一个记录是非常困难的。
我们现在已经完全超出了确保反馈形式需要采取的实际领域 - 这些数据实际上并不重要 - 但是幽默我,这是一个有趣的问题,我想知道是否有一个能够最大限度地提高安全性和可读性的良好解决方案。
答案 0 :(得分:8)
从根本上说,这归结为一个非常简单的情况。
你必须妥协。较大的 n 意味着较小的 p ,但标识符更难打字/复制/记忆。较小的 n 会缩短标识符,但会增加 p 。
如果标识符仅在有限的时间内有效,那么有一件事情会有所帮助。这允许您在不增加 p 的情况下发出大量标识符,因为只有一小部分已发布的标识符实际上同时有效。您的用例可能会也可能不会规定标识符的最小合理生命周期。
在任何情况下,标识符当然应该基于随机数或包括密钥在内的若干事物的加密散列,以便与诸如订单号或序列号/序列号之类的有意义的信息片段没有可辨别的关系。如果你使用哈希并选择 n 小于哈希输出的长度,那么截断哈希是完全可以的。
将标识符编码为URL的最紧凑方式类似于base64。 base64的缺点当然是编码的字符串对人类没有意义。您可以使用各种编码方案,例如生成可发音词或词典中的单词序列。这些对于人类来说可能更难忘,但是对于相同数量的熵,它们实际上要长得多,因此它可能不值得(特别是如果URL通常被点击,复制和粘贴,或扫描为QR码)。