http 关于get和post

一个电话面试又问到get和post的区别什么的,这次把查到的资料整理一下,不全以后再补充

作者:罗志宇   链接:https://www.zhihu.com/question/31640769/answer/52824098
来源:知乎
著作权归作者所有,转载请联系作者获得授权。


事实上GET 和 POST 在实践上面有非常大的区别,这两种方法在语义上面并非能互相取代。

POST 是否比 GET 安全

是的, POST要比GET安全一点点,注意,是一点点。。。

说这两者都是明文传送当然是没有错的了,但是这里有一个细节,就是GET的URL会被放在浏览器历史和WEB 服务器日志里面。

POST 发完基本就木有了。。

所以如果你把关键数据放在GET里面,被人偷窥了浏览器,或者WEB服务器被入侵日志被人倒去了,基本泄露可能性100%。而POST来说,日志没有记录,只要数据库服务器不被入侵,基本还是安全的。

当然如果被抓了包,这一切都没有什么卵用,所以,HTTPS该用还是得用。

GET 相对 POST 的优势是什么

最大的优势是, GET 的URL可以人肉手输啊。。。你在地址栏打个POST给我看看。本质上面, GET 的所有信息都在URL, 所以很方便的记录下来重复使用。

所以如果你希望
- 请求中的URL可以被手动输入
- 请求中的URL可以被存在书签里,或者历史里,或者快速拨号里面,或者分享给别人。
- 请求中的URL是可以被搜索引擎收录的。
- 带云压缩的浏览器,比如Opera mini/Turbo 2, 只有GET才能在服务器端被预取的。
- 请求中的URL可以被缓存。
请使用GET.

大家有没有注意到,其实这里面很多方面的要求是和网站的运营相关的,而不是技术相关的。任何的技术行为中,其实多多少少都能看到商业的影子。

反之,就用POST. 特别是有一些东西你是不想让人家可以在浏览器地址栏里面可以输入的。比如,如果你设计一个blog系统, 设计这样一个URL来删掉所有帖子。http://myblog.com/?action=delete_all
我只能说很快你就知道什么叫不作死就不会死这个道理了,搜索引擎的爬虫分分钟教你做人。(你有一个get请求用来删除所有东西的,放在了页面上,爬虫也会访问这个get请求,然后你的东西就被删除了。)

另外一个准则是,可以重复的交互,比如取个数据,跳个页面, 用GET.
不可以重复的操作, 比如创建一个条目/修改一条记录, 用POST,因为POST不能被缓存,所以浏览器不会多次提交。

WEB API 的设计相对于网页来说更加复杂,同时也有GET/POST的问题,目前主流接受的方法是RESTful, 参见这里Representational state transfer
这个是趋势:

同时对于何时用GET, W3C 也有一篇文章专门解释:
http://www.w3.org/2001/tag/doc/whenToUseGet.html
摘一点出来:

1.3 Quick Checklist for Choosing HTTP GET or POST

  • Use GET if:类似询问的交互,比如查询,读取,查找等安全的操作
    • The interaction is more like a question (i.e., it is a safe operation such as a query, read operation, or lookup).

and

·        Use POST if: 如果该交互类似指令;交互会改变

o    The interaction is more like an order, or

o    The interaction changes the state of the resource in away that the user would perceive (e.g., a subscription to a service), or o Theuser be held accountable for the results of the interaction.

However, before the final decision to use HTTP GET orPOST, please also consider considerations for sensitive data and practicalconsiderations.

一般建议用post 防止url 被误用导致事故


作者:罗宸   链接:https://www.zhihu.com/question/31640769/answer/52905190

因为它们表达的语义不一样,这决定了主干网络可以对其做不同的处理。

get表达的是一种幂等的,只读的,纯粹的操作,即它除了返回结果不应该会产生其它副作用(如写数据库),因此绝大部分get请求(通常超过90%)都直接被CDN缓存了,这能大大减少web服务器的负担。

而post所表达的语义是非幂等的,有副作用的操作,所以必须交由web服务器处理。

把所有get请求换成post,意味着主干网络上的所有CDN都废掉了,web服务器要处理的请求数量将成百上千倍地增加,显然这不是一个聪明的做法!

-------------------------绕圈子的分割线-----------------------

开发过web服务器的同学都知道,只要请求打到了服务器上,那么要怎么解释这个请求的内容就完全是服务器自己的事情了,只是web服务器开发框架通常会自动帮你做一些解析http请求的事情而已。

所以如果说客户端和服务端都是自己写,那当然很随意,想怎么玩就怎么玩好了,事实上在没有RESTful建议的时候,大家也的确玩得很随意。

实际上问题真正困难的地方在于,网络上每天产生的请求数目庞大,并且其中绝大部分请求均为只读请求,如果所有这些请求都要交由web服务器直接处理,这无疑是巨大的资源浪费。所以大家自然能想到,假如我们能在请求到达web服务器之前,就对请求作一个初步的解析,得知请求的大致意图,对于不同意图的请求以不同方式满足(比如请求经过nginx的时候nginx就会解析请求头信息,然后根据这些信息把请求分配给合适的角色去进一步处理),那么事情就合理多了。

于是RESTful的建议就在这个时候应运而生了,它的出现正是为了解决http基础设施未能得到充分合理利用的问题。

所以我们开发一个服务的时候,选择http协议(而不是直接用tcp),最根本的原因是,我们希望它可以直接和浏览器打交道,可以借用现有的http基础设施,它的行为能被除自己的客户端以外的,网络中的其它角色所理解。 (而不是仅仅靠http解决文本编码问题

这才是我们之所以强调get和post区别,强调“语义”的真正原因。

http规范里说了method有两个特性,一个是是否safe,一个是是否幂等。4个主要方法中只有GET是既safe又幂等的。

 

作者:刘典   链接:https://www.zhihu.com/question/31640769/answer/52950543

HTTP 是应用协议!!!!!!!!不是传输协议!!!!!!!!

如果站在传输协议的角度来看 POST 完全可以代替 GET,会觉得 GET的存在没有必要。如果站在应用协议的角度,任何应用程序都少不了“增删改查”功能,HTTP 协议的方法除了POST、GET外还有 DELETE和PUT,他们刚好是对应的:POST是添加,DELETE是删除,PUT是修改,GET是查询,至于增删改查的具体内容每个应用都不同,但是他们都可以用URL定位,内容在HTTP里叫做“资源”,所以URL叫“统一资源定位符”。RESTful API 正是按照这种方式来定义的,大家都用 HTTP 协议提供 API 不是偶然,而是就是为此而设计的。

post 是创建,put 是更新。post 相当于 add, put 相当于set,其实put也可以创建新资源,比如 put 一个不存在的资源时可以创建这个资源,如果业务规则允许的话,但是新资源的url必须和put操作的url相同,而不是产生一个新的url,因为put操作必须是幂等的


作者:谢照东    链接:https://www.zhihu.com/question/31640769/answer/52782267

先来列举一下get和post的区别

  1. Http Get方法提交的数据大小长度并没有限制,HTTP协议规范没有对URL长度进行限制。这个限制是特定的浏览器服务器对它的限制,众所周知,IE是浏览器里面最烂的,貌似url长度限制也是最短的2083个字符,所以为了让所有的用户都能正常浏览,最好GET的长度不要超过2083字符。POST按照协议来说是没有限制的,但是一般服务器都有限制,比如java使用的tomcat默认限制是2M,可以配置server.xml的一个参数maxPostSize=“0”取消限制
  2. GET请求能够被cache,GET请求能够被保存在浏览器的浏览历史里面(密码等重要数据GET提交,别人查看历史记录,就可以直接看到这些私密数据)。POST不进行缓存(正所谓线上在牛逼,抵不上线下挖掘机是一样的道理)。这就是POST比GET安全的原因吗?那你告诉我HTTPS用来干嘛?(那么HTTPS是否应该废除??)PS:虽然用GET是能够造成CSRF攻击的!
  3. 某些数据只能用POST不能用GET携带,比如file
  4. GET和POST的语义不一样,详情请参考RESTFUl的设计
  5. 多数浏览器(除了firefox)在AJAX中对于POST采用两阶段发送数据的,先发送请求头,再发送请求体。详情请看这篇文章-->YSLOW法则中,为什么yahoo推荐用GET代替POST?(请不要怀疑yahoo前端35条优化法则)还有这篇文章https://josephscott.org/archives/2009/08/xmlhttprequest-xhr-uses-multiple-packets-for-http-post/

看了这些你还觉得get应该被废除吗?存在即合理,所以不要滥用GET的POST!


作者:渚熏   链接:https://www.zhihu.com/question/31640769/answer/54440324

针对有些回答里“post和get在安全性上无区别”,这个说法:
不说别的,就说有些个csrf漏洞,同样都是不带csrf_token
要是个删帖的操作做成get的,那意味着:找个论坛管理员常去的地方外链一堆图片,地址是hxxp://xxxx/del.php?del=1,hxxp://xxxx/del.php?del=2……hxxp://xxxx/del.php?del=9999,等管理员上个黄网的功夫论坛的帖子可能就光了。
改成post起码不会被人这么搞。
所以post在安全上比get稍微好一点是毋庸置疑的。


CSRF(Cross-site request forgery),中文名称:跨站请求伪造  参考:
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html

http://www.freebuf.com/articles/web/55965.html

 

HTTP 方法:GET 对比 POST

  http://www.w3school.com.cn/tags/html_ref_httpmethods.asp  

两种最常用的 HTTP 方法是:GET 和 POST。

什么是 HTTP?

超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信。

HTTP 的工作方式是客户机与服务器之间的请求-应答协议。

web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。

举例:客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。响应包含关于请求的状态信息以及可能被请求的内容。

两种 HTTP 请求方法:GET 和 POST

在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。

  • GET - 从指定的资源请求数据。
  • POST - 向指定的资源提交要被处理的数据

GET 方法

请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的:

/test/demo_form.asp?name1=value1&name2=value2

有关 GET 请求的其他一些注释:

  • GET 请求可被缓存
  • GET 请求保留在浏览器历史记录中
  • GET 请求可被收藏为书签
  • GET 请求不应在处理敏感数据时使用
  • GET 请求有长度限制
  • GET 请求只应当用于取回数据

POST 方法

请注意,查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的:

POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2

有关 POST 请求的其他一些注释:

  • POST 请求不会被缓存
  • POST 请求不会保留在浏览器历史记录中
  • POST 不能被收藏为书签
  • POST 请求对数据长度没有要求

比较 GET 与 POST

下面的表格比较了两种 HTTP 方法:GET 和 POST。

 GETPOST
后退按钮/刷新无害数据会被重新提交(浏览器应该告知用户数据会被重新提交)。
书签可收藏为书签不可收藏为书签
缓存能被缓存不能缓存
编码类型application/x-www-form-urlencodedapplication/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。
历史参数保留在浏览器历史中。参数不会保存在浏览器历史中。
对数据长度的限制是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。无限制。
对数据类型的限制只允许 ASCII 字符。没有限制。也允许二进制数据。
安全性

与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。

在发送密码或其他敏感信息时绝不要使用 GET !

POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。
可见性数据在 URL 中对所有人都是可见的。数据不会显示在 URL 中。

其他 HTTP 请求方法

下面的表格列出了其他一些 HTTP 请求方法:

方法描述
HEAD与 GET 相同,但只返回 HTTP 报头,不返回文档主体。
PUT上传指定的 URI 表示。
DELETE删除指定资源。
OPTIONS返回服务器支持的 HTTP 方法。
CONNECT把请求连接转换到透明的 TCP/IP 通道。

关于HTTP幂等性

http://www.cnblogs.com/weidagang2046/archive/2011/06/04/2063696.html#!comments

理解HTTP幂等性

基于HTTP协议的Web API是时下最为流行的一种分布式服务提供方式。无论是在大型互联网应用还是企业级架构中,我们都见到了越来越多的SOA或RESTful的Web API。为什么Web API如此流行呢?我认为很大程度上应归功于简单有效的HTTP协议。HTTP协议是一种分布式的面向资源的网络应用层协议,无论是服务器端提供Web服务,还是客户端消费Web服务都非常简单。再加上浏览器、Javascript、AJAX、JSON以及HTML5等技术和工具的发展,互联网应用架构设计表现出了从传统的PHP、JSP、ASP.NET等服务器端动态网页向Web API + RIA(富互联网应用)过渡的趋势。Web API专注于提供业务服务,RIA专注于用户界面和交互设计,从此两个领域的分工更加明晰。在这种趋势下,Web API设计将成为服务器端程序员的必修课。然而,正如简单的Java语言并不意味着高质量的Java程序,简单的HTTP协议也不意味着高质量的Web API。要想设计出高质量的Web API,还需要深入理解分布式系统及HTTP协议的特性。

幂等性定义

本文所要探讨的正是HTTP协议涉及到的一种重要性质:幂等性(Idempotence)。在HTTP/1.1规范中幂等性的定义是:

Methods can also have the property of"idempotence" in that (aside from error or expiration issues) theside-effects of N > 0 identical requests is the same as for a singlerequest.

从定义上看,HTTP方法的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性属于语义范畴,正如编译器只能帮助检查语法错误一样,HTTP规范也没有办法通过消息格式等语法手段来定义它,这可能是它不太受到重视的原因之一。但实际上,幂等性是分布式系统设计中十分重要的概念,而HTTP的分布式本质也决定了它在HTTP中具有重要地位。

分布式事务 vs 幂等设计

为什么需要幂等性呢?我们先从一个例子说起,假设有一个从账户取钱的远程API(可以是HTTP的,也可以不是),我们暂时用类函数的方式记为:

bool withdraw(account_id, amount)

withdraw的语义是从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。值得注意的是:和本地环境相比,我们不能轻易假设分布式环境的可靠性。一种典型的情况是withdraw请求已经被服务器端正确处理,但服务器端的返回结果由于网络等原因被掉丢了,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会使用户认为上一次操作失败了,然后刷新页面,这就导致了withdraw被调用两次,账户也被多扣了一次钱。如图1所示:

图1

这个问题的解决方案一是采用分布式事务,通过引入支持分布式事务的中间件来保证withdraw功能的事务性。分布式事务的优点是对于调用者很简单,复杂性都交给了中间件来管理。缺点则是一方面架构太重量级,容易被绑在特定的中间件上,不利于异构系统的集成;另一方面分布式事务虽然能保证事务的ACID性质,而但却无法提供性能和可用性的保证。

另一种更轻量级的解决方案是幂等设计。我们可以通过一些技巧把withdraw变成幂等的,比如:

int create_ticket() 
bool idempotent_withdraw(ticket_id, account_id, amount)

create_ticket的语义是获取一个服务器端生成的唯一的处理号ticket_id,它将用于标识后续的操作。idempotent_withdraw和withdraw的区别在于关联了一个ticket_id,一个ticket_id表示的操作至多只会被处理一次,每次调用都将返回第一次调用时的处理结果。这样,idempotent_withdraw就符合幂等性了,客户端就可以放心地多次调用。

基于幂等性的解决方案中一个完整的取钱流程被分解成了两个步骤:1.调用create_ticket()获取ticket_id;2.调用idempotent_withdraw(ticket_id,account_id, amount)。虽然create_ticket不是幂等的,但在这种设计下,它对系统状态的影响可以忽略,加上idempotent_withdraw是幂等的,所以任何一步由于网络等原因失败或超时,客户端都可以重试,直到获得结果。如图2所示:

图2

和分布式事务相比,幂等设计的优势在于它的轻量级,容易适应异构环境,以及性能和可用性方面。在某些性能要求比较高的应用,幂等设计往往是唯一的选择。

HTTP的幂等性

HTTP协议本身是一种面向资源的应用层协议,但对HTTP协议的使用实际上存在着两种不同的方式:一种是RESTful的,它把HTTP当成应用层协议,比较忠实地遵守了HTTP协议的各种规定;另一种是SOA的,它并没有完全把HTTP当成应用层协议,而是把HTTP协议作为了传输层协议,然后在HTTP之上建立了自己的应用层协议。本文所讨论的HTTP幂等性主要针对RESTful风格的,不过正如上一节所看到的那样,幂等性并不属于特定的协议,它是分布式系统的一种特性;所以,不论是SOA还是RESTful的Web API设计都应该考虑幂等性。下面将介绍HTTP GET、DELETE、PUT、POST四种主要方法的语义和幂等性。

HTTP GET方法用于获取资源,不应有副作用,所以是幂等的。比如:GET http://www.bank.com/account/123456,不会改变资源的状态,不论调用一次还是N次都没有副作用。请注意,这里强调的是一次和N次具有相同的副作用,而不是每次GET的结果相同。GET http://www.news.com/latest-news这个HTTP请求可能会每次得到不同的结果,但它本身并没有产生任何副作用,因而是满足幂等性的。

HTTP DELETE方法用于删除资源,有副作用,但它应该满足幂等性。比如:DELETE http://www.forum.com/article/4231,调用一次和N次对系统产生的副作用是相同的,即删掉id为4231的帖子;因此,调用者可以多次调用或刷新页面而不必担心引起错误。

比较容易混淆的是HTTP POST和PUT。POST和PUT的区别容易被简单地误认为“POST表示创建资源,PUT表示更新资源”;而实际上,二者均可用于创建资源,更为本质的差别是在幂等性方面。在HTTP规范中对POST和PUT是这样定义的:

The POST method is used to request that theorigin server accept the entity enclosed in the request as a new subordinate ofthe resource identified by the Request-URI in the Request-Line ...... If aresource has been created on the origin server, the response SHOULD be 201(Created) and contain an entity which describes the status of the request andrefers to the new resource, and a Location header.

The PUT method requests that the enclosed entity be stored under the suppliedRequest-URI. If the Request-URI refers to an already existing resource, theenclosed entity SHOULD be considered as a modified version of the one residingon the origin server. If the Request-URI does not point to an existingresource, and that URI is capable of being defined as a new resource by therequesting user agent, the origin server can create the resource with that URI.

POST所对应的URI并非创建的资源本身,而是资源的接收者。比如:POSThttp://www.forum.com/articles的语义是在http://www.forum.com/articles下创建一篇帖子,HTTP响应中应包含帖子的创建状态以及帖子的URI。两次相同的POST请求会在服务器端创建两份资源,它们具有不同的URI;所以,POST方法不具备幂等性。而PUT所对应的URI是要创建或更新的资源本身。比如:PUT http://www.forum/articles/4231的语义是创建或更新ID为4231的帖子。对同一URI进行多次PUT的副作用和一次PUT是相同的;因此,PUT方法具有幂等性。

在介绍了几种操作的语义和幂等性之后,我们来看看如何通过Web API的形式实现前面所提到的取款功能。很简单,用POST /tickets来实现create_ticket;用PUT/accounts/account_id/ticket_id&amount=xxx来实现idempotent_withdraw。值得注意的是严格来讲amount参数不应该作为URI的一部分,真正的URI应该是/accounts/account_id/ticket_id,而amount应该放在请求的body中。这种模式可以应用于很多场合,比如:论坛网站中防止意外的重复发帖。

总结

上面简单介绍了幂等性的概念,用幂等设计取代分布式事务的方法,以及HTTP主要方法的语义和幂等性特征。其实,如果要追根溯源,幂等性是数学中的一个概念,表达的是N次变换与1次变换的结果相同,有兴趣的读者可以从Wikipedia上进一步了解。

参考

RFC 2616,Hypertext Transfer Protocol -- HTTP/1.1, Method Definitions
TheImportance of Idempotence
Stackoverflow- PUT vs POST in REST

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值