问题

公司规定所有接口都用 post 请求,这是为什么?

回答
公司所有接口都强制使用 POST 请求,这个规定听起来确实有点让人费解,尤其是在我们习惯了 GET 请求的简单明了之后。不过,这背后并非没有考量,甚至可以说是出于一些深思熟虑的安全和设计原则。咱们不妨从几个角度来好好掰扯掰扯。

一、 隐藏敏感信息,提升安全性是首要原因

这是最直观也是最重要的理由。

URL中的信息暴露问题: 我们都知道,GET 请求的参数是直接拼接在 URL 里面的(问号后面那一串 `key=value&key=value`)。这意味着什么?这意味着这些参数会出现在:
浏览器历史记录里: 哪怕用户清除了缓存,但如果浏览器支持记录 URL,敏感信息(比如用户ID、支付金额、甚至token)就这样明晃晃地躺在历史记录里,一旦电脑被别人使用,风险不言而喻。
服务器日志里: веб服务器会记录每一条请求的 URL。这意味着,用户每次提交带有敏感信息的请求,这些信息都会被持久化地保存在服务器日志中。虽然日志本身有权限控制,但万一日志泄露,或者运维人员不当操作,信息暴露的风险就会大大增加。
网络代理/监控工具里: 在一些网络环境复杂的场景下,比如企业内网,可能会有网络代理或监控工具,它们能够捕获并记录所有经过的网络流量。GET 请求的参数因为在 URL 中,极易被这些工具截获和展示。
分享链接里: 想象一下,如果一个用户分享了一个包含用户信息的 URL 给朋友,那后果就不堪设想了。

POST 请求的优势: 相对而言,POST 请求将数据放在请求体(Request Body)中发送。
隐藏性更强: 数据不再直接暴露在 URL 中,浏览器历史记录、服务器日志(至少是URL部分)就不会直接记录这些敏感参数。
安全性提升(相对): 虽然 HTTPS 是保护传输过程中数据安全的关键,但 POST 请求在 URL 层面就做到了信息隐藏,这是一种额外的安全加固。即便 HTTPS 存在配置错误或其他问题, POST 请求的参数也不会轻易被看到。

二、 避免副作用与幂等性的混淆

HTTP 协议本身对 GET 和 POST 有一些语义上的建议,虽然不是强制的硬性规定,但遵循这些原则能够让接口设计更清晰。

GET 的设计初衷: GET 方法被设计用来获取资源,它应该是幂等的,并且不应该有副作用。幂等意味着多次执行同一个 GET 请求,结果应该是相同的,不会改变服务器的状态。例如,获取用户信息就是一个典型的 GET 操作。
POST 的设计初衷: POST 方法则用来提交数据,通常会改变服务器的状态,它不要求幂等。例如,创建订单、提交表单、上传文件都是 POST 的典型应用。

公司规定背后的考量:
明确接口意图: 如果公司强制所有接口都用 POST,那么开发人员在接收到需求时,会更倾向于将操作理解为“提交”或“修改”状态,而不是单纯的“获取”。这强制性地将“修改状态”的操作与“读取状态”的操作区分开来。
减少误用风险: 有时候,一个原本是获取数据的操作,如果被错误地设计成了 GET 请求,但又在内部修改了某些数据(例如,记录日志、更新访问次数),这就违背了 GET 的幂等性和无副作用原则,导致潜在的 bug 和难以追踪的问题。通过强制 POST,这种可能性大大降低。即使内部有副作用,至少从接口设计的层面,我们默认它就是有副作用的,不会再去纠结它是否应该幂等。

三、 处理大数据量的能力

虽然不是最主要的理由,但在某些情况下也会被考虑到。

GET 的限制: HTTP 协议对 GET 请求的 URL 长度并没有严格的限制,但实际应用中,不同的浏览器、服务器和中间件都会对 URL 的长度有一个实际的上限(通常是 2048 个字符左右)。如果需要传递大量数据(例如,批量更新数据),GET 请求会非常吃力,甚至可能失败。
POST 的优势: POST 请求没有这个限制。请求体的大小只受限于服务器配置或协议本身的限制,可以轻松传递大量数据。

四、 API 设计的一致性与可维护性

在一个团队中,尤其是规模较大的团队,保持接口设计的一致性至关重要。

降低学习成本: 所有接口都遵循同一套规则,新入职的开发人员更容易理解和上手。他们不需要去记忆哪些操作应该用 GET,哪些应该用 POST,只需要理解 POST 的用法。
简化开发和测试: 在编写客户端代码或进行接口测试时,只需要熟悉一种请求方式,减少了因选择不同请求方法而引入的潜在错误。测试用例编写也会更简单统一。
更易于工具化支持: 很多 API 管理工具或框架,在生成代码、文档或进行自动化测试时,更容易针对一种固定的请求方式进行优化和支持。

可能的顾虑与进一步说明

当然,这种做法也不是没有代价或潜在的缺点:

缓存问题: GET 请求可以被浏览器和代理服务器缓存,这对于经常访问且不常变动的数据非常有益,可以提升性能。强制 POST 会让这类请求无法利用 HTTP 缓存机制。
应对: 在这种情况下,可能需要在应用层实现自己的缓存策略,或者对某些特定场景进行例外处理。
链接分享不便: 如前所述,GET 请求的参数直接在 URL 中,方便用户分享带有特定参数的链接。强制 POST 会让这种情况变得复杂。
应对: 可以通过生成特定的短链接或通过用户登录后加载的页面来达到类似的效果,但这增加了实现的复杂度。
语义模糊(潜在): 如果过度滥用 POST,并且没有在请求体中清晰地定义操作类型,那么所有的操作都可能变得模糊不清,即使是简单的查询也强制用 POST,可能会让一些开发者觉得不符合 HTTP 的原始设计理念。
应对: 在 POST 请求体中,通常会包含一个 `action` 或 `command` 字段来明确指示要执行的具体操作,以弥补这一可能存在的语义模糊。

总结一下,公司之所以可能坚持所有接口都用 POST 请求,主要是在安全性和统一性之间做了一个权衡。 通过将所有数据传输(尤其是敏感数据)隐藏在请求体中,可以显著提高信息安全性,并强制开发人员更规范地处理具有副作用的操作。虽然这可能在一定程度上牺牲了 HTTP 缓存的便利性和 URL 的直观性,但对于需要高度安全和一致性管理的系统来说,这是一种可以理解的策略。

与其说是一种“不让用 GET”的规定,不如说是一种“强制用 POST 以实现更强的安全性和明确性”的工程实践。在不同的技术栈、不同的安全要求下,会有不同的最佳实践,而这种“全 POST”的模式,就是一种为了特定目标而采取的“工程化”决策。

网友意见

user avatar

只有一个原因,就是为了迁就低水平不思进取的架构师和前后端程序员们。

这问题底下好多津津乐道“这是多年一线开发经验总结出的最佳实践”的人恰好印证了这一点。


看了一下其他答案,全POST的理由大致分两类:

一是反RESTful,用POST替代PUT、DELETE、PATCH等;

姑且还有点道理,REST用Method表达语义其实是很清晰的,但它和传统RPC的思维方式并不直接兼容。而且两者也不是技术上的高低关系,无非是两种接口定义而已。

最怕的就是学个半吊子还简单粗暴硬要上REST,最后弄出个四不像,谁都理解不了。

但有人硬说PUT /api/object看不懂,只能看懂POST /api/updateObject,那只能说你确实该用一个POST包打天下。

如果一个团队有三成的人理解不了REST怎么写login,那还是放弃它吧,免得挖大坑。GET/POST也是很清晰的语法体系啊。


另一种是反GET,理由无外乎url长度和缓存,这就更让人迷惑了。

url长度问题基本都出现在多参数检索中。但是,哪怕用REST语义来分析,复杂检索也本来就该用POST。因为“检索条件-结果”是资源本身而不是一个资源列表,你创建了检索id后可以缓存结果并再次用GET获取。这种原本解决方案十分清晰的问题居然被解释为“GET放不下,我们用POST代替吧”,哭笑不得。

缓存才是不可思议的:无论移动端还是web端都有起码五六种方法来阻止缓存,你可以添加Header,可以在url加时间戳或随机数,可以用Etag,再不济可以手工清除。居然能被这个问题困住而不得不改用POST,莫非只会用浏览器调试API?


全接口POST化绝大部分时候就是为了迁就低水平技术人员。但这种说法有点伤自尊,所以往往会拿“公司统一规定”搪塞。表面显得又标准又规范,实际内里什么样很多人都清楚。

“标准太麻烦,所以堂而皇之地扔掉标准另起炉灶还以此为傲”,这种草台班子心态对一个技术人员的成长是十分有害的。


说到这儿我忽然想起某个强制规定前端一律用div的团队。h1h2h3是div,p是div,label是div,button是div,span是inline的div。语义化是什么?不懂,没用。冠冕堂皇的理由自然是所谓的标准统一好管理不出错。然而为了防止样式混乱,文档里又详细规定了一堆title1、title2、label、btn的class……

user avatar

可能你们公司用了GraphQL吧

user avatar

两种可能:

1、我们现在确定一下,无副作用的查询接口,使用GET请求,有副作用的操作接口,使用POST请求。

老师,那登陆应该用GET咯?

不,登陆一般用POST请求,这是特例,因为登陆通常需要表单提交,而且登陆也不是完全无副作用,blablabla……

哦,那还有哪些特例呢?

…………

……

好,我们确定一下,以后一律用POST接口。


2、对于每个接口,我们都返回一个标准的JSON,其中有一个属性标注是否成功……同时HTTP响应码都为200 OK

哎呀,错误的结果被缓存了……

经研究决定,以后不准用GET请求……

user avatar

作为程序员,应该知道这种问题的准确答案应该去公司的架构师或者技术总监,他们有责任给一个解释,在知乎上问并不是正确的职业做法,知乎上啥人都有,他们的经历是他们的经历,你的公司是你的公司,你去问一个不相干的人你们公司的规定为什么,你不觉得......缘木求鱼吗?

不过,我可以给一些我自己的看法。

如果是在我现在的公司,我不会规定所有接口都是POST,我会按照『业界最佳实践』制定规范,幂等不修改服务器状态的用GET,幂等修改服务器状态的用PUT,不幂等修改服务器状态的用POST。

为啥要用『业界最佳实践』呢?

因为我司都是很牛的程序员啊,按照最科学的方式来做,才显得我们的公司尊重科学啊,按照业界最佳实践做,就是一种开放的姿态,广纳英才,我们的程序员也能够理解这样的规范,何乐而不为。

但是,如果让我去一个程序员水平良莠不齐的创业公司......我估计也会要求所有的接口都用POST请求。

这又是为啥呢?

因为我担心公司里这些打工人理解不了业界最佳实践,你和他们说幂等不修改服务器状态的用GET,幂等修改服务器状态的用PUT,不幂等修改服务器状态的用POST,他么会——

说了你又不听

听了你又不懂

懂了你又不做

做了你又做错

错了你又不认

认了你又不改

改了你又不服

不服你又不说

这样一种情况,我费那劲讲这些『业界最佳实践』的大道理干啥?

我也会简单粗暴用一种最不容易出错的方式,POST不会误用缓存,POST不受URL长度限制,POST能够用来获取也可以用来修改,那就用POST好了!

我不光规定用POST,还要通过工具强制要求用POST,API Server设置成除了POST请求都不接!

有时候就是这样最高效,费口水教育别人,还不如不给他们选择。

这科学吗?

不科学,这样不利于可持续发展,没有给员工犯错机会,所以他们难有成长。

但是话又说回来,有些程序员遇到公司技术规章问题,想到的都不是去问自己公司的架构师和技术总监,却跑到知乎上来问......也的确很难让他们成长。

再说了,员工没有犯错机会,作为创业公司的技术负责人一样没几次犯错机会了,系统搞成一坨浆糊了谁来背锅?

所以,两害取其轻,就这么简单粗暴地规定好了。

还好,我不再在创业公司工作了。

user avatar

因为需要在维护初级技术人员自尊心的同时防止低级bug的出现。

很多初级程序员会选择在传参内容少的时候用GET,传参内容多的时候才使用POST,但这样一来,就会出现一些低级的bug,比如创建留言板发帖时url被缓存,导致重复发帖。

统一用POST,避免了URL缓存,也就避免了这类bug。但语义错误,会让了解语义规则的程序员觉得很不舒服,而且该用GET的地方用了POST,就没有了URL缓存,也就增加了服务器的负载压力。有些公司面试时问着如何处理高负载高并发问题,却连这种小细节都不要求,也确实是一件比较可笑的事情。

但是作为员工,没有必要去指出这一点,因为大多数公司,一千多的云主机就足够用了,压根不需要考虑负载问题。你要求公司修改这个规则,就是在说:“我不是针对谁,我是说在座各位……”

公司里知道语义规则的人应该是不少的,制定这条规则的人,心里应该也是清楚的。大家的目标都只是用最少的消耗去解决问题而已。

然后,题主既然提出了这个问题,应该是知道GET和POST的语义规则的,但是我还是在这里科普一下吧,毕竟这是一个负知识,公司里不敢说,网上总可以说一下的:

GET

  • 安全且幂等
  • 读取服务器内容时使用
  • 变更时获取表示(缓存)

POST

  • 不安全且不幂等
  • 使用服务端管理的(自动产生)的实例号创建资源
  • 创建子资源
  • 部分更新资源
  • 如果没有被修改,则不更新资源(乐观锁)

PUT

  • 不安全但幂等
  • 用客户端管理的实例号创建一个资源
  • 通过替换的方式更新资源
  • 如果未被修改,则更新资源(乐观锁)

DELETE

  • 不安全但幂等
  • 删除资源

HEAD

  • 安全且幂等
  • 递交获取资源的元数据

OPTIONS

  • 安全且幂等
  • 获取信息,关于资源的哪些属性是客户端可以改变的。

PATCH

  • 不安全,可以是不幂等的
  • 局部更新资源
  • 与PUT区别:只更新少部分内容;可能根据原数据进行变化(比如基本工资加200元),这时就不幂等了。

具体可以参见:

类似的话题

本站所有内容均为互联网搜索引擎提供的公开搜索信息,本站不存储任何数据与内容,任何内容与数据均与本站无关,如有需要请联系相关搜索引擎包括但不限于百度google,bing,sogou

© 2025 tinynews.org All Rights Reserved. 百科问答小站 版权所有