【问题标题】:Hide autoincrement ids in GET parameter (PHP)在 GET 参数中隐藏自动增量 ID (PHP)
【发布时间】:2009-09-15 11:19:49
【问题描述】:

编辑:我已经找到并发布了一个高效而优雅的解决方案,可以将3141592 之类的 ID 转换为vJST 之类的字符串并向后转换。它在此处可用于 PHP:

https://github.com/delight-im/PHP-IDs

提供一些背景知识,它使用 Knuth 的乘法散列,然后进行基本转换来生成唯一、可逆、非顺序的 ID。

问题:

我在 PHP 中有动态页面,其中的内容根据给定的 id 显示。 id 总是通过 GET 参数提交:page.php?id=X 这会导致一个问题:站点访问者可以枚举 id 并简单地浏览所有不同的内容页面。当然,这应该是不可能的。

如何解决?

我的方法是对链接和表单中的所有 id 进行编码,稍后用作 GET 参数。在每一页的开头,给定的 id 被解码为数据库中使用的“真实”id。这是一个好方法吗?你会选择其他方式吗?

我的方法的可能解决方案:

我会将整数 id 转换为以 38 为基数的整数,并用给定列表的字符替换数字。我会将这些字符用于编码的字符串 id:

a-z 0-9 - _

你也会使用其他角色吗?对于这些角色,我的脚本是这样的:

function id2secure($old_number) {
    $alphabet_en = array(0=>'1', 1=>'3', 2=>'5', 3=>'7', 4=>'9', 5=>'0', 6=>'2', 7=>'4', 8=>'6', 9=>'8', 10=>'a', 11=>'c', 12=>'e', 13=>'g', 14=>'i', 15=>'k', 16=>'m', 17=>'o', 18=>'q', 19=>'s', 20=>'u', 21=>'w', 22=>'y', 23=>'b', 24=>'d', 25=>'f', 26=>'h', 27=>'j', 28=>'l', 29=>'n', 30=>'p', 31=>'r', 32=>'t', 33=>'v', 34=>'x', 35=>'z', 36=>'-', 37=>'_');
    $new_number = '';
    while ($old_number > 0) {
        $rest = $old_number%38;
        if (!isset($alphabet_en[$rest])) { return FALSE; }
        $new_number .= $alphabet_en[$rest];
        $old_number = floor($old_number/38);
    }
    $new_number = strrev($new_number);
    return $new_number;
}

其他问题:

我的函数的反向函数是什么?

我希望你能帮助我。谢谢!

【问题讨论】:

  • 您可以使用字符串'1…_' 来缩短您的数组构造array(0=>'1', …, 37=>'_')。然后您只需将!isset($alphabet_en[$rest]) 替换为$rest >= 38,它就可以像您一样工作。
  • “这当然不可能。”除非不允许用户访问这些页面,否则我会提出完全相反的观点。有能力的用户应该能够以他们认为合适的任何方式浏览网站。
  • @Gumbo:非常感谢,好主意。这应该更快吧?
  • 一个“枚举”究竟是怎样的?
  • 为什么不直接使用php原生base64编码/解码函数?

标签: php security encryption parameters get


【解决方案1】:

用户可以通过网站访问页面吗?如果答案是肯定的,那么你应该问问自己这是否真的是一个问题。

如果不是,那么问题在于您没有保护您的页面,或者换句话说:您依赖于默默无闻的安全性,这绝不是一个好的举措。

我的建议?要么保护您的页面,以便只有正确的用户可以访问它们,要么不用担心。

如果您真的必须担心它,只需传递一个对于给定页面必须正确的额外字段。我不会从 ID 构造这个。当您在数据库中创建页面条目时,可能会生成另一个数字或 GUID。如果两个字段都不正确,则不显示该页面。

忘记简单的字符替换和其他幼稚的混淆技术。他们是在浪费你的时间。

编辑:如果您需要长度相同的非顺序 ID,请考虑使用 UUID 而不是自动递增主键。基本上这是在应用程序级别完成的:

  • 将主键更改为 char(36);
  • 在您的插入语句中,您必须设置密钥并使用 MySQL UUID() 函数填充它。

看看To UUID or not to UUID ?UUID as a primary key。这会导致性能下降(特别是因为您使用字符而不是整数进行查找),但除非您有大量(超过 100 万行)或数据,否则在实践中可能不会成为问题。

【讨论】:

  • 现在,每个页面都是独立的。但我认为如果每个 id 都具有相同的长度会更好看。 :D 并且用户不知道我的网站有多少用户以及哪个用户是第一个等等。
  • 您可以通过使用 GUID 作为 ID 而不是自动增量字段来实现这两件事。
  • 你想到像“936DA01F-9ABD-4d9d-80C7-02AF85C822A8”这样的东西吗?我应该如何创建它?
【解决方案2】:

使用checksum algorithm like Luhn

$id = 1337;

$_GET['id'] = Luhn($id, 3); // 1337518, adds 3 checkdigits
$_GET['id'] = Luhn_Verify($_GET['id'], 3); // 1337, returns the original number of false if validation fails

echo $_GET['id']; // 1337

编辑:我忘了提,但是通过使用这种方法,您可以检查 ID 是否有效,甚至不必查询数据库,例如:

$id = Luhn_Verify($_GET['id'], 3);

if ($id === false)
{
    // someone is trying to guess the ID
}

else
{
    // $id is valid, do the DB stuff here
}

【讨论】:

  • 碰撞怎么样,有可能吗?
  • 如果您总是使用相同数量的迭代(在我的示例 3 中),则不会。
【解决方案3】:

您仍然可以按顺序浏览您的页面,但猜测模式会更困难。只要根模式是连续的,您最终就会遇到问题(假设它实际上是一个问题,而不仅仅是您不喜欢的想法)。

您可以使用随机数作为 ID。这将防止对页面 ID 和页面顺序的轻松猜测(再次强调,如果这很重要的话)。

【讨论】:

  • 但是随机数我会有很多冲突,不是吗?
  • 这取决于您计划拥有多少页,以及现在用于存储的许多大数据类型。同样,这取决于您的系统和目标。
【解决方案4】:

您还可以使用Hashids 对您的 ID 进行编码/解码。

编写此代码的目的是将创建的 ID 放置在可见的位置 - 例如 URL。

Hashids 是一个小型开源库,可根据数字生成短的、唯一的、非连续的 id。
它将诸如 347 之类的数字转换为诸如“yr8”之类的字符串,或将诸如 [27, 986] 之类的数字数组转换为“3kTMd”。
您还可以将这些 id 解码回来。这对于将多个参数捆绑到一个或仅将它们用作短 UID 很有用。

【讨论】:

    【解决方案5】:

    我不会为这个“问题”而烦恼,但无论如何我在我的一个项目中使用了这样的方法:

    将新页面保存到数据库后,我生成了md5 of (record_id + page_title)并将其放入特殊字段pagecode。然后我通过该页面代码而不是 id 访问页面。并且最好在数据库中索引pagecode字段。

    【讨论】:

    • 在这里的另一个问题中,他们告诉我 md5 哈希不是足够的主键。我宁愿使用整数,因为它更快且碰撞风险更小。
    • 哈希不是主键,只是索引。
    • 但是 ID 应该是主键,因为它也应该是唯一的,不是吗?
    • ID 是一个自动递增的主键。哈希只是唯一的键。我在这里没有看到问题,该站点已经运行了两年。注册用户通过 id 访问这些页面,并通过页面代码匿名访问。
    【解决方案6】:

    网站访问者可以枚举 ID 并简单地走过所有 不同的内容页面。这 当然,这应该是不可能的。

    我不知道为什么这会是个问题 - 人们只需在 Google 中输入site:domain.com 即可查看网站上所有(公共、Googlebot 索引的)页面的列表,并在他们愿意时循环浏览它们.更改您使用的唯一索引不会改变这一点。

    但如果您真的不希望访问者直接访问您的页面,一个简单的快速解决方法是使用 POST 而不是 GET。

    【讨论】:

    • 但如果我使用 post 需要执行操作才能显示正确的内容,对吗?
    • 是的,它本质上意味着将每个链接更改为一个表单,并为每个链接使用 ,并为不运行 javascript 的任何人使用适当的
    • 但是它不适用于没有 javascript 的用户(即使只有 1%)。并且:这不是表格的用途,对吧?
    • 如果您在
    • 哇哦 - 将所有链接更改为使用 javascript 提交 POST 变量的表单?这……太可怕了。再见可用性、可访问性、搜索引擎优化、书签能力、刷新页面的能力、没有烦人的消息等等……
    猜你喜欢
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    • 2016-06-03
    • 1970-01-01
    • 2016-12-02
    • 2016-08-23
    • 2018-04-11
    相关资源
    最近更新 更多