浏览器窗口输入一个url的过程
输入一个url的请求,例如:http://console.ucloud.cn:80/icp
1)浏览器解析出主机名: console.ucloud.cn
2)浏览器查询这个主机的IP地址(DNS解析) 43.227.197.201
3)浏览器获得端口号80
4)浏览器发起到43.227.197.201端口80的连接(此处有TCP的连接,经典三次握手)
5)发送 http请求
6)浏览器接收返回内容
7)将返回的内容渲染在页面上
8)关闭连接(此处关闭的是http连接,TCP连接通道是否关闭,看当前http的协议,以及请求报文的配置)
http发展,不同版本与区别
- Http0.9,只有Get请求,只能返回html字符串,服务端响应后立马关闭TCP
- Http1.0,添加其他请求Post,Put,Header,Delete,增加请求头和响应头Headers(status code,缓存,权限,内容编码),扩充了媒体格式,依然是无状态,无连接
- Http1.1,长连接,Connection:keep-alive,管道化,顺序执行,无法解决对头阻塞的问题;缓存字段Cache-Control;断点传输
- Https,在传输层与网络层之间,加了一层SSL/TLS 安全层,需要有SSL证书,才能访问。默认端口443,所有传输的内容都经过加密的,防止运营商劫持(脚本抓包)
- Http2:多路复用,二进制分帧
特性
http请求的首行:General包含字段:
Request URL:请求路径
Request Method:请求方法
Status Code:状态码
//举例子
> curl http://baidu.com
>curl http://www.baidu.com
>curl -v http://www.baidu.com
//返回浏览器的请求报文信息,和返回内容
常见的状态码
2XX表示请求已经被正常处理了
3XX表示重定向
4XX表示客户端错误
5XX表示服务端错误
export default {
200: ‘OK 请求被正确处理并返回了结果’,
201: ‘新增或修改数据成功’,
202: ‘请求已进入任务队列,被异步处理’,
203: ‘令牌或登录状态失效’,
204: ‘No Content’, //该状态码代表服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分。另外,也不允许返回任何实体的主体。比如,当从浏览器发出请求 处理后,返回 204 响应,那么浏览器显示的页面不发生更新。
206: ‘Partial Content’,//该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求。响应报文中包含由 Content-Range 指定范围的实体内容
301: ‘请求的资源被永久重定向到新的位置,将从新的地址重新请求’,
302: ‘请求的资源被临时重定向到新的位置’,
304: ‘满足协商缓存‘,
400: ‘请求参数错误,服务器没有对数据做新建或修改’,
401: ‘Unauthorized 无访问权限,用户名、密码、令牌错误’,
403: ‘Forbidden 得到访问授权,但访问是被禁止’,
404: ‘Not Found 访问的是不存在的资源’, //服务器上没有请求的资源
405: ‘Method Not Allowed 请求方式不正确’, //该状态码标明,客户端请求的方法虽然能被服务器识别,但是服务器禁止使用该方法
406: ‘请求的数据格式不是服务接收的类型’,
410: ‘请求的资源被永久删除’,
422: ‘服务器创建对象时发生错误’,
500: ‘Internal Server Error 服务器不可用,未返回正确的数据’,
502: ‘Bad Gateway 服务器网关错误’,
503: ‘Service Unavailable 服务器过载或维护中’, //该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
504: ‘服务器响应超时’
}
简单请求与非简单请求
简单请求:不需要预检OPTIONS请求
非简单请求:需要通过预检OPTIONS请求,才能向服务器请求数据
满足简单请求的条件:
1、请求的方法是以下三种之一:HEAD、GET、POST
2、HTTP头信息不超过以下几种字段:
Accept //request header中
Accept-language //request header中
Content-Language //response header中
Last-Event-ID???
Content-Type:只限于三个值application/www-form-urlencoded、multipart/form-data、text/plain //response header中
headers
通用的header字段
Cache-Control:用来控制缓存
Connection:管理持久连接:Keep-Alive
Date:表示创建HTTP报文的日期和时间
Pragma:用来向后兼容只支持HTTP/1.0协议的缓存服务器,那时候HTTP/1.0协议中的Cache-Control还没出来;例如:Program: no-cache
Transfer-Encoding:Trailer:说明报文主体后使用了哪些首部字段,(可用在HTTP/1.1版本分块传输编码时);Transfer-Encoding: 规定了传输报文主体时采用的编码方式(仅对分块传输编码有效);例如:Transfer-Encoding: chunked
Upgrade:用于检测HTTP协议或其他协议,是否可使用更高版本的协议进行通信,其参数值可以用来指定一个完全不同的通信协议(仅限客户端与邻近服务器之间,因此使用首部字段Upgrade时还需要额外指定Connect:Upgrade)
Via:为了追踪客户端和服务端之间的请求和响应报文的传输路径。当报文讲过代理或网关时,会先在首部字段Via中附加服务器的信息,然后再进行转发。(此字段很少见到过)
Warning
Request header常见字段
1、Accept
//通知服务器,用户代理能处理的媒体类型,以及媒体类型的相对优先级
Accept: text/html,application/json;q=0.9, application/xml;q=0.8
//q=num表示权重的优先值,权重值num的取值范围是0-1,可以精确到三位小数,1位权重最大值,默认为1
2、Accept-Charset
//通知服务器,用户代理能够处理的字符集类型,以及字符集的相对优先级,q=num代表含义同上
Accept-Charset:UTF-8
3、Accept-language
//用来告知服务器,用户代理能够处理的语言类型,采用权重q指定优先级
Accept-Language:zh-CN,zh;q=0.9
4、Accept-Encoding
//用来告知服务器,用户代理能够处理的编码类型
//压缩就是编码的一种
Access-Encoding: gzip,deflate,compress,identity //压缩
//默认identity:对请求内容,不进行编码
//gzip:表明实体采用GNU zip编码
//compress:表明实体采用Unix的文件压缩程序
//deflate:表明实体是用zlib的格式压缩的
//gzip,compress,deflate都是无损压缩的算法,用于减少传输报文的大小,不会导致信息损失。其中gzip的效率最高,使用最广泛。
5、Authorization
用来告知服务器,用户代理的认证信息用于验证用户身份的凭证
6、Host
请求服务器的域名,以及监听的端口
7、if-Match与if-None-Match表达意思相反
8、if-Modified-Since (与reponse header中 Last-Modified对应,用于协商缓存,判断文件最后一次的修改时间是否一致)
9、if-None-Match (与reponse header中 ETag对应,用于协商缓存,判断文件是否修改过)
10、if-Range
//以上7-10这几个字段,都与缓存有关
11、Referer
可以根据Referer查看请求资源是从哪个页面发起的
12、User-Agent
用户请求的浏览器设备信息、版本号等
Response header常见字段
Accept-Ranges:告知客户端,服务器能否处理范围请求(与分片上传有关);例如Accept-Ranges: bytes 或者 none
Content-Type(通用字段):服务端返回的内容类型,如:application/json; charset=utf-8 或者application/x-www-form-urlencoded
Content-Encoding:返回内容编码方式:例如gzip,deflate, compress
Content-Length:返回内容的大小(字节): 比如:1024B
Age:告知客户端,源服务器在多久前创建了响应,字段值的单位为秒(不曾见过)
Location:指定将页面重新定向的地址
E-Tag、Expires、Last-Modified与缓存有关,后面会详解
Access-Control-Allow-Origin:允许请求的域(指定域名的话,服务端只能设置一个,如果想要允许多个,可在服务端动态配置,根据request的url,判断域名是否在请求允许范围内,如果是则动态设置为该值)
Access-Control-Allow-Headers:允许设置的headers
Access-Control-Allow-Credentials:允许客户端携带验证信息如cookie, 此字段需要客户端与服务端配合使用,
服务端设置Access-Control-Allow-Credentials:true
客户端设置
var xhr = new XMLHttpRequest();
xhr.open(‘GET‘, ‘http://example.com/‘, true);
xhr.withCredentials = true;
xhr.send(null);
或者使用fetch(提取凭证)
fetch(url, {
credentials: ‘include‘
})
跨域
待补充.....
cors配置
缓存
缓存的判断策略:
缓存策略分为:过期策略,协商策略,存储策略
过期策略发生在请求前,用于判断缓存是否过期;协商策略发生在请求中,用于判断缓存资源是否更新;存储策略发生在请求后,用于决定是否缓存相应的资源
触发浏览器访问资源的7种方式
1、地址栏输入url并回车
2、链接跳转
3、前进、后退
4、window.open()打开新的标签页
5、从收藏栏打开链接
6、f5刷新页面
7、ctrl+f5强制刷新页面
这几种不同的方式,缓存的策略是不同的
??注意,chrome中,不改变内容直接地址栏回车,等价于f5刷新页面。其他浏览器就是上图中的正常流程
webkit资源分为主资源和派生资源,主资源是地址栏输入url后请求返回的资源,派生资源是主资源中所引用的js,css和图片
缓存的基础知识
缓存的优先级:
先判断强缓存(Cache-Control中设置max-age)=〉再判断协商缓存(Cache-Control中设置的max-age过期或者设置为no-cache)=〉协商缓存中ETag字段 =〉协商缓存中的Last-Modified字段
各类缓存的优缺点
待补充...
缓存的最佳实践
待补充...
cookie、session、token
由于Http是无状态协议,服务器从网络连接上无从得知客户的身份,无法让客户保持登录的状态。因此需要用到cookie、session、token来管理会话。
Session:抽象的定义,在不同场合代表的含义不同。代表浏览器与服务器之间的一次会话过程(指从浏览器打开到关闭的期间);也指在客户端登录后存储在服务端的,用以区分用户身份的信息(以sessionId展示在客户端)。
Cookie:保存在浏览器上的小文本文件,用来存储用户信息的。Cookie信息是存储在浏览器中的,根据Expires与Max-age设置有效期,如果没有设置,就默认为Session,即关闭浏览器时失效。
其他本地存储,有localStorage、sessionStorage
cookie使用方式
//无论是客户端设置的cookie信息还是服务端设置的,都会存储在浏览器中,并且在每次http发起请求时,都会自动携带。
//客户端,只能设置这几个属性name, value, expires, domain, path, secure
//设置多个cookie,需要单独调用document.cookie设置
document.cookie=“sessionId=XXXXXXX;domain=ucloud.cn;path=/icp;Expires=Wed, 21 Oct 2015 07:28:00 GMT;Secure;HttpOnly”
document.cookie=“name=karla;domain=ucloud.cn;path=/icp;Expires=Wed, 21 Oct 2015 07:28:00 GMT;Secure;HttpOnly”
//服务端,response使用set-cookie的属性添加
var express = require(‘express‘);
// 可以直接使用req.cookies.cname来访问cookie
var cookie = require(‘cookie-parser‘);
// 创建app对象
var app = express();
app.use(cookie())
// 设置cookie
app.get(‘/setc‘,function(req,res){
res.cookie(‘resc‘, ‘设置到cookie里的值‘, { expires: new Date(Date.now() + 900000), httpOnly: true });
res.end(‘cookies set ok‘)
})
// 在3000端口监听http请求
app.listen(3000);
cookie属性的权限
Cookie 不能跨域;只能设置自己域和顶域的cookie;子域能访问顶域的cookie(共享)
Name:一个cookie的名称
Value:一个cookie的值
Domain:可以访问此cookie的域名
*域名:只能设置domain为*域名,不能设置二级/三级域名,否则cookie无法生成
二级域名:能读取设置了domain为*域名或自身的cookie,不能读取其他二级域名的cookie
Path:可以访问此cookie的页面路径,比如domain为abc.com,path为/test那么只有abc.com/test页面才能读取此cookie
Expires/Max-Age:Expires:此cookie的超时时间,若设置为一个时间,那么当到达此时间后,cookie失效;不设置的话,默认值为Session,意思是cookie会和session一起失效,也就是当浏览器关闭时(使整个浏览器关闭,而不是标签页),此cookie才失效
Max-Age:cookie 失效的时间,单位秒。如果为整数,则该 cookie 在 maxAge 秒后失效。如果为负数,该 cookie 为临时 cookie ,关闭浏览器即失效,浏览器也不会以任何形式保存该 cookie 。如果为 0,表示删除该 cookie 。默认为 -1。
Size:此cookie的大小
HttpOnly:若此属性值为true,则只有http请求中带有此cookie值,使用document.cookie访问不到此cookie。
Secure:设置是否只能通过https来传递此条cookie
SameSite:sameSite-cookies 是一种机制,用于定义 cookie 如何跨域发送,其目的主要是为了尝试阻止 CSRF (Cross-site request forgery 跨站请求伪造)以及 XSSI (Cross Site Script Inclusion (XSSI) 跨站脚本包含)攻击。
Priority:优先级
(下图为我司登录官网后浏览器存储的cookie)
Session识别用户信息、保持登录状态的一种方案
- 使用Session保持登录状态并识别用户信息的方是之一:依赖与cookie,服务端根据用户信息,生成唯一SessionID,并设置在cookie中,返回给客户端。客户端在往后每一次http请求时,自动携带sessionId,服务端可根据SessionID来判断请求是否合法有效,以及请求的是哪个用户。
- 使用Session保持登录状态并识别用户信息的方是之二:也可直接将sessionID返回给客户端,客户端每次以QueryString方式,将sessionID拼接在请求的url上,但不太安全
Session的存储方式
服务端只是给 cookie 一个 sessionId,而 session 的具体内容(可能包含用户信息、session 状态等),要自己存一下。存储的方式有几种:
- Redis(推荐):内存型数据库,以 key-value 的形式存,正合 sessionId-sessionData 的场景;且访问快。
- 内存:直接放到变量里。一旦服务重启就没了。
- 数据库:普通数据库。性能不高。
Session 的过期和销毁
很简单,只要把存储的 session 数据销毁就可以。
Session扩展性问题:
服务器集群的情况:单机当然没问题, 如果是服务器集群, 或者是跨域的服务导向架构, 这就要求session数据共享,每台服务器都能够读取session。
举例来说, A网站和B网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?这个问题就是如何实现单点登录的问题
- Nginx ip_hash 策略,服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。
- Session复制:任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。
node.js使用session,可以用express-session的npm包依赖,提供了cookie读写,session读写的封装api
Token(令牌)
Acesss Token:访问接口时所需要的凭证
简单 token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)
JWT为Token方案的一种
JWT介绍:阮一峰JWT原理和用法教程:http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
Cookie与Session的区别:
1、数据存放位置不同:
cookie数据存在客户端,session数据存放在服务端
2、数据存储大小不同
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie, 而session存储在服务端,浏览器没有对其限制
3、安全性不同
Cookie的安全性一般,他人可通过分析存放在本地的Cookie并进行Cookie欺骗。在安全性第一的前提下,选择Session更优。重要交互信息比如权限等就要放在Session中,一般的信息记录放Cookie就好了
4、Session 的运行依赖Session ID,而 Session ID 是存在 Cookie 中的,也就是说,如果浏览器禁用了 Cookie,Session 也会失效(但是可以通过其它方式实现,比如在 url 中传递 Session ID)
5、session存储在服务端,当访问的用户积累到一定量时,对服务器来说也是有性能消耗的压力
6、session不能支持A服务登录后,打开(跨域)B服务无需登录的场景。