繁体   English   中英

在数据库表中有两个唯一ID的坏主意?

[英]Bad idea to have two unique IDs in database table?

我希望允许用户通过URL跟踪我的数据库中的记录。

我猜这个URL不是一个好主意,其中要查看的记录的标识符是记录自动增量ID!

http://www.example.com/$db_record_id

以上是不必要的信息。 这是真的吗? 不会为每一行创建自己的ID会造成同样的问题吗?

有没有更好的方法来解决我的问题。

环境:灯(PHP)

谢谢大家

你发出两条信息:

  • 容易预测的记录网址
  • 很容易找出总共有多少记录

这些是你的应用程序的问题,然后使用其他东西

您可以将GUID用于Db键,但这可能会对大型数据集产生潜在的性能影响。

将记录的ID放在URL中通常不是问题。 例如,查看此浏览器窗口的URL,您将看到此问题的ID。

如果由于某种原因不希望id清晰可见,您可以对值进行加扰或加密。 如果您需要保护某些记录不被查看,这当然不是一种安全的方法,那么您必须将其与某种身份验证相结合,例如登录用户的会话ID。

编辑:
为了保证适当的安全性,必须关注真正的问题。 如果某些页面应该限制访问,问题不是任何人都可以找到页面的URL,问题是任何人都可以查看该页面。 URL总是可以通过某种方式获得(例如包嗅探),因此必须以其他方式实现安全性。

您提供的信息太少,无法获得真正有用​​的答案。

  • 如何生成URL?
  • 软件如何查找要显示的记录?

也就是说,我同意公开这样的ID是有问题的。 commmon解决方案是每次向数据库查询一组记录时生成临时ID,并在内部存储tempID-> real ID。 然后将这些临时ID放入URL中,并在服务器上进行翻译。

该方法的一个可能问题是,通过顺序递增URL中的ID,某人很容易检索所有页面/记录。 这可能不是您想要的,但是您不应该依赖于使用模糊的URL来保证安全性。

其他一些选择是:

  • 在每一行上生成一个随机哈希(虽然这将是一个讨厌的无意义的URL)
  • 为每一行生成一个'slug'(例如'bad-idea-to-two-unique-id-in')。 您需要明确确保这是唯一的,例如通过添加其他内容。

如果我是你,我会在你的表上使用一个整数主键(自动识别码),并在其上添加一个带有唯一约束和索引的GUID,默认为UUID()

然后装备您的页面以获取URL上的GUID并使用它来搜索您的表。

也许您应该公开另一个唯一标识符,例如标题而不是主键? 公开您的PK不一定会带来安全风险,但如果您可以公开其他属性,您可能会在搜索结果上获得更高的价格。

用户请求中的主键本身不容易受到攻击。 只需将其转换为整数值即可

$id = (int)$id;

另一个问题是限制一些记录访问。 您可以通过简单编辑查询来解决此问题,并添加一些访问规则。 例如,如果您有admin / editor / reader / guest类型的用户,则可以在SET字段中保存访问权限并将查询条件添加到查询中

SELECT ... 
FROM mytable 
WHERE 
    id = (int)$id 
    AND 
    (FIND_IN_SET('admin', access) OR FIND_IN_SET('editor', access))

...
if (!$fetch = mysql_fetch_acssoc($res))
    throw new Exception('Record not found or you have no permission to access it');

因此,不要担心主键 - 如果您不忘记将它们转换为整数以避免SQL注入,它们是非常安全的。

这不是一个好主意,因为它已经被说过了(你几乎暴露了表中的每一行),我认为没有必要。

我认为用户将在某个场景(从列表或其他任何内容中选择一个元素)后到达该页面,因此您将有一个页面提交和一个控制器(如果您尝试使用MVC架构)将处理任何需要处理,它将发送到一个查看页面,该页面可能只是一个www.yoursite.com/displayElement.htm

通过这种方式,ID只是作为会话变量传递,不会在任何地方显示。

但是如果我弄错了你正在显示某种目录,那么你希望用户能够为页面添加书签,而不是只需要添加一些混淆机制来创建一个基于ID的复杂字符串,在将ID发送到URL并在代码中解码之前对其进行编码以获得实际ID。

如果用户无论如何都可以观看该页面,我发现使用该ID没有问题。 如果他们想要乐趣更改网址并转到随机页面,我会毫无疑问。

如果任何人都不看这些页面,我实际上仍然没有问题。 因为如果是这种情况,你应该进行一些授权检查,这会阻止他们看到他们不被允许看到的页面。

您所描述的是称为直接对象引用的漏洞。 这些本质上并不坏,但不安全的直接对象引用在OWASP前十名中是#4。

您可以通过检查属于当前用户的对象来保护直接对象引用,如果不存在则不显示它。

此外,即使访问被拒绝的消息也可能泄露信息。 例如,如果您的参数是订单号,则攻击者可以发现您的公司实际拥有的订单数量,即使您没有显示它们,只需增加数量直到获得404即可。

我个人只是使​​用GUID作为间接对象引用的一种形式,但显然不是数据库中的主键。

威胁级别取决于范围和受众:

  1. 这是一个内部crud应用程序? 如果是这样,您可能不需要担心它。
  2. 这是公开的信息(如推特帖子)吗? 同样,您可能不需要担心它。 实际上,可预测的URL可能是链接的理想选择。
  3. 您的身份验证用户可以修改任何记录或查看他们不应该的内容吗? 您可以通过实施所有权系统来降低此风险。
  4. 它可以导致1次点击操作或XSS漏洞吗? 如果可以的话,你做错了。

一般来说,我赞成可预测的URL。 话虽如此,重要的是要考虑如何使用它们以及谁可以看到它们。

如果你想确保人们不只是猜测URL,那么这是一个简单的方法。 这绝不是安全的 (即不要使用此方法进行访问检查),但它将确保您不能只输入随机URL并将sendt发送到该页面。

使用网址中的另一条信息补充ID。 我建议使用id的盐腌哈希。

生成网址时:

$id = 5;
$hash = md5($id . "MY_SALT_VALUE");
$url = "/$id/$hash";

并在显示记录时:

$params = explode(',', $_SERVER['REQUEST_URL']);
$id = $params[0];
$hash = $params[1];
if($hash != md5($id ."MY_SALT_VALUE")) {
    die('Uh oh! You guessed the URL, didn\'t you! Bad user!');
}
$data = $MyModel->load($id);
if(!$data) {
    die('No such record');
}
DisplayModel($data);

当然,这是一个模型(在错误消息中说太多,只是die()而不是正确的404页面,依此类推)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM