HTTP

概述

参考网站:MDN

一个完整的HTTP请求:

  • Redirect - 根据本地缓存判断,是否永久跳转到新的URL
  • App cache - 查询资源缓存
  • DNS - DNS 解析域名
  • TCP - 创建TCP,SSL
  • Request - 请求
  • Response - 响应

版本

  • 1.1
    • 持久TCP连接
    • Pipeline 多个请求放入一个Pipeline依次处理
    • Host等命令,区分服务器上的不同web服务
  • 2
    • 所有数据以二进制传输
    • 多个请求不再按照顺序处理
    • 头信息压缩
    • 服务器主动推送

如果客户端想要升级协议,例如:HTTP/2, WebSocket,可以配置头部:

1
2
3
4
GET /index.html HTTP/1.1
Host: www.example.com
Connection: upgrade
Upgrade: example/1, foo/2

资源

HTTP 资源

  • URI - 包含 URL 和 URN - 统一资源标识符
  • URL - 统一资源定位符
    • protocol://user:password@hostname:port/path?query=string#hash
  • URN - 永久统一资源定位符 - 目前还没有成熟方案

URL 模式

  • 普通模式 - 使用?携带参数,/app?id=1&name=xyz
  • PATHINFO - 使用/, -携带参数
    • /index.php/module/action/var
    • /index.php/module-action-var
  • REWRITE - 在PATHINFO基础上增加了重写规则,可以去掉index.php
  • 兼容模式 - 用于不支持PATHINFO的情况,/index.php/?s=/module/action/var

Data URL:允许向文档中嵌入小文件,其格式如下:

1
2
data:[<mediatype>][;base64],<data>
data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

MIME 类型:用于描述文件类型。

  • text / plain, html, css, javascript - 文本
  • image / gif, png, jpg, bmp, x-icon … - 图片
  • application / xml, pdf, javascript, x-www-form-urlencoded, json - 二进制文件
  • multipart / form-data, byteranges - 复合文件格式,
    • 例:byteranges可以配合206来发送文件的一部分
  • audio / midi, mpeg, ogg, wav
  • video / webm, ogg
  • font
  • message
  • example
  • model

HTTP客户端 CURL

1
2
3
4
# 一次访问
curl baidu.com
# 一次访问 带头部
curl -v www.baidu.com

客户端由user-agent描述。

CORS 跨域

  • 请求会接受,响应也会发送,但是会被浏览器拦截响应
  • 不受跨域限制的有link, script, img等标签
  • 默认只允许
    • 方法:GET, HEAD, POST
    • Content-Type: text/plain, multipart/form-data, application/x-www-form-urlencoded
    • 请求头:Accept, Accept-Language, Content-Language, Content-Type
    • XMLHttpRequestUpload 对象,均没有注册任何事件监听器
    • 没有ReadableStream对象
  • 预请求验证
    • 先发送一个OPTIONS请求,再发送真正的请求
  • 服务器端的Response需要添加头部
    • ‘Access-Control-Allow-Origin’: ‘*’
  • 添加允许的请求头
    • ‘Access-Control-Allow-Headers’: ‘X-Test-Cors’
  • 添加允许的方法
    • ‘Access-Control-Allow-Methods’: ‘POST, PUT, DELETE’
  • 1000秒内不用再发预请求
    • ‘Access-Control-Max-Age’: ‘1000’

缓存

  • Cache-Control 字段:客户端的缓存
  • 可缓存性:public, private, no-cache
    • public - 请求经过的所有节点都可以缓存
    • private - 只有发起请求的浏览器可以缓存
    • no-cache - 缓存,但是每次去服务器验证一次
  • 到期
    • max-age = 秒数 - 浏览器使用
    • s-maxage = 秒数 - 代理服务器使用
    • max-stale = 秒数 - 即便缓存过期,但是没超过这个时间,缓存仍然可以用
  • 重新验证
    • must-revalidate - 如果已经过期,则必须到原服务端验证缓存
    • proxy-revalidate - 代理服务去原服务器验证缓存
  • 其他
    • no-store - 不缓存,每次去服务器拿新数据
    • no-transform - 代理服务器不对数据做改动(压缩等)
  • 如果想要每次更新后重新请求缓存,可以通过修改资源名,使用hash名称。
  • 资源验证
    • Code:304 - 所请求的资源未修改,允许客户端使用缓存
    • 验证头
      • Last-Modified - ‘123’ - 对比时间,过期则请求缓存
        • If-Modified-Since - 客户端下次请求,就会拿出这些头
        • If-Unmodified-Since -
      • Etag - ‘789’ - 通过数据签名验证,每个数据签名唯一,只要修改就变
        • If-Match - 客户端下次请求,就会拿出这些头
        • If-Non-Match
1
2
3
4
5
6
7
// Etag 
if(req.headers['if-non-match'] === '789') {
resp.writeHead(304, {/* Headers */})
resp.end('')
}else{
resp.end('true content')
}

Cookie

  • Set-Cookie - 服务器设置,之后客户端每次访问都会带着,可以有多个这个头,不可跨域访问
    • max-age - 有效时间,默认关闭浏览器后清除
    • expires - 到期时间
    • Secure
    • HttpOnly - 禁止Javascript访问
    • domain - 允许设置的域名,可以解决跨域不能访问的问题
1
2
3
4
// Cookie
resp.writeHead(200, {
'Set-Cookie': ['id=123; max-age=2', 'abc=456']
})

但是由于传输Cookie会带来额外开销,因此浏览器又提供了新的数据存储方法。

  • sessionStorage - 为每个页面开辟的独立存储区域,浏览器关闭后释放。大小一般为10MB。
  • localStorage - 功能相同,关闭浏览器也不会消失。大小一般为10MB。
  • IndexedDB - 基于 JavaScript 的非关系数据库,大小可达2GB。可以用于WebGL开发。

身份验证

当客户端未授权访问一个页面时,服务器会返回401 unauthorized响应,并附带WWW-Authenticate头部对客户端进行质询,该头部包含了几种允许的质询的方式。之后客户端就会在Authorization头部写入身份凭证信息。

代理服务器也可以对客户端进行身份验证,使用的是407响应,并附带Proxy-Authorization头部。之后客户端就会在Proxy-Authorization头部写入身份凭证信息。

验证方案有如下集中:

  • Basic 基本认证,base64编码用户名和密码(即用户凭证)
    • Authorization: Basic base64(user:password)
  • Digest 摘要认证,采用质询与响应方法
    • Authorization-Required
    • WWW-Authenticate: Digest realm=”DIGEST” …(质询码,加密算法,等)
    • Authorization: Digest username=”user” realm=”DIGEST” response=”xxx” …(质询码,加密算法,等)
  • SSL 客户端认证:利用HTTPS
  • FormBase 表单认证:利用Cookie和Session
  • Bearer 通过OAuth 2.0保护资源
  • HOBA
  • Mutual
  • AWS4-HMAC-SHA256

长连接

  • 并发限制:默认是6个连接,多了会等待
  • Connection
    • keep-alive - 保持长连接
    • close - 关闭长连接

数据协商

  • 客户端要求的数据格式,服务器返回的格式
  • 请求
    • Accept
    • Accept-Encoding - 编码方式
    • Accept-Language - 语言
    • User-Agent - 浏览器信息
  • 响应
    • Content-Type - 对应 Accept 里的一种格式,使用MIME Type
      • application/x-www-form-urlencoded
      • multipart/form-data - 上传文件使用,需要加boundry,不同部分可以是不同的Content-Type
      • text/plain
    • X-Content-Type-Options - nosniff - 禁止客户端预测返回内容
    • Content-Encoding - 数据压缩
      • gzip
    • Content-Language
  • 断点续传
    • Range - 请求头中,指示第一个字节和最后一个字节的位置
      • 0-1024, 3000-3999, 8000-
    • Content-Range - (200, 206) 响应头,表示返回的实际内容
      • bytes 0-1024 / [总长度]
    • Content-Length - 响应头,表示返回的实际长度

重定向

  • 响应 Code:
    • 301 - 永久跳转,下次跳转不会经过服务器,慎用
    • 302 - 临时跳转
  • Location - 新的 URL
    • 如果不是同一个域,就需要加上hostname和端口

内容安全策略 CSP

  • 用于限制资源获取,报告资源获取越权
  • 资源类型限制
    • default-src - 全局限制
    • connect-src - 请求源限制
    • img-src, font-src, frame-src, media-src, style-src, script-src, manifest-src - 可以被哪个网址加载
  • Content-Security-Policy:
    • default-src http: https:
      • 禁用 inline script
    • default-src ‘self’
      • 禁用 外链资源,只能加载本站资源
    • default-src ‘self’ ‘http://www.baidu.com/
      • 只允许 本站和百度的资源
    • form-action ‘self’
      • 只允许 表单提交到本站
    • report-uri /report
      • 问题报告到这个连接
  • Content-Security-Policy-Report-Only - 检测到,但是不拦截,只报告

也可以写到htle的meta标签中。

1
2
3
<head>
<meta http-equiv="Content-Security-Policy" ccontent="script-src 'self'">
</head>

HTTPS

客户端向服务端发送请求,服务器返回一个公钥,客户端使用公钥加密数据再次发给服务器,服务器利用私钥解密数据。

此外,CA会向服务器颁发证书,证书中包含:服务器公钥(CA用私钥加密),签名(CA用私钥加密)等。之后服务器只向客户端发送证书,证书的合法性由客户端自己去求证。

TLS/SSL协议:

  • SSL 3.0 - 存在安全漏洞
  • TLS 1.0 - 存在安全漏洞
  • TLS 1.1
  • TLS 1.2
  • TLS 1.3

使用HTTPS需要证书,以及对于证书的加解密配置。证书可以让CA签发,也可以自己生成。

生成一个证书

1
2
3
4
5
6
7
8
9
10
11
# 服务器证书 : alias 别名, keystore 证书存放位置, validity 证书过期时间, sigalg 签名算法
keytool -genkey -v -alias tomcat -keyalg RSA -keystore /usr/java/tomcat.keystore -validity 36500 -sigalg SHA256withRSA
# 输入:密码,六位
# 输入:网站信息

# 客户端证书
keytool -keystore tomcat.keystore -export -alias tomcat -file tomcat.cer
# 输入:密码

# 再配置Web服务器添加HTTPS证书 tomcat.keystore
# 再为客户端安装证书 tomcat.cer

WebSocket

过去采用Ajax,Long Poll等方式同步数据。

WebSocket建立时,请求发送协议升级请求,同时给出Websocket-Key,通信协议(chat, superchat),版本号。服务器会返回响应。

HTTP2

SPDY,用于TLS与HTTP之间,用来提速网络。SPDY会多路复用,请求优化。服务器也会主动推送。压缩了HTTP头,强制使用SSL。

HTTP2是基于SPDY设计的。最特色的功能是采用二进制传输而非文本传输,数据采用分帧发送。同时会压缩首部,且双方各维护一份首部表,一般会只发送更新的部分。也采用了多路复用。可以并行交错发送数据。流设置优先级,高优先级的流(css, js)先发送,优先级不是绝对的。服务器还会主动推送,例如主动推送CSS, JS文件。

WebDAV

基于WWW的分布式文件系统。支持在线打开,编辑,映射为本地的硬盘。

HTTP3

基于QUIC协议发展,而QUIC底层使用UDP。HTTP 2.0有队头阻塞,握手延迟大问题。

QUIC不使用(IP, PORT)识别对方,而是采用ID的方式,这在移动端更适用。

QUIC采用前向纠错。

Web 安全

安全问题

  • Authentication 验证
  • Authorization 授权
  • 客户端攻击
  • 远程执行
  • 信息泄露
  • 逻辑问题

漏洞分类

  • 注入:SQL NOSQL OS LDAP
  • 失效身份验证,破译密码,密钥等
  • 敏感数据泄露
  • XXE 利用XML外部实体窃取内部文件,执行远程代码
  • 失效的访问控制
  • 安全配置错误:默认设置,不完整的配置等
  • XSS 跨站攻击
  • 不安全的反序列化
  • 含有漏洞的组件
  • 不足的日志记录和监控(必须含有6个月的日志)

安全机制

  • 验证机制,登录
  • 会话管理,SESSION
  • 访问控制,API接口

验证机制

方案:输入用户名密码,使用SSL,限制登录等。

双因子认证:个人密码 + 手机验证码。

忘记密码:需要身份验证。邮箱找回密码,负载要加密。

多阶登录机制并不安全。

会话管理

服务器在用户登录后签发一个令牌,并为令牌签名。

应当适当终止会话,过期Session。

HTTP 状态码

1xx:信息

100 Continue:服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。
101 Switching Protocols:服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。
103 Checkpoint:用于 PUT 或者 POST 请求恢复失败时的恢复请求建议。

2xx:成功

200 OK:请求成功(这是对HTTP请求成功的标准应答。)
201 Created:请求被创建完成,同时新的资源被创建。
202 Accepted:供处理的请求已被接受,但是处理未完成。
203 Non-Authoritative Information:请求已经被成功处理,但是一些应答头可能不正确,因为使用的是其他文档的拷贝。
204 No Content:请求已经被成功处理,但是没有返回新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
205 Reset Content:请求已经被成功处理,但是没有返回新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。
206 Partial Content:客户发送了一个带有Range头的GET请求,服务器完成了它。

3xx:重定向

300 Multiple Choices:多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。
301 Moved Permanently:所请求的页面已经转移至新的 URL 。
302 Found:所请求的页面已经临时转移至新的 URL 。
303 See Other:所请求的页面可在别的 URL 下被找到。
304 Not Modified:未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy:客户请求的文档应该通过Location头所指明的代理服务器提取。
306 Switch Proxy:目前已不再使用,但是代码依然被保留。
307 Temporary Redirect:被请求的页面已经临时移至新的 URL 。
308 Resume Incomplete:用于 PUT 或者 POST 请求恢复失败时的恢复请求建议。

4xx:客户端错误

400 Bad Request:因为语法错误,服务器未能理解请求。
401 Unauthorized:合法请求,但对被请求页面的访问被禁止。因为被请求的页面需要身份验证,客户端没有提供或者身份验证失败。
402 Payment Required:此代码尚无法使用。
403 Forbidden:合法请求,但对被请求页面的访问被禁止。
404 Not Found:服务器无法找到被请求的页面。
405 Method Not Allowed:请求中指定的方法不被允许。
406 Not Acceptable:服务器生成的响应无法被客户端所接受。
407 Proxy Authentication Required:用户必须首先使用代理服务器进行验证,这样请求才会被处理。
408 Request Timeout:请求超出了服务器的等待时间。
409 Conflict:由于冲突,请求无法被完成。
410 Gone:被请求的页面不可用。
411 Length Required:”Content-Length” 未被定义。如果无此内容,服务器不会接受请求。
412 Precondition Failed:请求中的前提条件被服务器评估为失败。
413 Request Entity Too Large:由于所请求的实体太大,服务器不会接受请求。
414 Request-URI Too Long:由于 URL 太长,服务器不会接受请求。当 POST 请求被转换为带有很长的查询信息的 GET 请求时,就会发生这种情况。
415 Unsupported Media Type:由于媒介类型不被支持,服务器不会接受请求。
416 Requested Range Not Satisfiable:客户端请求部分文档,但是服务器不能提供被请求的部分。
417 Expectation Failed:服务器不能满足客户在请求中指定的请求头。

5xx:服务器错误

500 Internal Server Error:请求未完成。服务器遇到不可预知的情况。
501 Not Implemented:请求未完成。服务器不支持所请求的功能,或者服务器无法完成请求。
502 Bad Gateway:请求未完成。服务器充当网关或者代理的角色时,从上游服务器收到一个无效的响应。
503 Service Unavailable:服务器当前不可用(过载或者当机)。
504 Gateway Timeout:网关超时。服务器充当网关或者代理的角色时,未能从上游服务器收到一个及时的响应。
505 HTTP Version Not Supported:服务器不支持请求中指明的HTTP协议版本。
511 Network Authentication Required:用户需要提供身份验证来获取网络访问入口。

SSL/TLS