【问题标题】:GET vs. POST Best PracticesGET 与 POST 最佳实践
【发布时间】:2009-03-24 19:59:33
【问题描述】:

对于我的 Web 应用程序 (PHP/MYSQL),我会显示一个项目列表,并在每行显示一个链接以删除该项目。现在,链接是

<a href='item.php?id=3&action=delete'>Delete Item</a>

如果我想改用 POST……我该怎么做(这是一个动态生成的列表)?我可以在不使用表单的情况下发送 POST 数据吗?

或者,对于每个项目,我必须这样做:

<form action='item.php?id={$item_id}' method='POST'>
    <input type='hidden' name='action' value='delete'>
    <input type='submit' value='delete item'>
</form>

并将提交按钮的样式设置为看起来像原始链接?

我不熟悉 php CURL 或 REST,他们会帮助解决这个问题吗?

【问题讨论】:

  • 如果您希望人们/搜索引擎仅通过访问链接从数据库中删除内容,请使用 GET,否则使用 POST。
  • stackoverflow.com/questions/46585/… 我的理解是在修改状态的时候应该使用POST。
  • 看,就像我说的,如果这个页面被网络爬虫访问了怎么办。它只会向页面上的每个链接发出 GET。如果你觉得可以,那我也可以。
  • 我知道在这种情况下我应该使用 POST,我的问题是最好的方法是什么。有什么方法可以在不使用 HTML 表单的情况下做到这一点?
  • 不行,您需要使用表单或AJAX (JavaScript) 发出POST。

标签: php html http forms rest


【解决方案1】:

请使用 POST 来修改数据库中的持久状态。您不希望爬虫访问您的删除链接!
阅读 W3C 的 Architecture of the World Wide Web, Volume OneURIs, Addressability, and the use of HTTP GET and POST

编辑:有时您需要使用 GET。例如,通过电子邮件发送的会员激活 URL 是 GET,需要以某种方式修改数据库。

【讨论】:

  • 是的,爬虫无法进行 POST,因此使用这种通过不需要的表单和无用的 javascript 来模拟 POST 的破旧、奇怪的方法,而不是在服务器端进行适当的身份验证,将使这个应用程序安全!哦...
【解决方案2】:

一般来说,以某种方式修改系统状态的 GET 请求不是一个好主意,例如删除项目。

你可以让你的表单看起来像这样:

<form action='item.php' method='POST' id='form'>
    <input type='hidden' name='action' value='delete' />
    <input type='hidden' name='id' value='{item_id}' />
    <a href="" onclick="document.getElementById('form').submit(); return false;">Delete item</a>
</form>

【讨论】:

  • 这是此用例的“最佳实践”方法——提交表单的链接。
  • 如果您不希望页面中有大量表单,您可以使用一个表单并使用 javascript 函数来设置值并提交表单,即 onclick="deleteItem('{item_id }'); 并让函数设置值并调用 form.submit()
  • 谢谢大家,这回答了我的问题。我应该检查@item.php 上的跨站点请求伪造和用户身份验证,对吗?我应该在另一边检查任何其他安全问题吗?
  • 比链接更好的是提交按钮。无需 JavaScript 即可工作,中键单击时不会感到困惑,等等。如果你想让它看起来像一个链接,你可以用 CSS 重新设置它的样式,让它看起来不像一个按钮。
  • 就个人而言,我更喜欢将 a 链接到确认页面。这个页面有一个表单,当 POST'ed 时,它会删除条目并重定向回列表。如果你想离开确认页面,至少使用提交按钮,而不是 标签和javascript。按钮不应看起来像链接。
【解决方案3】:

您不应该通过 GET 请求更改数据库中的任何内容(日志信息或其他临时数据除外)。问题是存在各种网络爬虫软件、网络加速器、防病毒程序等,它们会对他们找到的每个 URL 执行 GET 请求;您不希望他们在这样做时自动删除项目。 GET 也容易受到跨站请求伪造;如果攻击者让您的一个用户点击执行错误操作的链接(例如,创建一个重定向到删除 URL 的 tinyurl),那么他们可以欺骗用户使用他们的权限删除某些内容而没有意识到。

是的,您需要提交一个表单来创建 POST 请求。另一种选择是使用 JavaScript 和 XMLHttpRequest,但这不适用于禁用 JavaScript 的用户。

您还应该确保一旦您接受了来自 POST 请求的数据,而不是返回一个新页面来响应该请求,您应该将用户重定向到由 GET 请求访问的页面。这样,他们不会在点击重新加载或稍后在浏览会话中点击后退按钮时意外地重新发送 POST 请求。

【讨论】:

    【解决方案4】:

    这是一个很好的例子,说明为什么不使用 GET 来更改服务器状态:

    http://www.infoworld.com/article/08/06/16/25FE-stupid-users-part-3-admins_5.html

    关键部分是:

    “它登录到管理区域并点击‘删除’链接 每个条目,”管理员说。

    如果删除被编码为 POST,这将永远不会发生。 (OTOH,我们会被剥夺一个有趣的系统管理员故事。)

    【讨论】:

      【解决方案5】:

      您不想使用 Get,因为 REST 原则不允许 Get 更改系统状态。除非你喜欢搜索引擎删除你所有的内容。

      您不需要为每个项目提供表格;您可以在列表周围使用一种方法=发布表单,并使用 delete_{id} 输入类型=提交。或者,更巧妙的是,。提交按钮上允许使用名称。

      根据您在 cmets 中的问题, 可能会更好,尽管它会遇到一些对本地化网站效果不佳的问题。您始终可以恢复为 HTML 按钮,以便对演示文稿进行更多控制。默认情况下,它就像一个提交按钮。

      当您只是查看列表时,如果您使用建议的“按项目表单”解决方案发回比所需大得多的页面的平均情况,您可能会在提交中获得额外的、不需要的信息这一事实得到缓解.对于支持 javascript 的客户端,您始终可以使用 javascript 将plain-old-html 表单的行为替换为更智能的版本。

      如果您要链接到“Get”以进行删除,您应该返回一个确认页面,其中包含实际在确认后发布的 Get。

      【讨论】:

      • 在每一行中使用“input type=submit”的问题是该值必须是 id...但我希望链接显示“删除”,而不是显示 id。有没有办法解决我忽略的问题?
      • 这与 REST 无关。根据 HTTP 规范,让 GET 产生副作用是完全非法的。
      • 啊,好点子。这很 hacky,但也许:
      • 对我来说,REST 基本上是遵循 HTTP 规范的形式化。
      • 不过,公平地说,REST 并不一定严格要求使用 http。
      【解决方案6】:

      POST 并不能像某些人暗示的那样保护所有恶意行为。恶意用户仍然可以创建链接(包含执行 POST 的 javascript)并导致与 GET 相同的跨站点脚本问题。 ()

      也就是说,使用 POST 而不是 GET 的所有其他原因都适用(爬虫等)。

      【讨论】:

      • POST 不能防止恶意行为。没有什么是。当软件在它找到的每个链接上运行 GET 请求时,POST 将保护您免受非常常见的行为(常规爬虫、网络加速器等)的影响。
      【解决方案7】:

      正如其他人所说,将 GET 用于删除等破坏性操作是一个非常糟糕的主意,尤其是在面向 Internet 的网站(或使用 Google Mini 设备的公司)上,网络爬虫可能会意外删除您的所有数据。

      如果您不想使用表单,请使用 XMLHttpRequest 将 POST 发送到您的服务器。如果您的服务器支持,您甚至可以将方法设置为 DELETE。

      如果您不能使用 JavaScript 和 XHR(您的用户生活在 1999 年),并且您不想在列表中使用表单,请使用指向单独页面的链接,您可以在其中显示表单和可能“你确定吗?”消息。

      最好的办法可能是结合上述两个选项:使用表单呈现指向单独页面的链接,但使用 JavaScript 将链接重写为 XHR 调用。这样,1999 年或 2009 年的用户都可以获得最佳体验。

      【讨论】:

        【解决方案8】:

        您不应该使用 href 来删除项目。

        我建议以老式方式执行此操作,并为每一行/项目实现一个表单发布。

        例如:

        <tr><td>Item 1</td><td><form action=/delete method=post><input type=hidden name=id value=1><input type=submit value=Delete></form></tr>
        <tr><td>Item 2</td><td><form action=/delete method=post><input type=hidden name=id value=2><input type=submit value=Delete></form></tr>
        <tr><td>Item 5</td><td><form action=/delete method=post><input type=hidden name=id value=5><input type=submit value=Delete></form></tr>
        

        另外两个选项: 1)对每个项目使用一个 2)Ajax(但你需要精通Ajax)

        【讨论】:

          【解决方案9】:

          您也可以使用 get,但您需要检查会话值以确保它是试图删除的帖子的所有者。 get 不是“普遍不安全的”。这完全取决于你如何使用它。

          【讨论】:

            【解决方案10】:

            最好还是用 GET 来做。

            如果您的问题是您不喜欢链接的丑陋 URL,您应该可以使用 mod_rewrite 来解决这个问题(如果您使用 Apache 网络服务器)。

            编辑: 没有任何理由在这里使用 POST。没有。原因。

            这里的人写关于安全和不安全的文章,好像选择方法会以任何方式影响安全。当然,无论您选择哪种方法,您都应该验证您的用户。如果您不这样做,那么您的软件已经损坏。如果您在没有有表单、不需要它、根本不需要任何 javascript 的情况下使用 javascript 来模拟发送表单,那么您的软件已经坏了。 p>

            实际上,大约 90% 的网络软件都被破坏了,因为人们不知道自己在做什么。

            忽略这个 cmets 被一些奇怪的人严重贬低。避免 javascript(不需要),避免 POST(没有理由),验证您的用户(安全),使用 mod_rewrite 或其他方式使 href 更漂亮(很好)。

            【讨论】:

            • 使用 GET 打开跨站请求伪造的大门。
            • 这甚至不是一个丑陋的 url,在处理状态时使用 GET 不是一个好主意。
            • 这太错误了,我什至无法想象有人会想出这个……根据 HTTP 规范,GET 有副作用是完全非法的。期间。
            • -1:错误的答案。唯一有用的一点是对您的用户进行身份验证,但这是常识,(不幸的是)并非总是可行
            • @IlyaBirman 7 年多过去了……您仍然认为使用 GET 进行状态修改是个好主意吗? (提示 - 请拒绝)
            猜你喜欢
            • 2015-06-25
            • 2021-05-07
            • 2017-09-12
            • 2011-09-16
            • 1970-01-01
            • 2012-05-23
            • 2021-06-30
            • 2011-03-29
            • 1970-01-01
            相关资源
            最近更新 更多