本文正在参与 “网络协议必知必会”征文活动。
想了解HTTP的话可以去这里网络协议 HTTP篇。
想了解HTTPS的话可以去这里网络协议 安全篇。
Cookie
Cookie是一小块存储在客户端的信息「只有4kb」,它发明的原因是需要解决http无状态的问题,这样后台可以根据cookie来记录登陆的状态,但是cookie的安全问题,将会慢慢被舍弃使用,不过还有很多网站还在继续使用,比如www.baidu.com 就有特别多的cookie。
Cookie 主要用于以下三个方面:
- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)
Cookie的使用
响应头:Set-Cookie:name=value
请求头:Cookie:name=value
JavaScript访问方式:document.cookie
可以设置的字段:过期时间、域、路径、有效期、适用站点
过期时间
会话cookie是不需要设置过期时间,当页面关闭cookie则会删掉。
持久cookie是需要设置过期时间的,可以通过 Expires、Max-age来设置。
Expires
为 Cookie 的删除设置一个过期的日期Max-age
设置一个 Cookie 将要过期的秒数- IE 浏览器(ie6、ie7 和 ie8) 不支持
max-age
,所有的浏览器都支持expires
Set-Cookie: id=123; Expires=Fri Sep 03 2021 16:56:41 GMT
Cookie:id=123; Expires=Fri Sep 03 2021 16:56:41 GMT
Cookie 的作用域
Domain
和 Path
标识定义了Cookie的作用域: 即允许 Cookie 应该发送给哪些URL。
域(domain)
Domain
指定了哪些主机可以接受 Cookie。如果不指定,默认为origin,不包含子域名。如果指定了Domain
,则一般包含子域名。因此,指定 Domain
比省略它的限制要少。所以,当子域需要共享有关用户的信息时,这可能会有所帮助。
Set-Cookie:Domain=developer.mozilla.org
Cookie:Domain=developer.mozilla.org
路径(path)
Path
标识指定了主机下的哪些路径可以接受 Cookie,子路径也会被匹配。
例如,设置 Path=/docs
,则以下地址都会匹配:
/docs
/docs/Web/
/docs/Web/HTTP
Set-Cookie:Path=/docs
Cookie:Path=/docs
适用站点(Samesite Cookie)
为了从源头上解决这个问题,Google起草了一份草案来改进HTTP协议,那就是为Set-Cookie响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cookie只能作为第一方Cookie,不能作为第三方Cookie,Samesite 有三个属性值,分别是 Strict 和 Lax,None下面分别讲解:
Samesite=Strict
这种称为严格模式,表明这个 Cookie 在任何情况下都不可能作为第三方 Cookie,绝无例外。比如说 b.com 设置了如下 Cookie:
我们在 a.com 下发起对 b.com 的任意请求,foo 这个 Cookie 都不会被包含在 Cookie 请求头中,但 bar 会。举个实际的例子就是,假如淘宝网站用来识别用户登录与否的 Cookie 被设置成了 Samesite=Strict,那么用户从百度搜索页面甚至天猫页面的链接点击进入淘宝后,淘宝都不会是登录状态,因为淘宝的服务器不会接受到那个 Cookie,其它网站发起的对淘宝的任意请求都不会带上那个 Cookie。
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3
Samesite=Lax 这种称为宽松模式,比 Strict 放宽了点限制:假如这个请求是这种请求(改变了当前页面或者打开了新页面)且同时是个GET请求,则这个Cookie可以作为第三方Cookie。比如说 b.com设置了如下Cookie:
Set-Cookie: foo=1; Samesite=Strict
Set-Cookie: bar=2; Samesite=Lax
Set-Cookie: baz=3
当用户从 a.com 点击链接进入 b.com 时,foo 这个 Cookie 不会被包含在 Cookie 请求头中,但 bar 和 baz 会,也就是说用户在不同网站之间通过链接跳转是不受影响了。但假如这个请求是从 a.com 发起的对 b.com 的异步请求,或者页面跳转是通过表单的 post 提交触发的,则bar也不会发送。
我们应该如何使用SamesiteCookie 如果SamesiteCookie被设置为Strict,浏览器在任何跨域请求中都不会携带Cookie,新标签重新打开也不携带,所以说CSRF攻击基本没有机会。
而且跳转子域名或者是新标签重新打开刚登陆的网站,之前的Cookie都不会存在。尤其是有登录的网站,那么我们新打开一个标签进入,或者跳转到子域名的网站,都需要重新登录。对于用户来讲,可能体验不会很好。
如果SamesiteCookie被设置为Lax,那么其他网站通过页面跳转过来的时候可以使用Cookie,可以保障外域连接打开页面时用户的登录状态。但相应的,其安全性也比较低。
总之,SamesiteCookie是一个可能替代同源验证的方案,但是需要合理使用Strict Lax。
安全
使用 HttpOnly
属性可防止通过 JavaScript 访问 cookie 值。
使用 Secure
的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。
但是这两个属性对于安全的防范用处并不大,HttpOnly确实使用不了cookie,但是开发者需要使用cookie的时候会带来极大的不便。
Set-Cookie:Secure; HttpOnly
Cookie的优缺点
优点
- 存储数据量小,这是在场景上的问题,简单轻量。
- 数据持久性,不需要任何服务器资源,因为cookie是存储在客户端并发送给服务器读取,比如可以记住用户的行为,如设置过的主题。
缺点
1.存储数据量小,这是在场景上的问题,只有4kb,不适合存储大的数据。
2.性能问题,每当发送请求的时候,都会将cookie带上请求头,将会浪费带宽,可以通过domain path来设置。
3.安全问题,cookie是很容易被利用的,如xss攻击。
请求方法
请求方法是http获取资源的方式,但是不同方法获取不同的资源,使语义更加明确,
restful架构设计是不同的资源或者操作「增删改查」,是需要相关语义去使用,更加明确。
但是有些公司是不用的,只有post请求走天下,哈哈。
总之,用与不用看公司的技术架构决定,用有用的好处,不用有不用的方便。
GET
GET方法请求一个指定资源的表示形式,使用GET的请求应该只被用于获取数据。
比如图片、JavaScript、CSS、还有登录图形验证码。
HEAD
HEAD方法 请求资源的头部信息, 并且这些头部与 GET 请求时返回的一致.,该请求方法的一个使用场景是在下载一个大文件前先获取其大小再决定是否要下载, 以此可以节约带宽资源,并且是没有响应体的。
可以总结为是一个没有响应体GET请求。
POST
POST方法用于将实体提交到指定的资源,通常导致在服务器上的状态变化或副作用。
应用最广,而且一些不使用restful架构的,基本全部使用post请求。
PUT
PUT方法用请求提交参数替换目标资源的请求。
相当于更新操作。
DELETE
DELETE方法删除指定的资源。
相当于删除操作。
CONNECT
CONNECT方法建立一个到由目标资源标识的服务器的隧道。
OPTIONS
OPTIONS方法用于描述目标资源的所支持的通信选项。
TRACE
TRACE方法沿着到目标资源的路径执行一个消息环回测试。
其实我们会在项目开发中发现 trace请求会经常自动发的
PATCH
PATCH方法用于对资源应用部分修改,不同于PUT全部覆盖修改。
头部
包含请求头和响应头。
请求头:是客户端传给服务端的信息,用来给服务端判断客户端的身体或者登录状态等等
响应头:是服务端传递给客户端的信息,用来给客户端判断的返回信息等等
无论是请求头,响应头都是可以自定义的,key:value,其中key不区分大小写
比如请求头token:xxxyyy
因为字段太多了,请参考所有的头部字段
请求头字段
Name | Description | Example |
---|---|---|
Accept | 响应可接受的媒体类型 | Accept: text/html |
Accept-Charset | 可接受的字符类型 | Accept-Charset: utf-8 |
Accept-Encoding | 支持的文件压缩方式 | Accept-Encoding: gzip, deflate |
Accept-Language | 接受那种语言 | Accept-Language: zh-CN |
Access-Control-Request-Method, Access-Control-Request-Headers | 在非同源策略下面设置接受请求方式,和请求头 | Access-Control-Request-Method: GET |
Cache-Control | 用于设置缓存策略 | Cache-Control: no-cache |
Connection | 设置长连接,不能在http2.0中使用 | Connection: keep-alive |
Content-Encoding | 用来告知客户端应该怎样解码才能获取在 Content-Type 中标示的媒体类型内容。 | Content-Encoding: gzip |
Content-Length | 用来指明发送给接收方的消息主体(请求体)的大小 | Content-Length: 348 |
Content-Type | 设置请求体的类型 | Content-Type: application/x-www-form-urlencoded |
Cookie | 服务端通过Set-Cookie设置字段保存在客户端 | Cookie: $Version=1; Skin=new; |
Expect | 表示客户端需要特定的服务器行为 | Expect: 100-continue |
Forwarded | 客户端通过HTTP代理连接到Web服务器的原始信息 | Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43 Forwarded: for=192.0.2.43, for=198.51.100.17 |
Host | 服务器的域名(用于虚拟主机),以及服务器正在侦听的 TCP 端口号。 如果端口是所请求服务的标准端口,则可以省略端口号。从 HTTP/1.1 开始是必需的。 如果请求是直接在 HTTP/2 中生成的,则不应使用它。 | Host: en.wikipedia.org:8080``Host: en.wikipedia.org |
If-Match(http1.1) | 仅当客户端提供的实体与服务器上的同一实体匹配时才执行该操作。 这主要用于像 PUT 这样的方法只更新自用户上次更新以来没有修改过的资源。 | If-Match: "737060cd8c284d8af7ad3082f209582d" |
If-Modified-Since | 如果资源没有改变过,则返回304,走协商缓存。 | If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
If-None-Match | 如果资源没有改变过,则返回304 | If-None-Match: "737060cd8c284d8af7ad3082f209582d" |
Origin | 请求首部字段 Origin 指示了请求来自于哪个站点。该字段仅指示服务器名称,并不包含任何路径信息。该首部用于 CORS 请求或者 POST 请求。除了不包含路径信息,该字段与 Referer 首部字段相似。 | Origin: http://www.example-social-network.com |
Range | 仅请求实体的一部分。 字节从 0 开始编号。 | Range: bytes=500-999 |
Referer | 这是指向当前请求页面的链接的前一个网页的地址。 (“referrer”一词在 RFC 以及大多数实现中被拼错,以至于它已成为标准用法并被认为是正确的术语) | Referer: http://en.wikipedia.org/wiki/Main_Page |
Transfer-Encoding | 用于将实体安全传输给用户的编码形式。目前定义的方法有:chunked、compress、deflate、gzip、identity。不得与 HTTP/2 一起使用。 | Transfer-Encoding: chunked |
User-Agent | 用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/12.0 |
Via | 通知服务器发送请求的代理服务器。 | Via: 1.0 fred, 1.1 example.com (Apache/1.1) |
Warning | 关于实体主体可能出现的问题的一般警告。 | Warning: 199 Miscellaneous warning |
常见的非标准请求字段
Field name | Description | Example |
---|---|---|
DNT | 请求首部 DNT (Do Not Track) 表明了用户对于网站追踪的偏好。它允许用户指定自己是否更注重个人隐私还是定制化内容。 | DNT: 1 (Do Not Track Enabled)DNT: 0 (Do Not Track Disabled) |
X-Forwarded-For | X-Forwarded-For (XFF) 在客户端访问服务器的过程中如果需要经过HTTP代理或者负载均衡服务器,可以被用来获取最初发起请求的客户端的IP地址,这个消息首部成为事实上的标准。在消息流从客户端流向服务器的过程中被拦截的情况下,服务器端的访问日志只能记录代理服务器或者负载均衡服务器的IP地址。如果想要获得最初发起请求的客户端的IP地址的话,那么 X-Forwarded-For 就派上了用场。 | X-Forwarded-For: client1, proxy1, proxy2 X-Forwarded-For: 129.78.138.66, 129.78.64.103 |
X-Forwarded-Host | 是一个事实上的标准首部,用来确定客户端发起的请求中使用 Host 指定的初始域名。反向代理(如负载均衡服务器、CDN等)的域名或端口号可能会与处理请求的源头服务器有所不同,在这种情况下,X-Forwarded-Host 可以用来确定哪一个域名是最初被用来访问的。 | X-Forwarded-Host: en.wikipedia.org:8080``X-Forwarded-Host: en.wikipedia.org |
X-Forwarded-Host | X-Forwarded-Proto (XFP) 是一个事实上的标准首部,用来确定客户端与代理服务器或者负载均衡服务器之间的连接所采用的传输协议(HTTP 或 HTTPS)。在服务器的访问日志中记录的是负载均衡服务器与服务器之间的连接所使用的传输协议,而非客户端与负载均衡服务器之间所使用的协议。为了确定客户端与负载均衡服务器之间所使用的协议, X-Forwarded-Proto 就派上了用场。 | X-Forwarded-Proto: https |
响应头字段
Field name | Description | Example |
---|---|---|
Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Expose-Headers, Access-Control-Max-Age, Access-Control-Allow-Methods, Access-Control-Allow-Headers | 指定哪些网站可以参与 CORS | Access-Control-Allow-Origin: * |
Accept-Patch | 服务器使用 HTTP 响应头 Accept-Patch 通知浏览器请求的媒体类型(media-type)可以被服务器理解。 | Accept-Patch: text/example;charset=utf-8 |
Accept-Ranges | 服务器使用 HTTP 响应头 Accept-Ranges 标识自身支持范围请求(partial requests)。字段的具体值用于定义范围请求的单位。 | Accept-Ranges: bytes |
Age | Age 消息头里包含对象在缓存代理中存贮的时长,以秒为单位。 | Age: 12 |
Allow | Allow 首部字段用于枚举资源所支持的 HTTP 方法的集合。若服务器返回状态码 405 Method Not Allowed,则该首部字段亦需要同时返回给客户端。如果 Allow 首部字段的值为空,说明资源不接受使用任何 HTTP 方法的请求。这是可能的,比如服务器需要临时禁止对资源的任何访问。 | Allow: GET, HEAD |
Alt-Svc | Alt-Svc 全称为“Alternative-Service”,直译为“备选服务”。该头部列举了当前站点备选的访问方式列表。一般用于在提供 “QUIC” 等新兴协议支持的同时,实现向下兼容。 | Alt-Svc: http/1.1="http2.example.com:8001"; ma=7200 |
Cache-Control | 从服务器到客户端的所有缓存机制它们是否可以缓存这个对象。 它以秒为单位 | Cache-Control: max-age=3600 |
Connection | 设置长连接,不能在http2.0中使用 | Connection: close |
Content-Encoding | 响应回来编码格式 | Content-Encoding: gzip |
Content-Language | 响应回来语言 | Content-Language: zh-cn |
Content-Length | 返回数据的长度 | Content-Length: 348 |
Content-Location | Content-Location 首部指定的是要返回的数据的地址选项。最主要的用途是用来指定要访问的资源经过内容协商后的结果的URL。Location 与 Content-Location ,是不同的,前者Location 指定的是一个重定向请求的目的地址(或者新创建的文件的URL),而后者Content-Location 指向的是可供访问的资源的直接地址,不需要进行进一步的内容协商。Location 对应的是响应,而Content-Location 对应的是要返回的实体。 | Content-Location: /index.html |
Content-Range | 响应首部 Content-Range 显示的是一个数据片段在整个文件中的位置。 | Content-Range: bytes 21010-47021/47022 |
Content-Type | 返回的数据类型 | Content-Type: text/html; charset=utf-8 |
Date | 返回响应创建的时间 | Date: Tue, 15 Nov 1994 08:12:31 GMT |
ETag | ETag HTTP响应头是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web服务器不需要发送完整的响应。而如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖(“空中碰撞”)。如果给定URL中的资源更改,则一定要生成新的Etag值。 因此Etags类似于指纹,也可能被某些服务器用于跟踪。 比较etags能快速确定此资源是否变化,但也可能被跟踪服务器永久存留。 | ETag: "737060cd8c284d8af7ad3082f209582d" |
Expires | 响应过期时间 | Expires: Thu, 01 Dec 1994 16:00:00 GMT |
Last-Modified | The Last-Modified 是一个响应首部,其中包含源头服务器认定的资源做出修改的日期及时间。 它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。由于精确度比 ETag 要低,所以这是一个备用机制。包含有 If-Modified-Since 或 If-Unmodified-Since 首部的条件请求会使用这个字段。 | Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT |
Location | developer.mozilla.org/zh-CN/docs/… | Example 1: Location: http://www.w3.org/pub/WWW/People.html Example 2: Location: /pub/WWW/People.html |
Set-Cookie | 服务端设置cookie | Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1 |
Via | Via 是一个通用首部,是由代理服务器添加的,适用于正向和反向代理,在请求和响应首部中均可出现。这个消息首部可以用来追踪消息转发情况,防止循环请求,以及识别在请求或响应传递链中消息发送者对于协议的支持能力。 | Via: 1.0 fred, 1.1 example.com (Apache/1.1) |
常见的非标准响应字段
Field name | Description | Example |
---|---|---|
Content-Security-Policy | HTTP 响应头**Content-Security-Policy **允许站点管理者控制用户代理能够为指定的页面加载哪些资源。除了少数例外情况,设置的政策主要涉及指定服务器的源和脚本结束点。这将帮助防止跨站脚本攻击XSS | Content-Security-Policy: <policy-directive>; <policy-directive> |
状态码
http状态码描述当前请求响应的状态。
响应分为五类:信息响应(
100
–199
),成功响应(200
–299
),重定向(300
–399
),客户端错误(400
–499
)和服务器错误 (500
–599
)。
信息响应(100-199)
状态码 | 描述 |
---|---|
100 Continue | 这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续请求,如果已经完成,则忽略它。 |
101 Switching Protocol | 响应客户端的 Upgrade (en-US) 标头发送的,并且指示服务器也正在切换的协议。 |
103 Early Hints | 主要用于与Link 链接头一起使用,以允许用户代理在服务器仍在准备响应时开始预加载资源。 |
成功响应(200
–299
)
状态码 | 描述 |
---|---|
200 OK | 请求成功。 |
201 Created | 该请求已成功,并创建了一个新的资源和返回在响应体中或者响应头中。这通常是在POST请求,或是某些PUT请求之后返回的响应。 |
202 Accepted | 请求已经接收到,但还未响应,没有结果。意味着不会有一个异步的响应去表明当前请求的结果,预期另外的进程和服务去处理请求,或者批处理。 |
204 No Content | HTTP **204 No Content **成功状态响应码,表示该请求已经成功了,但是客户端客户不需要离开当前页面。默认情况下 204 响应是可缓存的。一个 ETag 标头包含在此类响应中。 使用惯例是,在 PUT 请求中进行资源更新,但是不需要改变当前展示给用户的页面,那么返回 204 No Content。如果创建了资源,则返回 201 Created 。如果应将页面更改为新更新的页面,则应改用 200 。 |
205 Reset Content | 服务器成功处理了请求,且没有返回任何内容。但是与204响应不同,返回此状态码的响应要求请求者重置文档视图。该响应主要是被用于接受用户输入后,立即重置表单,以便用户能够轻松地开始另一次输入。与204响应一样,该响应也被禁止包含任何消息体,且以消息头后的第一个空行结束。现在都是局部刷新,这个状态码是一般用不了。 |
206 Partial Content | 服务器已经成功处理了部分 GET 请求。类似于 FlashGet 或者迅雷这类的 HTTP 下载工具都是使用此类响应实现断点续传或者将一个大文档分解为多个下载段同时下载。该请求必须包含 Range 头信息来指示客户端希望得到的内容范围,并且可能包含 If-Range 来作为请求条件。 |
重定向(300
–399
)
状态码 | 描述 |
---|---|
300 Multiple Choice | 被请求的资源有一系列可供选择的回馈信息,每个都有自己特定的地址和浏览器驱动的商议信息。用户或浏览器能够自行选择一个首选的地址进行重定向。 |
301 Moved Permanently (http1.0) | HTTP 301 永久重定向 说明请求的资源已经被移动到了由 Location 头部指定的url上,是固定的不会再改变。搜索引擎会根据该响应修正。尽管标准要求浏览器在收到该响应并进行重定向时不应该修改http method和body,但是有一些浏览器可能会有问题。所以最好是在应对GET 或 HEAD 方法时使用301,其他情况使用308 来替代301。 |
302 Found(http1.0) | 请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。 |
303 See Other | 对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。这个方法的存在主要是为了允许由脚本激活的POST请求输出重定向到一个新的资源。 |
304 Not Modified | 如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。304 响应禁止包含消息体,因此始终以消息头后的第一个空行结尾。 |
307 Temporary Redirect(http1.1) | 请求的资源现在临时从不同的URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。 |
308 Permanent Redirect(http1.1) | 这意味着资源现在永久位于由 Location: HTTP Response 标头指定的另一个 URI。 这与 301 Moved Permanently HTTP 响应代码具有相同的语义,但用户代理不能更改所使用的 HTTP 方法:如果在第一个请求中使用 POST ,则必须在第二个请求中使用 POST 。 |
客户端错误(400
–499
)
状态码 | 描述 |
---|---|
400 Bad Request | 1、语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求。2、请求参数有误。 |
401Unauthorized | 当前请求没有权限,或者没有登录等等 |
403 Forbidden | 可能是服务器禁访问,也可能是网站被封了 |
404 Not Found | 当前请求找不到,可能是地址错了,或者后台没有接口 |
405 Method Not Allowed | 当前的请求方式不允许 |
406 Not Acceptable | 请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体。 |
408 Request Timeout | 请求超时。客户端没有在服务器预备等待的时间内完成一个请求的发送。客户端可以随时再次提交这一请求而无需进行任何更改。 |
409 Conflict | 由于和被请求的资源的当前状态之间存在冲突,请求无法完成。这个代码只允许用在这样的情况下才能被使用:用户被认为能够解决冲突,并且会重新提交新的请求。该响应应当包含足够的信息以便用户发现冲突的源头。 |
429 Too Many Requests | 用户在给定的时间内发送了太多请求(“限制请求速率”)。 |
服务器错误 (500
–599
)
状态码 | 描述 |
---|---|
500 Internal Server Error | 服务器遇到了不知道如何处理的情况。 |
501 Not Implemented | 此请求方法不被服务器支持且无法被处理。只有GET 和HEAD 是要求服务器支持的。 |
503 Service Unavailable | 很大可能是服务器重启 |
504 Gateway Timeout | 当服务器作为网关,不能及时得到响应时返回此错误代码。 |
505 HTTP Version Not Supported | 服务器不支持请求中所使用的HTTP协议版本。 |
参考
各位看官如遇上不理解的地方,或者我文章有不足、错误的地方,欢迎在评论区指出,感谢阅读。