URL 路径元素中的标识符是否有任何安全隐患?

Are there any security implications of identifiers in URL path elements?

我正在使用 Devise 实现一个 Rails 应用程序来完成大部分用户身份验证工作。我注意到的一件事是,在为安全敏感任务传递标识符时,它们总是使用查询字符串参数来完成。

例如,发送给用户的密码重置电子邮件中包含的 URL 可能如下所示:

http://example.com/users/password/edit?reset_password_token=_aPKoNpLHm7HYs_o4Qex

Devise 根据 reset_password_token 查找用户并在用户重置表单时更改密码。

我刚刚实现了 Devise 未处理的类似功能。在每封电子邮件中,我都包含一个退订 link。控制器根据唯一令牌查找用户并将其取消订阅标志设置为 true,即使用户未登录也是如此。

然而,我生成的 URL 看起来像这样:

http://example.com/subscription/3e7eb22a268b62d5/edit

基本上,这与 Devise 正在做的事情是一样的。区别在于我在 URL 路径本身而不是查询字符串中包含了令牌。

在我看来,这更像是 RESTful,因为它指向用户随后更新的特定资源(有问题的订阅)(通过将表单发布到 PUT http://example.com/subscription/3e7eb22a268b62d5)。除了这个好处,我看不出这两种方法有什么区别。

有什么原因让我无法在 RESTful URL 上使用查询字符串参数吗?

在 URL 中传递令牌在 RESTful 服务中并不是很好。更好的方法是在请求内容中发送它。也就是说,这个令牌是一次性的,与身份验证并没有真正相关,所以它可能不那么烦人......而且我想这个功能需要从 link (在电子邮件中)不是来自表单提交,这就是为什么使用这样的 URL 参数。

否则,在资源路径 (http://example.com/subscription/3e7eb22a268b62d5/edit) 中诚实地使用操作(元素 edit)名称并不是真正的 RESTful ;-) 事实上,操作是由使用的方法本身。在方法 POST 的情况下,如果您想支持多个操作,我们最终还可以使用额外的提示。

关于方法 PUT 的使用,当您想要更新资源的完整表示时应该使用它。在您的情况下,我认为您更像是方法 POST 的情况,因为您想使用重置密码令牌对订阅执行操作(重置订阅的密码)。这是我在您的案例中看到的请求:

POST http://example.com/subscription/3e7eb22a268b62d5
{
    "reset_password_token": "_aPKoNpLHm7HYs_o4Qex"
}

我为您提供两个 link 可以帮助您设计您的请求:

根据 Craig Walker 的评论进行编辑。

希望对你有帮助, 蒂埃里

Is there something reason I'm missing to use a query string parameter over a RESTful URL?

不是真的。 user a query parameter 和 not 之间唯一真正的区别是一些干预系统可能不会缓存带有查询参数的 URI,因此在这种情况下,在基本 URI 中嵌入标识符是一种解决方法。

也就是说,该论点与您的用例几乎无关。

在高层次上,REST 根本不关心,因为它将 URI 视为一个整体(并且查询参数是 URI 的一部分)。因此,它对此事没有任何建议。两个 URI 都是唯一的 "name the resource",因此 REST 很高兴。

习惯上,在 BASE URI 中嵌入 id 非常流行,它可能与边缘情况缓存场景相关,因此,这是唯一真正支持该形式而不是查询参数的人。

在外观上,许多人更喜欢嵌入式样式。

我会让你权衡这些因素。