使用主键/ ID字段作为URL中的标识符

时间:2009-02-19 20:28:42

标签: security database-design friendly-url

使用数据库主键作为URL标识符有哪些优缺点?例如,http://localhost/post/view/13 - 13是我的帖子表的主键。

像reddit这样的网站使用的是我认为的唯一ID,它不是主键,但仍然是唯一有助于识别链接的ID:

http://www.reddit.com/r/funny/comments/7ynin/the_mystery_of_irelands_worst_driver/

只要/ 7ynin /是相同的,您就可以将URL的最后一部分更改为您想要的任何内容。


Digg似乎使用了一个链接标题的标题来标识一个链接:

http://digg.com/space/Liquid_Water_Recently_Seen_on_Mars

如果我没记错的话,默认的WordPress安装使用index.php?p =#作为他们的ID,直到启用了花哨的网址。


我可以看到为什么对于SEO而言,您希望获得最具信息性的网址,但我只是想看看使用主键是安全风险还是仅仅是糟糕的形式。

6 个答案:

答案 0 :(得分:14)

您总是希望为用户提供一个不错的网址 - 而不是一些讨厌的自动生成的ID。但我不认为你应该说“友好网址”是主键。您仍然应该使用“经典”自动递增的数字PK,并且第二列是唯一的“友好网址”。为什么呢?

  1. 所有评论表,评分 表,无论有哪些表 与您的内容表的关系 可以使用数字主键。 这意味着更小的指数和更低 记忆用法。
  2. 有人会想 更改友好网址。如果你的话 有一个数字主键,你没有 必须更新你的任何依赖 表(或让DB通过 级联更新)。
  3. 将来, 你可以抽象出URL位 进入另一张桌子。说表可以 然后存储“遗留”URL映射 该问题重定向到主要问题 “真正的”URL地图。然后当用户 想要更改友好的URL, 你不必打破所有 入站旧版URL。做不到 这个,如果你的主键是 “友好的网址”。
  4. 我仍然倾向于在我的所有AJAX goo中使用数字主键(例如,post_new_comment()javascript函数将采用主键,而不是一些友好的URL)。我唯一一次使用友好的URL是任何面向用户的URL结构。
  5. 至于安全性?如果您的内容受访问控制,则无论是主键还是友好URL,您都必须检查访问权限。
  6. 如果您允许通过主键访问内容,人们可能会尝试插入随机ID。如果您的要求不仅限制了对内容的访问权限,而且拒绝说内容存在,那么这就是您的错误的措辞问题。它与登录失败相同 - 你不说“找不到用户名”你说“用户名或密码不好”。插入随机值以查找内容对于您采取的任何方法都会成为一个问题,只需使用数字键就可以尝试更少的值。
  7. 底线:友情网址?见鬼,是的。用它们作为主键?没有。

答案 1 :(得分:2)

它本身并不存在安全风险,但它确实告诉外部实体有关您系统的事情,这通常是一种避免的好习惯。

答案 2 :(得分:2)

正如您所说,将标题直接放在URL中的重点是SEO。在网址中包含关键字会对搜索引擎结果产生重大影响。

然而,还有一些与你的例子有关的想法:

  • 我不确定为什么你认为reddit字母数字键不是主键,没有什么能强迫主键是数字的。如果它是帖子的唯一标识符,则没有理由不将其用作主键(或至少部分主键)。
  • Digg实际上强制执行标题的唯一性(可能只是在特定类别中,我多年没有去过Digg,所以我不记得了)。我曾经常常看到这个有重复故事的故事,其中包含以下网址:

    http://digg.com/space/Liquid_Water_Recently_Seen_on_Mars_2
    

    这意味着标题至少是主键的一部分,因为这是确定链接打算针对哪个故事的唯一方法。

使用URL中的主键并没有任何明显的安全风险,除了人们猜测/预测其他人的能力,如pantulis所提到的。但是你不应该依赖“没人会猜这个”作为安全措施。

答案 3 :(得分:2)

如果您在URL /链接中包含主键,那么您必须制作某种临时合成键,然后,您必须保存映射在用户的会话中的那个键。这会增加更多的状态/内存使用/某些内容以破坏您的应用程序。

如果该值真正敏感,则此可能值得隐藏它的成本。然而,模糊密钥并不能真正使其安全,是吗?在授予对项目的访问权限之前,您需要在任何“控制器”(servlet,代码隐藏,等等)中检查用户角色。

答案 4 :(得分:1)

con:任何访问者都可以轻松尝试猜测其他ID,这可能不是您想要的。

答案 5 :(得分:1)

Reddit也使用数字ID,但使用Base 36进行转换,因此它显示为字符串。它就像十六进制数,实际上也是一个字符串。唯一的区别是基数。

Base 36是“使用ASCII字符的最紧凑的不区分大小写的字母数字系统”,它易于编码和解码。为什么36? A-Z = 26 + 0-9 = 10.