FrankKai / FrankKai.github.io

FE blog

Home Page:https://frankkai.github.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

如何理解HTTP方法的安全性,幂等性和缓存性?

FrankKai opened this issue · comments

在系统性学习OPTIONS请求的过程中,发现在这个请求头的描述信息中,除了reqeust是否有body,成功response是否有body以及是否在HTML forms中允许之外,还有3个没有注意过的HTTP方法的特性:安全性,幂等性和缓存性。

因此,这篇博文将来系统性学习一下这3个重要的HTTP方法的特性。

  • 安全性
  • 幂等性
  • 缓存性

安全性

  • HTTP的安全性是如何定义的?
  • HTTP安全的method有哪些?
  • 安全性与幂等性之间有什么关联?
  • 安全性对于服务器来说有什么好处?
  • 安全的方法仅仅用于获取静态文件吗?
  • 安全性由前端保证还是服务端保证?
  • 安全方法与不安全方法的比较
  • 常见安全方法与不安全方法

HTTP的安全性是如何定义的?

如果一个HTTP method不更改服务器的状态,那么它就是safe的。
换句话说,如果一个method是仅仅执行read-only操作的,那么它就是safe的。

HTTP安全的method有哪些?

以下这些HTTP方法是安全的:GET,HEAD,OPTIONS。

安全性与幂等性之间有什么关联?

所有的安全方法都是幂等的。
但不是所有的幂等方法都是安全的,比如PUT和DELETE是幂等的,但是并不安全。

安全性对于服务器来说有什么好处?

即使安全的方法只是read-only的,但是服务器可以修改他们的状态:打印或者用于统计。
这里最重要的一点是:通过调用安全的方法,client不会不要求任何服务器更改自身,所以不会给服务器创建出没必要的加载或者负担。浏览器调用安全的方法的话,不用担心对服务器造成伤害;这使得浏览器可以无风险的执行pre-fetching
web搜寻器也依赖于调用安全的方法。

安全的方法仅仅用于获取静态文件吗?

安全的方法不仅仅服务static文件。
可用于通知服务器生成安全脚本。(SSR) 一个server可以对一个即时的安全方法生成一个answer,只要生成的script是安全的:它不能出发副作用,例如在电商网站中触发一个订单。

安全性由前端保证还是服务端保证?

安全性由服务端保证,是web服务器(Apache,Nginx或IIS)。
应用程序不允许GET请求更改状态。

安全方法与不安全方法的比较

// 安全方法不改变服务器状态
GET /pageX.html HTTP/1.1
// 不安全方法改变服务器状态
POST /pageX.html HTTP/1.1
// 幂等但是不安全的方法
DELETE /idX/delete HTTP/1.1

常见安全方法与不安全方法

安全方法:GET,HEAD,OPTIONS
不安全方法:PUT,DELETE,POST

幂等性

  • HTTP的幂等性是如何定义的?
  • HTTP幂等的method有哪些?
  • 如何做到HTTP幂等?
  • 幂等方法与非幂等方法的比较
  • 常见幂等方法与非幂等方法

HTTP的幂等性是如何定义的?

如果一个影响完全相同的请求发起一次或多次之后,而服务器的状态一直是保持一致的。那么这个请求就可以叫做幂等的
换句话说,一个幂等方法不能有任何side-effects(除了刷新统计数据)。

HTTP幂等的method有哪些?

HTTP幂等的方法有GET,HEAD,PUT和DELETE,没有POST方法。
所有的安全方法都是幂等的,所以也包括OPTIONS。

如何做到HTTP幂等?

如果想要做到HTTP幂等,只有后端的真正的状态需要被考虑,每个请求的状态码可能会不同:第一个DELETE会返回200,而连续的请求会返回404。
另一个DELETE幂等的意义是开发者不能使用删除最后一个条目的DELETE方法实现RESTful API。
服务器不会保证方法幂等型,有些应用会打破幂等性的约束。

幂等方法与非幂等方法的比较

幂等方法多次调用,返回相同的结果。
非幂等方法调用多次,会导致增加多行。

// 幂等方法:GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
GET /pageX HTTP/1.1
// 非幂等方法:POST /add_row HTTP/1.1
POST /add_row HTTP/1.1
POST /add_row HTTP/1.1 -> 增加第二行
POST /add_row HTTP/1.1 -> 增加第三行
// 非幂等方法:DELETE /idX/delete HTTP/1.1
DELETE /idX/delete HTTP/1.1   -> 200
DELETE /idX/delete HTTP/1.1   -> 404
DELETE /idX/delete HTTP/1.1   ->404

常见幂等方法与非幂等方法

幂等方法:GET,HEAD,PUT,DELETE,OPTIONS,TRACE
非幂等方法:POST,PATCH,CONNECT

缓存性

  • HTTP的缓存性是如何定义的?
  • response被缓存后可以做什么?
  • 所有的HTTP response都可以被缓存吗?
  • 非缓存请求使缓存失效

HTTP的缓存性是如何定义的?

HTTP的缓存性是指:如果一个HTTP response可以被缓存,那么这个响应就是cacheable的。

response被缓存后可以做什么?

response被缓存后,可用于查询和后续使用:比如向服务器发一个新的请求。

所有的HTTP response都可以被缓存吗?

不是。
HTTP response可以被缓存的规则如下:

  • 自缓存方法GET,HEAD可缓存。 请求的方法是自缓存的(self cacheable)的话就可以缓存,例如GET和HEAD方法
  • 新鲜且设置Content-Location头的POST和PATCH可缓存。(不推荐) 如果指示是新鲜的而且Content-Location头有设置(很少有这么实现的),POST或PATCH请求的response同样可以被缓存。(firefox有个bug)
  • PUT和DELETE不能缓存。 PUT或DELETE方法是非可缓存方法,所以结果是不能缓存的。
  • 响应状态码缓存 这些状态码的响应是可缓存的200,203,204,206,300,301,404,405,410,414,501
  • 响应头。 如果响应中没有特殊的类似Cache-Control的请求头,阻止缓存。

非缓存请求使缓存失效

有一些非缓存的请求或响应也许会使相同URI的缓存失效。
例如,一个PUT到pageX.html会使得所有的GET和HEAD请求失效:

GET /pageX.html HTTP/1.1
() 
200 OK
()

PUT请求不能缓存。它会使得对同一个URI的HEAD或GET请求的缓存数据失效:

PUT /pageX.html HTTP/1.1
()
200 OK
()

再次使用GET请求时,在response的header中,Cache-Control的值为:no-cache

GET /pageX.html HTTP/1.1
()

200 OK
Cache-Control: no-cache
()
常见缓存方法和非缓存方法

缓存方法:GET,HEAD
非缓存方法:PUT,DELETE,POST

参考资料:
https://developer.mozilla.org/en-US/docs/Glossary/Safe
https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
https://developer.mozilla.org/en-US/docs/Glossary/Cacheable