本篇主要爲學習筆記,涉及到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的庫進行請求,又該如何實現呢?
本文大多內容來自下面的資源,推薦閱讀。不知道截圖是否侵權,若有侵權聯繫刪除。