【问题标题】:What's a good way to "mask" a progressive ID?什么是“掩盖”渐进式 ID 的好方法?
【发布时间】:2020-03-27 10:55:20
【问题描述】:

在我们的 CRM 中,我们有一个 PHP 页面,给定一个 6 位数的发票 ID(例如 314529),从数据库中获取产品行和总计并打印发票。

为了实施一些智能工作措施,我们现在公开了这个发票生成页面,以便我们可以通过电子邮件将发票链接发送给客户,例如https://example.com/get-invoice.php?id=314529

问题是,发票 ID 是累进的,因此任何客户都可以通过增加编号来访问任何其他客户的发票。

我的想法是生成一个随机 UUID 并将其映射到我们数据库中的实际发票编号,这样客户就无法“猜测”其他人的发票。

CREATE TABLE email_invoice (
 public_uuid VARCHAR(128) UNIQUE,
 actual_order_id INT
);

实现此唯一 ID 的有效、安全方法是什么?我应该 MD5 发票 ID 并将其子串,还是依赖 PHP uniqid

【问题讨论】:

  • MySQL 有自己的 UUID 实现,dev.mysql.com/doc/refman/8.0/en/…
  • 人们仍然可以简单地尝试 ID 并获得未经授权的访问。
  • 将附加令牌与所请求的 ID 结合使用 更有意义。令牌被注册并与 id 一起分发给客户。组合允许访问,不匹配的组合被拒绝。这提供了基本的保护。
  • 默默无闻的安全不是安全。客户不需要登录吗?当然,您可以添加一些简单的授权代码来检查用户是否真的拥有所选发票的权限?

标签: php mysql sql security architecture


【解决方案1】:

作为初学者:您应该在应用程序中管理授权层;每个用户在尝试访问存储的数据时都应该经过身份验证并检查访问权限。

话虽如此,在此之上添加一些混淆也不是一件坏事。您的用例看起来是使用 UUID()UUID_SHORT() 的好地方。

这些函数会产生唯一的、不可预测的标识符,这似乎正是您要寻找的。您可以只使用 UUID 列代替主键。

缺点是计算自动递增键的成本更高,并且在insert 查询中没有生成默认值的选项。

create table email_invoice (
    id varchar(36) primary key,
    email_id int,
    invoice_id int
); 

insert into email_invoice(id, email_id, invoice_id) values(uuid(), 1, 2);

Demo on DB Fiddle

编号 | email_id | invoice_id :------------------------------------------------ | --------: | ---------: b86d0d8b-7022-11ea-8095-00163e561f6d | 1 | 2

您还可以创建一个before 触发器,为每个插入分配一个uuid(),因此您无需担心在语句本身中调用该函数。

【讨论】:

    【解决方案2】:

    在 Web 请求中对客户端进行身份验证,并在给出结果之前验证它们是否已通过身份验证。

    您拥有的是insecure direct object reference。有很多方法可以防止这种情况发生。

    建议在开发 CRM 时获得一些网络安全专业知识,因为这是一个相当基本的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      • 2010-09-08
      • 1970-01-01
      • 2014-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多