GET与POST最佳实践

15

对于我的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,它们能帮助解决这个问题吗?


3
如果您希望人们/搜索引擎通过访问链接来从您的数据库中删除内容,请使用GET,否则请使用POST。 - alex
我的理解是,当你要修改状态时,应该使用POST。 - GeekJock
看,就像我说的那样,如果这个页面被网络爬虫访问了怎么办。它只会向页面上的每个链接发出GET请求。如果你没问题,那我也没问题。 - alex
我明白在这种情况下应该使用POST,我的问题是最好的方法是什么。有没有不使用HTML表单的方法? - GeekJock
不,你需要使用表单或AJAX(JavaScript)来发出POST请求。 - alex
10个回答

20

没错,网络爬虫绝对无法进行POST操作,因此使用这种破损、奇怪的方法通过不必要的表单和无用的JavaScript模拟POST,而不是在服务器端进行适当的身份验证,将使该应用程序更加安全!哦... - Ilya Birman

18

通常情况下,不建议使用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>

4
这是这种使用情况的“最佳实践”方法 - 一个提交表单的链接。 - erickson
3
比链接更好的选择是一个提交按钮。它无需JavaScript即可使用,在您中间点击时不会混淆等等。如果您想让它看起来像一个链接,您可以使用CSS重新定义其样式,使其不像一个按钮。 - bobince
2
个人而言,我更喜欢链接到一个确认页面。该页面具有一个表单,当提交时删除条目并重定向回列表。如果您想省略确认页,至少使用提交按钮,而不是带有JavaScript的<a>标签。按钮不应看起来像链接。 - troelskn
troelskn,您的解决方案是最好的。然而,这个答案中给出的解决方案是最差的。 - Ilya Birman
没有启用JavaScript的用户将无法执行删除操作。 - cherouvim
显示剩余4条评论

8
您绝不应该在GET请求中更改数据库中的任何内容(除了日志信息或其他短暂数据)。问题在于,有各种网络爬虫软件、网络加速器、防病毒程序等,它们会对找到的每个URL执行GET请求;您不希望它们在这样做时自动删除项目。GET还容易受到跨站点请求伪造的攻击;如果攻击者让您的用户点击执行恶意操作的链接(例如,创建一个重定向到删除URL的tinyurl),则他们可以欺骗用户使用其权限删除某些东西而不知道。
是的,您需要一个表单提交来创建POST请求。另一个选项是使用JavaScript和XMLHttpRequest,但这对于禁用JavaScript的用户无效。
您还应确保一旦接受了POST请求的数据,而不是在响应该请求时返回新页面,您应将用户重定向到通过GET请求访问的页面。这样,他们就不会在重新加载时意外地重新发送POST请求,或者在浏览会话后期按下后退按钮。

3
您不应该使用Get方法,因为REST原则不允许Get方法改变系统状态。除非您希望搜索引擎删除所有内容。
您不需要为每个项目都创建一个表单;您可以在列表周围使用一个method=post的表单,并添加一个delete_{id}类型为submit的输入框。或者更聪明的是,使用<input type=submit name="delete_item" value="{id}">。提交按钮上允许使用名称。
根据您在评论中提出的问题,<input type=submit name="action_{id}" value="Delete">可能更好一些,但它存在一些问题,对于本地化站点而言效果不佳。您始终可以返回HTML Button以便更精确地控制呈现方式。默认情况下,它的行为类似于提交按钮。
尽管在提交时可能会获得额外的、不必要的信息,但这可以通过平均情况下发送比所需页面大得多的页面来缓解,特别是当您只查看列表时。您始终可以使用JavaScript将普通的HTML表单的行为替换为更智能的版本,以满足支持JavaScript的客户端的需要。
如果您要链接到一个“Get”进行删除操作,您应该返回一个确认页面,该页面在确认后才执行post请求。

在每一行使用“input type = submit”的问题在于值必须是id...但我希望链接显示“删除”,而不是id。我是否忽略了某种解决方法? - GeekJock
这与REST无关。根据HTTP规范,让GET请求具有副作用是明显违法的。 - Jörg W Mittag
啊,好主意。虽然有些不专业,但或许可以这样:<input type="submit" name="action_1" value="删除"> - JasonTrue
对我来说,REST基本上是遵循HTTP规范的正式化。 - JasonTrue
可以通过FTP甚至CORBA实现。另一方面,仅仅因为使用了HTTP并不意味着正在使用REST。事实上,仅仅因为声称使用了REST,并不意味着真正使用了REST。Rails是一个很好的例子:Roy多次解释了为什么Rails不是RESTful的以及如何修复它,但是... - Jörg W Mittag
显示剩余3条评论

3
这是一个不应使用GET改变服务器状态的好例子:

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

重点部分是:

“管理员说:它登录了管理区域,并按照每个条目的‘删除’链接进行了操作。”

如果删除被编码为POST,这种情况就不会发生。(另一方面,我们也会失去一个有趣的系统管理员故事。)

3

POST并不能完全保护免受恶意行为的侵害,正如一些人所暗示的那样。恶意用户仍然可以创建链接(其中包含JavaScript来执行POST),并引起与GET相同的跨站脚本问题。(<a href="javascript:function () {...}"/>)

尽管如此,使用POST而不是GET的其他原因仍然适用(例如爬虫等)。


POST并不能保护免受恶意行为的侵害,没有任何东西可以做到这一点。但是当软件运行GET请求以获取每个链接时,POST将保护您免受非常常见的行为(例如常规爬虫、Web加速器等)的侵害。 - Adam Hawes

0

不应使用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)


0

正如其他人所说,使用GET进行删除等破坏性操作是一个非常糟糕的想法,特别是在面向互联网的网站(或拥有Google Mini设备的公司)上,网络爬虫可能会意外删除所有数据。

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

如果您无法使用JavaScript和XHR(您的用户生活在1999年),并且不想在列表中使用表单,请使用链接到单独的页面,在该页面上显示表单和“您确定吗?”消息。

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


0

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


-12

使用GET仍然是更好的选择。

如果您的问题是不喜欢链接的丑陋URL,您应该能够通过mod_rewrite(如果您使用Apache Web服务器)来解决这个问题。

编辑: 在此处使用POST没有任何理由。没有。理由。

这里的人们谈论安全和不安全,好像选择方法可以以任何方式影响安全性。当然,无论选择什么方法,都应该对用户进行身份验证。如果您不这样做,那么您的软件已经出现了问题。如果您使用JavaScript模拟发送表单时,没有表单,也不需要任何JavaScript,那么您的软件已经出现了问题。

实际上,约90%的Web软件都存在问题,因为人们对自己所做的事情一无所知。

忽略这些奇怪人士的负面评论。避免使用JavaScript(没有必要),避免使用POST(没有理由),对用户进行身份验证(安全),使用mod_rewrite或其他方式使href美观(友好)。


我认为使用POST并不能使应用程序免受跨站请求伪造攻击。 - GeekJock
1
这甚至不是关于丑陋的URL,而是在处理状态时使用GET并不是一个好主意。 - patricksweeney
4
这太不对了,我甚至无法想象有人会想出这个...使GET请求具有副作用在HTTP规范中是明确违法的。没有商量余地。 - Jörg W Mittag
1
-1:糟糕的回答。唯一有用的点是验证您的用户,但这是常识,(不幸的是)并非总是可能的。 - Adam Hawes
1
@IlyaBirman 七年多过去了...你仍然认为使用GET进行状态修改是个好主意吗?(提示-请说不) - Krease
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接