想象一下,我有一张Customer表。
在这个表中是一个ID列,主键int,Identity,所有爵士乐。我们的客户也有一个名字。
现在,如果我要在报告或电子邮件中发送信息,我的网站中有一个链接可以唯一标识该客户,那么使用主键ID字段是不错的做法?
我所有的直觉告诉我这很可怕,并且代理ID应该仅用于数据库 - 并且绝不会以这种方式暴露给外界。
但我正在寻找将来可以使用的杀手论证,如果(当)提出这个案例。
思想?
答案 0 :(得分:5)
唯一标识符是唯一标识符,如果您已经在数据库表的主键中使用它,请使用它。创建另一个代理键将是多余的,除非您有GUID,例如对于您的输出格式来说太长了。
---编辑----
考虑邮件参考,过去我已经创建了一个表格,该表格跟踪特定邮件以围绕响应构建指标。每个邮件记录都使用GUID作为主键来保持其唯一性,并将该记录链接回客户记录,客户记录中的任何详细信息都不会显示给链接的查看者。
如果您要提供客户详细信息,则需要访问控制,即使您对ID进行模糊处理,任何获取该链接的人都可以访问该数据,并且在大多数系统中都是不可接受的。
我认为这个决定始于'这些数据需要多安全?'然后继续前进。
答案 1 :(得分:4)
我建议不要添加新字段,但也不要公开Id。
创建一个表来存储您发送的电子邮件。包括GUID作为主键,UserId作为外键。在您提供的URL中,链接回GUID。然后,如果用户单击URL,您可以根据GUID更新记录,并指示用户何时访问URL。
答案 2 :(得分:2)
考虑到最终用户可能会发现,如果他们 能够更改网址,则更容易浏览您的网站,因为它们包含可读字符串,而不仅仅是ID。这是一种更为休息的方法。
另一方面,为什么不公开id? 如果您的应用程序仅仅因为有人推理出主键而容易受到攻击,那么您就会遇到问题。
答案 3 :(得分:1)
可以在您使用的表单中使用密钥。但是,在您的特定情况下,存在的问题是网址可以播放,人们可以看到其他人的信息。这取决于该URL的内容是否对您来说是一个问题。如果是,那么我建议您在网址中添加一些盐(第二个数字,一个guid,客户电子邮件哈希等),然后您可以将其与ID匹配以验证URL是否正确。即使使用不是1,2,3的ID而不是使用每个第7个ID ...仍然是可猜测的。另一方面,如果你是如此倾向,你可以只拥有ID ......或整个网址。除非您真的需要,否则您的信息通常不会被外界消耗。在这种情况下,你的直觉是正确的,因为人类不应该使用数据。但是该URL是您系统的一部分,因此实际上只是让信息对于阅读网址的人来说无用。
答案 4 :(得分:1)
您描述它的方式听起来好像用户只需修改链接中的主键值就可以查看其他用户数据。如果是这种情况,为外部目的生成唯一ID(例如GUID)将是更好的方法。
答案 5 :(得分:1)
创建一个名为CustomerNumber
的新字段,该字段在系统中是唯一的,但与ID /主键无关。
编辑:如果您通过电子邮件发送此类信息,请使用某种编码或加密方式,以便随机用户无法猜测其他客户的信息。只要它是独一无二的,关键的来源是什么并不重要。我的第一个建议只是一个用于处理客户的系统的一般建议。
答案 6 :(得分:1)
使用代理键,因为您不希望人们能够猜测(并且使用递增的PK而不是真正猜测)其他人的ID并查看其信息。我建议在客户表中添加一个密钥。
以下是添加新列的示例代码,该列为每条记录生成一个guid。
BEGIN TRANSACTION
GO
ALTER TABLE dbo.Customers ADD
PublicCustomerID uniqueidentifier NULL
GO
ALTER TABLE dbo.Customers ADD CONSTRAINT
DF_Customers_PublicCustomerID DEFAULT newid() FOR PublicCustomerID
GO
ALTER TABLE dbo.Customers SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
代理键也可以很好地用于电子邮件爆炸,为非关键客户信息提供合理数量的保护。但是,如果它非常重要,则需要由身份验证系统保护,而不仅仅是模糊的customerID。但是,如果这是一个销售电子邮件爆炸,如果他们必须单击链接并登录以查看页面而不是仅单击链接
,您将终止转换率答案 7 :(得分:0)
向公众公开普通ID并不是一个好主意。我解决它的方法是加密查询字符串参数。
答案 8 :(得分:0)
我将从这开始。使用代理键作为返回某个数据库对象的链接非常常见。实际上,许多流行的框架都是开箱即用的(ASP MVC,Ruby on Rails,CodeIgniter)。
但是,您可能会考虑使用一些自然键。您也可以尝试Base64编码ID字段。即便是这样的小措施也会有助于阻止某人“探索”您的数据库。
答案 9 :(得分:0)
您可以实现安全机制,而无需用户登录。您不应该仅仅依靠默默无闻来保护这些数据。
要求URL中的ID以及某种密码(随机分配的哈希)可能是所需的全部安全性。
答案 10 :(得分:0)
需要考虑的是在数据库中使用主键和自然键。主键唯一标识表中的行,而自然键唯一标识客户。如果您决定保留客户历史记录,则可以添加具有新主键的新行,但是为客户添加相同的自然键 - 然后在单独的列中标记“已过期”或“当前”行。这经常用于客户维度的数据仓库。在这种情况下,您只会公开自然键,而不是主键。联接仍然发生在主键上。
答案 11 :(得分:0)
反对使用主键的强烈论据是它很容易被黑客攻击,甚至很难被黑客攻击 - 只需通过稍微改变数字来猜测输入。如果用户试图在其他地方手动输入链接,你甚至会无意中将自己暴露在未命中类型中 - 比如他们是否打印出电子邮件给他们的老板然后输入客户B而不是A的代码。 / p>
仅此一项就足够了。至少我会在您发送给用户的代码末尾添加一个校验位 - 通常递归添加数字算法很便宜且有帮助(一点点)。
我自己但是我错了使用生成的GUID。感谢微软和其他许多人,输入36个字符串的概念对于用户来说并不像以前那样令人反感,大多数人只会点击一个链接,而且你手头很简单。保证独特性的功能,以便您将来永远不会绊倒自己。简单而强大。
答案 12 :(得分:-1)
是的,使用像用户名这样的内容而不是外部链接的实际主键更纯粹/更清洁/更好。但是,如果没有要使用的“自然”标识符,则使用主键。只要您使用它来识别行,而不是在其中加入一些语义值,就没有错。
答案 13 :(得分:-3)
暴露PK是一种安全隐患。用户可以进行钓鱼探险,只需尝试一些有趣的按键,看看他们可以通过这种方式看到什么。假设您发送的链接是http://www.example.org/ShowCustomer?id=4711。通过查看此报告,用户仅查找有关客户#4711的信息。竞争对手可以轻松地从1:http://www.example.org/ShowCustomer?id=1开始尝试所有客户ID,从而获得所有客户的列表。那么id = 0呢?或者id = -1?或者像http://www.example.org/ShowCustomer?id=1;DROP%20TABLE%20CUSTOMERS这样的SQL注入?