本篇主要为学习笔记,涉及到HTTP/一、HTTP/二、CSP、RestfulApi、跨域等等内容。javascript
从输入url到返回HTTP响应,浏览器的处理流程?css
HTTP协议依赖其它协议实现,如IP、TCP、UDP、DNS、ARP协议等html
TCP/IP,分层协议前端
ARP协议,将IP转为MAC java
DNS协议,将域名转为IP ios
HTTP报文依赖上述协议进行传入,其传输过程以下: web
在传输过程当中,有一个很重要的的概念,什么是TCP三次握手? ajax
从更普遍的角度来看,当浏览器输入url后,各种协议如何协同工做? 算法
还有一个很是重要的概念::chrome
http://b.edu.51cto.com
ftp://abc/a.txt
HTTP主要用于客户端和服务端之间的通讯及通讯数据转发服务,重点了解下通讯数据转发应用:
代理,接受客户端发送的请求并转发给服务器,接受服务器的响应并转发给客户端
网关,接收客户端的请求,就像本身拥有资源同样,对请求进行处理(转发局域网内其余服务器的数据,局域通讯的协议能够不是http)
隧道,相隔甚远的客户端和服务器之间进行中转,并保持双方通讯链接的应用程序
代理的意义:缓存代理(将服务端资源缓存在代理服务器),透明代理(不对报文进行任何加工处理),非透明代理(对报文内容进行处理)
网关的意义:将非HTTP服务转为HTTP服务,提升通讯的安全性?
隧道的意义:隧道可按照要求创建一条与其余服务器的通讯线路,使用SSL等加密手段进行通讯;隧道的目的是确保客户端可以与服务器进行安全的通讯;隧道自己不会去解析HTTP请求,请求和响应原样传输;隧道会在通讯双方断开链接时结束。
缓存是指代理服务器或客户端本地磁盘内保存的资源副本,利用缓存能够减小对源服务器的访问,也就节省了通讯流量和时间。缓存能够设置有效时间,若是资源过时则从新请求。
不对请求和响应之间的通讯状态(如登陆态)保存,不作持久化处理,好处就是简单!
请求完成后断开tcp链接,好处就是减小服务器CPU和内存消耗
随着Web愈来愈复杂,用户期待更好的体验,如速度更快、保留登陆态等等,因而就须要进行改进。
如何要保留用户的状态(如登陆态),因而有了Cookie技术:
TCP的链接过程是至关复杂的,须要经历3次握手才能传递数据。能不能节省握手时间,因而就有了持久链接技术:
HTTP/1.1开始支持持久化链接,且默认为持久链接;持久链接使用字段:
connection:keep-alive
;Chrome为了进一步提高速度,会为单个域名开启6个线程去请求资源。
传统的HTTP是请求/响应模式的,单个请求必需要等待响应完成后才能继续其它请求。如何节省请求等待时间,因而就有了管线化技术:
管线化能够克服同域并行请求限制带来的阻塞,把全部请求一块儿发给服务器,服务器按顺序响应(依赖于持久链接技术)。
学习HTTP必需要了解报文,透过报文结构能够了解请求/响应附加的各类信息,如:
实体类型,请求数据的类型multipart/form-data、application/json
获取部份内容的范围请求(断点恢复下载),设定获取资源范围,Range: bytes=5001-10000
内容协商,客户端和服务端就响应的资源内容进行交涉,而后提供给客户端最为适合的资源,如中英文界面:Accept、Accept-Charset、Accept-Encoding、Accept-Language、Content-Language
缓存控制信息,如Cache-Control、Expires
HTTP请求报文
HTTP响应报文
HTTP报文结构
HTTP的请求方法: get/post/put/delete/head/option/trace/connect
业务中经常使用Post和Get,他们有什么区别?
1. get在浏览器回退是无害的,而post会再次请求
2. get请求的url地址能够被收藏,而post不能够?
3. get请求浏览器会主动缓存,而post不会,post须要手动使用localStorage等
4. get只支持URI编码,而post支持多种编码形式
5. get请求参数会被完整的保留在浏览器历史记录中,而post中的参数不会被保留
6. get请求携带的数据长度有限制,而post没有限制
7. get没有post安全,由于参数直接在url中,因此不能传递敏感信息
8. get参数经过url传递,而post经过请求体(request Body)
复制代码
HTTP的状态码:
200,请求被服务器正常处理
204,请求成功,可是响应报文不含实体主体部分,收到204响应,浏览器页面不发生更新。【应用:通常在只须要从客户端往服务器发送信息,而对客户端不须要发送新信息内容的状况下使用】
206,客户端进行范围请求,服务器成功处理并返回有Content-Range指定范围的实体内容
301,永久性重定向。表示请求的资源被分配到新的URI上,之后应使用资源如今所指的URI。若是保存了书签,打开后依就会重定向(浏览器记住了重定向地址)【应用:res.location + res.sendStatus 配合使用等价于 res.redirect,重定向】
302,临时重定向,请求的资源被分配到新的URI上,但愿用户本次使用新的URI访问(永久重定向时,即便修改重启了服务端源码,chrome浏览器依旧进行重定向跳转)
303,同302,可是要求指定客户端使用get方法请求新的URI
304,客户端发送附带条件的请求,若是为知足条件则返回304,知足则容许访问
307,与302相同,禁止从post请求变成get请求??
400,请求报文中存在语法错误,须要修改请求的内容后再次发送请求。浏览器会像200同样对待该状态码?(200如何处理的?)
401,请求须要经过http认证(BASIC认证,DIGEST认证),若是携带认证信息依就返回401则表示认证失败
403,请求访问的资源被服务器拒绝
404,服务器没法找到请求的资源,或者服务端拒绝请求且不想说明理由时使用。
500,服务端在执行请求时发生错误,可能web应用中存在的bug或临时故障
503,服务器处于超负载或者正在进行停机维护,没法处理请求
复制代码
HTTP首部字段:
首部字段根据类型或缓存行为进行分类:
通用首部字段、请求首部字段、响应首部字段、实体首部字段 首部字段根据缓存行为分为两中类型,端到端首部字段(请求响应的最终接收目标)、逐跳首部字段(会因经过缓存或代理服务器再也不转发,在HTTP/1.1后必须配合connection才能使用!)
# 客户端请求首部
GET / HTTP/1.1
Upgrade: HTTP/1.1
Connection: Upgrade
# 通过代理服务器后发送给Web服务器的首部
GET / HTTP/1.1
复制代码
通用首部字段
请求首部字段
响应首部字段
实体首部字段
逐跳首部字段
通用首部字段详细介绍:
Cache-Control:控制缓存逻辑
Connection:管理持久连接,配合逐跳首部字段使用
pragma:再也不推荐使用,与cache-control功能基本相同
Date:报文建立的日期和事件
trailer:待查询
transfer-encoding:逐跳传输消息首部,用于指定编码形式
upgrade:询问服务器是否支持其余协议,或者http更高协议??须要配合connection使用??
via:追踪客户端和服务端之间请求响应报文的传输路径,避免循环请求
warning: 报文存在的问题,部分警告码只能用于缓存代理服务器的响应报文
请求首部字段详细介绍
从客户端发出,用于补充请求的附加信息、客户端信息、对响应内容相关的优先级等
Accept,告知服务器,用户(或代理)可以处理的媒体类型及媒体类型的相对优先级,如Accept: text/plain; 1=0.3, text/html
Accept-Charset,告知服务器用户(或代理)支持的字符集及字符集的相对优先顺序,如Accept-Charset:utf-8,iso-8859-1;q=0.5
Content-Type响应字段返回服务器的选择,如
Content-Type: text/html; charset=utf-8
Accept-Encoding,告知服务器用户(或代理)支持的内容编码及内容的编码的优先级顺序。如Accept-Encoding:gzip、compress、deflate、identity
Content-Encoding响应字段返回服务器的选择,如
Content-Encoding: gzip
Accept-Language,告知服务器用户代理可以处理的天然语言集(中文或英文)。如Accept-Language: en-US,en;q=0.5
Content-Language响应字段返回服务器的选择,如
Content-Language: de-DE
Authorization,告知服务器用于验证用户身份的凭证,如Authorization: Basic abcdefg
Expect: 服务器只有知足此指望条件状况下才能妥善地处理请求。如Expect:100-continue
(客户端要发送一个体积很大的消息体),等待状态码100后再发送消息体?
Form,电子邮箱
Host,虚拟主机运行在同一个ip上,使用此字段加以区分
If-Match,条件请求,服务端接受附带条件的请求后,只有判断为真时才执行请求。(if-match,资源ETag值相同)
if-Modified-Since,资源更新时间;;;;若是资源未更新返回状态码304Not Modified
if-None-Match,与if-Match相反
If-Range,若字段值与Etag或更新日期匹配,则继续做为范围请求。配合Range字段一块儿使用。若不一致则忽略返回,返回所有资源。(节约请求次数???)
Max-Forwards,设定请求被代理服务器转发的次数。
proxy-Authorization
Range,指定获取资源的范围,如Range: bytes=5001-10000(成功返回206,失败返回200+所有资源)
Referer,告诉服务器请求的原始资源的URI,经常使用于防盗链。
TE,告诉服务端客户端可以响应的传输编码方式及相对优先级,与Accept-Encoding功能很相像?
userAgent:将建立请求的浏览器和用户代理名称等信息传达给服务器。
响应首部字段详细介绍:
用于补充响应的附加信息、服务端信息、以及对客户端的附加要求等信息。
Accept-Ranges: bytes可处理范围请求,none不可处理范围请求
Age,源服务器在多久前建立了响应,字段值为秒。???
Etag,实体标识,uri相同时,借助etag区分文件
Location,将响应接收方引导到某个与请求URI位置不一样的资源,基本上配合3XX:Redirection,进行重定向,。
Proxy-Authenticate,
Retry-After,高知客户端应该在多久以后再次发送请求。配合状态码503Service Unavailable。或3XX Redirect一块儿使用。能够指定具体日期,或者建立响应后的秒数
Server,告知客户端服务器上安装的http服务程序信息,如Server:Apache/2.2.6(Unix) PHP/5.2.5
Vary
www-Authenticate
实体首部字段详细介绍
请求报文和响应报文中实体部分使用的首部,用于补充内容的更新时间等与实体相关的信息
text/html;application/x-www-form-urlencoded
Cookie字段详细介绍
set-cookie,服务端下发cookie,set-Cookie:status=enable; expires=Tue, 05 Jul 2011 07:26:31 GMT path=/ domain=.hack.jp secure httponly
认证信息的方式一般有:密码,动态令牌、数字证书、生物认证、IC卡。HTTP如何认证?
HTTP使用表单携带密码进行认证,借助cookie、session、jwt等方式管理状态,具体流程以下:
注:服务端如何安全保存密码?密码加盐添加额外信息,再使用散列函数进行处理,最后存储散列值!
存放在客户端,主要由服务器下发set-cookie
。cookie符合同源策略,每次请求时会自动携带。cookie有大小限制,单个限制3kb。
存放在服务端,用于记录用户状态。依赖于cookie技术(下发sessionId
cookie)。当访客较多时,占用服务端性能。
session-cookie技术,session保存在服务端安全,能够手动清除session,兼容性好。可是在跨域场景下不够友好,基于cookie技术很容易被CRSF(跨站请求伪造)。
JWT技术,服务端将信息进行加密(还会设置验签)下发给客户端,客户端存储在sessionStorage或localStorage中,每次请求中Authorization
字段携带jwt信息,服务端验证经过后返回信息。
理解网络安全:
HTTPS借助SSL或TLS协议,加密HTTP通讯内容,基于证书服务实现身份认证,即http + 加密 + 认证 + 完整性保护 === https
,可是,加密和解密消耗计算资源,也会使通讯变慢。
共享密钥加密:
公私钥加密:
混合加密机制:
引入证书证实公钥是正确的:
了解了加解密原理,了解了证书原理,HTTPS创建通讯的全过程:
传统的HTTP通讯过程,每次请求时都返回整个页面,没法作到局部更新:
AJAX技术,使用js执行异步网路请求,能够实现局部更新:
Comet技术,收到请求后服务端会等待内容更新,再返回响应,实现了服务端推送,可是为了维持连接,须要消耗更多的资源:
轮询效率低,因此有了全双工通讯websocket,其最经常使用场景---聊天软件
了解浏览器的CSP/同源策略,了解常见的攻击方式,保证业务安全。
前端主要攻击形式:XSS跨站脚本攻击、SQL注入、CSRF跨站请求伪造。
内容安全策略,用于减弱并削弱某些特定类型攻击,包括跨站脚本和数据注入攻击。CSP向后兼容,网页默认会使用同源策略确保安全。
如何使用:
一是能够由服务端下发,而是能够经过meta设置<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
防护原理:
指定浏览器可执行js的来源,避免xss脚本攻击;指定资源加载域;指定资源加载的协议,如强制HTTPS协议。
经常使用字段`default-src/script-src/style-src/img-src/self
同源策略限制了从同一个源加载的文档或脚本如何与来自另外一个源的资源进行交互,同源的定义是:协议/域名/端口 相同。
不符合同源策略的请求,如何实现实现通讯呢?即如何跨域?
跨域限制是浏览器的行为,能够给chrome浏览器设置--disable-web-security --user-data-dir=C:\MyChromeDevUserData
,便可轻松实现跨域,设置教程:www.cnblogs.com/laden666666…
除了上述hack方法,还有以下正规的途径。
Ajax符合同源策略,如何突破ajax跨域限制?即CORS方法!
简单请求的条件
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
)cors请求流程
预请求
对于非简单请求,在正式请求以前会预请求
使用OPTIONS方法,询问浏览器是否容许跨源请求
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
复制代码
Cors比jsonp更强大,支持全部请求类型;而jsonp只支持get请求,可是jsonp支持老版本浏览器,兼容性更好。JSOP的实现代码以下:
function jsonp(src, onsuccess, onerror) {
const callback = 'callback_' + Math.random().toString().substr(1, 6)
window[callback] = function () {
onsuccess && onsuccess.apply(null, arguments)
}
const script = document.createElement('script')
script.setAttribute("type","text/javascript")
script.setAttribute('src', `${src}?jsonp=${callback}`)
script.async = true
script.onload = script.onreadstatechange = function () {
if (!script.readystate && /complete|loaded/.test(script.readystate)) {
script.onload = script.onreadstatechange = null
if (script.parentNode) {
script.parentNode.removeChild(script)
}
window[callback] = null
}
}
script.onerror = function () {
onerror && onerror()
}
document.appendChild(script)
}
复制代码
Webscoket全双工通讯,事件驱动响应,支持跨域通讯。
// 客户端
let ws = new WebSocket('ws://localhost:3000/')
ws.onopen = function() {
ws.send('Hello!');
}
ws.onmessage = function(msg) {
console.log('get Message:', msg.data);
}
// 服务端
const WebSocket = require('ws')
const wss = new WebSocket.Server({port: 3000})
wss.on('connection', function(ws) {
ws.on('message', function (message) {
ws.send(`${message}-server`, err => {
if (err) {
console.log(err)
}
})
})
})
复制代码
以下图演示的攻击原理,上图为正常渲染,下图为攻击方式:
XSS脚本危害很是大,嵌入了可执行脚本能够作不少事情:
XSS根据存储方式分为:
XSS的攻击途径:
<p v-html="from"></p>
,攻击载荷http://localhost:8080/?from=%3Cscript%3Ealert(1)%3C/script%3E
<img src="avatar"/>
,攻击载荷http://localhost:8080/?avatar=1%22onerror=%22alert(1)%22
<p>hello world!</p><script>alert(1)</script>
针对上述攻击方式,如何有效进行防御?
X-XSS-Protection
,针对于反射型xss<>
等特殊符号转义为实体字符集function SaferHTML(templateData) {
let s = templateData[0];
for (let i = 1; i < arguments.length; i++) {
let arg = String(arguments[i]);
// Escape special characters in the substitution.
s += arg.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, ''')
.replace(/ /g, ' ');
// Don't escape special characters in the template.
s += templateData[i];
}
return s;
}
复制代码
[{img: ['src']}]
用户登陆A网站,在B网站诱导用户发起对A网站的请求(第3步),因为同源策略该攻击请求自动携带了cookie。
跨站请求伪造**利用用户登陆态完成业务请求*,能够进行盗取用户资金、冒充用户发帖等行为
针对上述攻击特征,如何进行有效防御?
same-site
属性,同站点才自动携带cookie<input name="csrf" value="xxx" hidden/>
形式,验证请求来源B网站使用iframe将A网站嵌入,诱导用户点击A网站产生交互。用户不知情,可是亲手操做。
如何防御点击劫持?
top.location === window.location
,禁止内嵌针对HTTP传输窃听等安全问题,使用更安全的协议HTTPS
Cookie经常使用于保留登陆态,如何针保证cookie安全?
http-only
禁止JS操做cookiesame-site
避免跨站请求伪造密码用于证实“你是你”,严禁密码明文存储!
密码泄露渠道
哈希算法
使用复杂密码对抗彩虹表,md5(sha1(md5(id+ab83kd+原始密码+81kdso+盐+1lso;$2)))
变化次数越多,密码越复杂,越安全。
传输的安全性
生物特征密码
还有文件上传安全?
避免上传的文件被当成程序进行执行!
基于RestfulAPi,HTTP/1.1引入“资源”概念,将HTTP从一种面向文档的协议完全转变为一种面向资源的协议。而HTTP-2的影响,主要在于更快的速度、更安全的传输。
分析HTTP请求响应流程图,寻找关键性能指标:
通过分析,得出关键性能指标:
网络指标:延迟、带宽、DNS查询、创建链接时间(TCP三次握手)、TLS协商时间(HTTPS链接)
服务器的优化:首字节时间(TTFB,浏览器从发起请求到接受到第一个字节之间的耗时)、内容下载时间(请求资源随后到达时间TTLB)、开始渲染时间(屏幕何时开始显示内容,即用户看到空白页面的时长)、文档加载完成时间(浏览器认为页面加载完毕的时间)
网络的趋势:更多的字节(web内容增加)、更多的资源(引用的资源愈来愈多)、更高的复杂度(web页面渲染复杂度)、更多的域名、更多的TCP连接
缺陷:
优化:
<link rel="dns-prefetch" href="//ajax.googlepis.com">
。<link rel="preconnect" href="" crossorigin>
。部分针对于HTTP/1的优化,在HTTP/2下多是反优化:
HTTP/2协议在设计时考虑考兼容性,任何不支持HTTP/2的客户端都会简单回退到HTTP/1,通常来讲HTTP/2就意味HTTPS,默认开启443端口。
HTTP/2协议大体分为两个部分:分帧层,即h2多路复用能力;数据层,即HTTP数据部分。主要特色:二进制协议、首部压缩、多路复用、加密传输。
链接:初始化一个TCP链接,帧和流在上面传输
帧:请求和响应能够交错甚至多路复用,有利于解决队头阻塞
流:h2连接上独立的、双向的帧序列交换。客户端发起请求,会开启一个流,服务器在这个流上回复。因为有分帧存在,多个请求和响应能够交错,而不会阻塞。
消息:流是用来传输一对请求/响应消息的,h2消息包含HEADERS帧和DATA帧
优先级:h2会分析依赖关系,优先请求最重要的资源
服务端推送:提高单个对象性能的最佳方式,就是在它被用到以前就放到浏览器的缓存里
首部压缩:hpack压缩算法
h2的设计目标是提高性能,可是HTTP/2的速度也有命脉:
RestfulApi内容源自这篇文章:imweb.io/topic/57075…
RestFulApi的主要意义在于将HTTP从面向文档 转为 面向资源
1. 每个URI表明一种资源
2. 客户端和服务器之间,传递这种资源的某种表现层(客户端想要操做服务器,必须经过某种手段,让服务器发生“状态转化”,这种转化是创建在变现层之上的,即Representational State Transfer---RESTfulApi)
3. 客户端经过四个HTTP动词,对服务器资源进行操做,实现“变现层状态转化”
复制代码
状态码
接口要求
实战
http://api.example.com/v1/zoos
待学习补充。
缓存命中流程图:
在资源加载方面浏览器提供了些新的方案---资源提示与指令:
preload:不一样于浏览器预加载,preload能够预加载css和js中定义的资源,并容许决定什么时候应用每一个资源;preload不会阻塞window的onload事件。
<link rel="preload">
prefetch:低优先级的资源提示,容许浏览器在后台(空闲时)获取未来可能用获得的资源,而且将他们存储在浏览器的缓存中。
<link rel="prefetch" href="pic.png">
<link re="dns-prefetch" href="//baidu.com">
prerendering:相似于prefetch,prerendering在后台渲染了整个页面 <link rel="prerender" href="https://www.baidu.com">
preconnect:预先浏览器在一个http请求正式发给服务器前预先执行一些操做,包括DNS解析、TLS协商、TCP握手,这消除了往返延迟并为用户节省了时间。<link rel="preconnect" href="//baidu.com" crossorigin>
先后端使用ajax进行数据传输,经过Content-type
定义数据格式,经常使用的方式以下:
元素标签form的默认编码形式,数据须要转为name=jj&age=17
形式传输,推荐第三方库qs进行数据处理。
// application/www-form-urlencode
function ajaxBy1 () {
let xhr = new XMLHttpRequest()
xhr.open('POST', 'http://localhost')
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
xhr.send('name=jj&age=17')
}
复制代码
元素标签form能够修改enctype=application/form-data
,也能够new FormData()
新建FormData实例对象,这种方案还支持文件上传。
// multipart/form-data
function ajaxBy2 () {
const data = new FormData()
data.append('name', 'jj')
data.append('age', 18)
let xhr = new XMLHttpRequest()
xhr.open('POST', 'http://localhost')
xhr.send(data)
}
复制代码
若是数据结构比较复杂,推荐使用application/json
方式,能够直接传输json对象。
// application/json
function ajaxBy3 () {
const data = {
"name": "jj",
"age": 18
}
let xhr = new XMLHttpRequest()
xhr.open('POST', 'http://localhost:5501')
xhr.setRequestHeader("Content-type","application/json")
xhr.send(JSON.stringify(data))
}
// 断点续传https://cloud.tencent.com/developer/article/1326932
复制代码
若是在业务中使用如axios的库进行请求,又该如何实现呢?
本文大多内容来自下面的资源,推荐阅读。不知道截图是否侵权,若有侵权联系删除。