http整理

387 阅读8分钟

图片防盗链

refer和hostname做对比,一般我们会设置一个白名单,不在白名单之内的refer特殊处理,一般可以将一个提示图片pipe到res中,起提示作用

gzip压缩

accept-encoding
content-encoding

代理

http-proxy模块
正向代理: 代理局域网的用户访问外网,用户知道要代理到哪个服务器
反向代理:,用来代理局域网中的服务器,用户不知道代理到哪里

user-agent

  • 判断用户内核,识别用户的操作系统

多语言

+ 客户端下拉选项实现
+ 服务器端实现
    + Accept-language: 各种语言用','隔开,语言和对应的权重使用';'隔开,例如'en;q=0.9',没写权重默认是1

缓存

强制缓存

200,不会再请求服务器端

expires: 绝对时间
cache-control: max-age,no-store(不缓存), no-cache是会被缓存的

协商缓存

+ last-modified: 只精确到s,如果改动了文件,但最后内容不变依然会请求客户端
   if-modified-since
+ E-tag: 根据内容,比上一个更精确
    + If-None-Match

cookie和session

cookie:
    name,
    value,
    path: 以path开头的路径可以写入对应的cookie
    httpOnly: true,客户端不能通过js操作cookie
    size,
    expires: 设置过期时间,是一个绝对时间
    max-age: 10,相对时间
    sameSite
    domain: 针对哪个域设置,(主域与子域),默认为当前域名,cookie默认发送,通过设置domain,针对某个域发,有效的减少了浪费
'cookie签名': 加盐算法(sha256),根据内容以及密钥进行加密,不可以反解,当内容有一点不一样,结果大不相同(雪崩效应)
Session是服务器端使用的一种记录客户端状态的机制

jwt

  • 网络应用环境间传递声明而执行的一种基于JSON的开放标准
JWT包含了使用.分隔的三部分
Header 头部, 头部可以指定所使用的加密算法,例如{ "alg": "HS256", "typ": "JWT"} 
Payload 负载,对内容进行加密
Signature 签名,创建签名需要使用编码后的header和payload以及一个秘钥


原理: jwt分为三部分,header,preload,sign,服务器端先将header以及preload使用Base64Url编码组成了JWT结构的第一部分和第二部分,然后根据得到的这两个加上一个密钥进行签名得到第三部分,然后将这三部分返回

实现

const crypto = require('crypto');
function encode(payload, key) {
    let header = { type: 'JWT', alg: 'sha256' };//声明类型和算法
    var segments = [];//声明一个数组
    segments.push(base64urlEncode(JSON.stringify(header)));//对header进行base64
    segments.push(base64urlEncode(JSON.stringify(payload)));//对负载进行base64
    segments.push(sign(segments.join('.'), key));//加入签名
    return segments.join('.');
}
function sign(input, key) {
    return crypto.createHmac('sha256', key).update(input).digest('base64');
}


function decode(token, key) {
    var segments = token.split('.');
    var headerSeg = segments[0];
    var payloadSeg = segments[1];
    var signatureSeg = segments[2];

    var header = JSON.parse(base64urlDecode(headerSeg));
    var payload = JSON.parse(base64urlDecode(payloadSeg));

    if (signatureSeg != sign([headerSeg, payloadSeg].join('.'), key)) {
        throw new Error('verify failed');
    }

    if (payload.exp && Date.now() > payload.exp * 1000) {
        throw new Error('Token expired');
    }
    return payload;
}

function base64urlEncode(str) {
    return new Buffer(str).toString('base64');
}

function base64urlDecode(str) {
    return new Buffer(str, 'base64').toString();
}

module.exports = {
    encode,
    decode
}

http相关

3.5.2 2XX 成功
200(OK 客户端发过来的数据被正常处理
204(Not Content 正常响应,没有实体
206(Partial Content 范围请求,返回部分数据,响应报文中由Content-Range指定实体内容
3.5.3 3XX 重定向
301(Moved Permanently) 永久重定向
302(Found) 临时重定向,规范要求方法名不变,但是都会改变
303(See Other) 和302类似,但必须用GET方法
304(Not Modified) 状态未改变 配合(If-Match、If-Modified-Since、If-None_Match、If-Range、If-Unmodified-Since)
307(Temporary Redirect) 临时重定向,不该改变请求方法
3.5.4 4XX 客户端错误
400(Bad Request) 请求报文语法错误
401 (unauthorized) 需要认证
403(Forbidden) 服务器拒绝访问对应的资源
404(Not Found) 服务器上无法找到资源
3.5.5 5XX 服务器端错误
500(Internal Server Error)服务器故障
503(Service Unavailable) 服务器处于超负载或正在停机维护

http连接描述

  • http直接通过明文的方式在浏览器与服务器之间传输信息

    • 传统的http是直接将http报文直接传递到TCP,然后TCP再通过TCP套接字传递到目标主机上
  • https采取对称加密与非对称加密的结合的方式保证浏览器与服务器之间传输信息的安全性

    • 策略: 采用对称加密传输数据 + 采用非对称加密验证身份传递密钥 + 采用散列算法验证完整性
    • 过程: https将http报文传输给SSL套接字进行加密,将加密后的报文发送给TCP套接字,TCP套接字再将加密后的报文发送给目标主机,目标主机通过TCP套接字接受加密后的报文给SSL套接字,SSL解密后交给对应的进程
  • 窃听 - 对称加密

  • 篡改 - 完整性校验,使用散列算法进行签名

  • 传递密钥 - 非对称加密

  • 安全速度 - 非对称加密+对称加密

  • 中间人攻击 - 证书

  • 证书伪造 - 消息摘要

  • 摘要伪造 - 数字证书

  • http + TLS/SSL

TLS/SSL

  • 散列算法: 用来校验数据的完整性 md5 SHA
  • 对称加密: 信息加密,加密解密用同一种密钥 AES
  • 非对称加密: RSA 身份密钥交换: 加密和解密用的密钥不一样,但有关系

签名

私钥和文件组成一个签名,然后通过签名,公钥以及文件进行验证签名

数字证书的原理

  • 客户端访问服务器端,服务器端会生成公钥和私钥一对密钥对
  • 然后服务器端把公钥发给CA机构,CA机构使用自己的私钥和服务器的公钥进行签名,并颁发数字证书发送给服务端
  • 服务端将证书发给客户端,客户端拿内置的一些CA的公钥确认数字证书的真假
  • 把数据使用服务器公钥加密后传输

http加密过程

  • 先建立tcp链接
    • 三次握手
      • 第一次握手,客户端主动去connect服务器端,发送请求请求标志SYN=1,并发送客户端的初始序列号x,此时服务器端被动打开
      • 第二次握手,服务器端发送请求标志SYN=1,并发送自己的初始序列号y,并发送客户端的确认序列号ack=x+1
      • 第三次握手,客户端发送请求标志SYN=1,向服务器发送自己的序列号x+1,以及确认收到服务端序列号ack应y+1
      • 至此双方握手成功,可以开始通信了
  • 基于SSL协议握手交换密钥
    • 用户通过https的url建立ssl链接
    • 服务端生成一对密钥,将非对称加密的公钥A发送给浏览器端
    • 浏览器拿到公钥A,生成一个随机数,作为对称加密的密钥B
    • 浏览器拿到公钥A与自己生成的堆成加密的密钥B加密,生成密钥C
    • 浏览器将密钥C发送给服务器端
    • 服务器端使用自己的私钥对密钥C进行解密,得到对称加密的密钥B,
    • 浏览器和服务器都拥有对称加密的密钥B进行通信
  • 拿到协商好的密钥进行通信

三次握手图

四次挥手图

  • 第一次挥手:客户端发送想要释放链接的标志FIN=1,并且把自己的序列号u发送给服务器端,进入FIN-WAIT-1状态
  • 第二次挥手:服务器端收到客户端的报文,向服务器发送自己的序列号v,以及确认标志ACK=1和客户端的确认号ack=u+1,进入CLOSE-WAIT状态
  • 第三次挥手:客户端收到服务器端的确认结果后,进入FIN-WAIT-2状态,服务器端释放FIN=1信号,确认标志ACK=1以及确认序列号u+1,以及自己的序列号w,进入LAST-ACK状态
  • 第四次挥手:客户端收到后发送确认标志ACK=1,确认序列号w+1,以及自己的序列号u+1,进入CLOSE状态

为什么三次握手四次挥手

三次握手时,服务器同时把ACK和SYN放在一起发送到了客户端那里
四次挥手时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方 ACK 和 FIN 一般都会分开发送。

http和https的区别

https = http + ssl
http是基于超文本传输协议的明文传输,https加密传输
https需要CA证书,http没有
http默认80端口,https默认443端口。

http1和http2的区别

+ 采用新的二进制
+ 头部压缩:HPACK 使用2个索引表(静态索引表和动态索引表)来把头部映射到索引值,并对不存在的头部使用 huffman 编码,并动态缓存到索引,从而达到压缩头部的效果。
+ 多路堵用
+ 服务器推送:(server push)指的是,还没有收到浏览器的请求,服务器就把各种资源推送给浏览器。

get和post的区别

get产生一个数据包,浏览器是将http的header和data一起发送出去,服务器返回200
而data是先将header发送出去,服务器返回100continue,再将data发送出去,服务器返回200

http的协议层:物数网传会表应

物理层
数据链路层
网络层
传输层
会话层
表现层
应用层