摘要:狀態(tài)行,由協(xié)議版本號,狀態(tài)碼,狀態(tài)消息三部分組成。第四次揮手收到后,進(jìn)入狀態(tài),接著發(fā)送一個給,確認(rèn)序號為收到序號,進(jìn)入狀態(tài),完成四次揮手。否則,返回最新的資源。
題庫長期更新維護(hù) css部分 rem原理
rem布局的本質(zhì)是等比縮放,一般是基于寬度,假設(shè)將屏幕寬度分為100份,每份寬度是1rem,1rem的寬度是屏幕寬度/100,,然后子元素設(shè)置rem單位的屬性,
通過改變html元素的字體大小,就可以設(shè)置子元素的實際大小。
rem布局加載閃爍的問題
解決方案,媒體查詢設(shè)置根元素字體大小,比如設(shè)計稿是750px;對應(yīng)的開發(fā)方式是1rem=100px,那375px的font-size 大小就是50px(具體方法可以百度一下)
比rem更好的方案(缺點(diǎn)兼容不好)
vw(1vw是視口寬度的1%,100vw就是視口寬度),vh(100vh就是視口高度)
實現(xiàn)三欄布局(兩側(cè)定寬,中間自適應(yīng))采用了 absolute,導(dǎo)致父元素脫離了文檔流,那所有的子元素也需要脫離文檔流。如果頁面復(fù)雜,那開發(fā)的難度可想而知
利用浮動 當(dāng)中間內(nèi)容高于兩側(cè)時,兩側(cè)高度不會隨中間內(nèi)容變高而變高
彈性盒子布局(flex)
利用負(fù)邊距和浮動,實現(xiàn)起來比較復(fù)雜
利用網(wǎng)格布局
.container { display: grid; grid-template-columns: 100px auto 200px; }BFC(塊級格式化上下文)
BFC 的原理
其實也就是 BFC 的渲染規(guī)則(能說出以下四點(diǎn)就夠了)。包括:
1. BFC 內(nèi)部的子元素,在垂直方向,邊距會發(fā)生重疊。 2. BFC在頁面中是獨(dú)立的容器,外面的元素不會影響里面的元素,反之亦然。 3. BFC區(qū)域不與旁邊的float box區(qū)域重疊。(可以用來清除浮動帶來的影響)。 4. 計算BFC的高度時,浮動的子元素也參與計算。
如何生成BFC
方法1:overflow: 不為visible,可以讓屬性是 hidden、auto?!咀畛S谩?/p>
方法2:浮動中:float的屬性值不為none。意思是,只要設(shè)置了浮動,當(dāng)前元素就創(chuàng)建了BFC。
方法3:定位中:只要posiiton的值不是 static或者是relative即可,可以是absolute或fixed,也就生成了一個BFC。
方法4:display為inline-block, table-cell, table-caption, flex, inline-flex
BFC應(yīng)用
阻止margin重疊
可以包含浮動元素 —— 清除內(nèi)部浮動(清除浮動的原理是兩個div都位于同一個 BFC 區(qū)域之中)
自適應(yīng)兩欄布局
可以阻止元素被浮動元素覆蓋
flex(面試常問,略) js部分 call, apply, bind區(qū)別? 怎么實現(xiàn)call,apply方法Function.prototype.myBind = function(content) { if(type of this !="function"){ throw Error("not a function") } let _this = this; let args = [...arguments].slice(1) let resFn=function(){ return _this.apply(this instanceof resFn?this:content,content.concat(...arguments)) } return resFn }; /** * 每個函數(shù)都可以調(diào)用call方法,來改變當(dāng)前這個函數(shù)執(zhí)行的this關(guān)鍵字,并且支持傳入?yún)?shù) */ Function.prototype.myCall=function(context=window){ context.fn = this;//此處this是指調(diào)用myCall的function let args=[...arguments].slice(1); let result=content.fn(...args) //將this指向銷毀 delete context.fn; return result; } /** * apply函數(shù)傳入的是this指向和參數(shù)數(shù)組 */ Function.prototype.myApply = function(context=window) { context.fn = this; let result; if(arguments[1]){ result=context.fn(...arguments[1]) }else{ result=context.fn() } //將this指向銷毀 delete context.fn; return result; }函數(shù)柯里化 js繼承,構(gòu)造函數(shù),原型鏈,構(gòu)造函數(shù)、原型鏈組合式繼承,寄生式組合繼承,Object.create polyfill; 數(shù)組去重
[...new Set(arr]
var arr = [1,2,1,2,3,5,4,5,3,4,4,4,4], init=[] var result = arr.sort().reduce((init, current)=>{ console.log(init,current) if(init.length===0 || init[init.length-1]!==current){ init.push(current); } return init; }, []); console.log(result);//1,2,3,4,5防抖節(jié)流
var deBounce=function(fn,wait=300){ let timer return function(){ if(timer){ clearTimeOut(timer) } timer=setTimeOut(()=>{ fn.apply(this,arguments) },wait) } } var throttle = function (fn, wait = 300) { let prev = +new Date(); return function () { const args = argument, now = +new Date(); if (now > prev + wait) { prev = now; fn.apply(this, args) } } }實現(xiàn)Promise思路
//0 pending,1 resolve,2 reject function Promise(fn) {... this._state = 0 // 狀態(tài)標(biāo)記 doResolve(fn, this) } function doResolve(fn, self) { var done = false // 保證只執(zhí)行一個監(jiān)聽 try { fn(function(value) { if (done) return done = true resolve(self, value) }, function(reason) { if (done) return; done = true reject(self, value) }) } catch (err) { if (done) return done = true reject(self, err) } } function resolve(self, newValue) { try { self._state = 1; ... } catch (err) { reject(self, err) } } function reject(self, newValue) { self._state = 2; ... if (!self._handled) { Promise._unhandledRejectionFn(self._value); } }實現(xiàn)深拷貝
funtion deepCopy(obj){ let result; if(typeofObj=="object"){ //復(fù)雜數(shù)據(jù)類型 result=obj.constructor==Array?[]:{} for (let i in obj){ result[i]=typeof obj[i]=="object"?deepCopy(obj[i]):obj[i] } }else{ //簡單數(shù)據(jù)類型 result=obj } return result }正則實現(xiàn)千位分隔符
function commafy(num) { return num && num .toString() .replace(/(d)(?=(d{3})+.)/g, function($0, $1) { return $1 + ","; }); } console.log(commafy(1312567.903000))js事件循環(huán)
javascript是單線程語言,任務(wù)設(shè)計成了兩類,同步任務(wù)和異步任務(wù)
同步和異步任務(wù)分別進(jìn)入不同的執(zhí)行“場所”,同步進(jìn)入主線程,異步進(jìn)入Event Table并注冊函數(shù)。當(dāng)指定的事情完成時,Event Table會將這個函數(shù)移入Event Queue。主線程內(nèi)的任務(wù)執(zhí)行完畢為空,回去了Event Queue讀取對應(yīng)的函數(shù),進(jìn)入主線程。
上述過程會不斷重復(fù),也就是常說的Event Loop(事件循環(huán))。
但是,JS異步還有一個機(jī)制,就是遇到宏任務(wù),先執(zhí)行宏任務(wù),將宏任務(wù)放入event queue,然后再執(zhí)行微任務(wù),將微任務(wù)放入eventqueue,但是,這兩個queue不是一個queue。當(dāng)你往外拿的時候先從微任務(wù)里拿這個回調(diào)函數(shù),然后再從宏任務(wù)的queue拿宏任務(wù)的回調(diào)函數(shù)
宏任務(wù)一般包括:整體代碼script,setTimeout,setInterval。
微任務(wù):Promise,process.nextTick
事件捕獲
處于目標(biāo)階段
事件冒泡階段
事件委托 事件委托是指將事件綁定目標(biāo)元素的到父元素上,利用冒泡機(jī)制觸發(fā)該事件
可以減少事件注冊,節(jié)省大量內(nèi)存占用可以將事件應(yīng)用于動態(tài)添加的子元素上
event.target返回觸發(fā)事件的元素
event.currentTarget返回綁定事件的元素
new的過程以及實現(xiàn)new//方法1 function create(){ //1.創(chuàng)建一個空對象 let obj={} //2.獲取構(gòu)造函數(shù) let Con=[].shift.call(arguments) //3.設(shè)置空對象的原型 obj._proto_=Con.prototype //4.綁定this并執(zhí)行構(gòu)造函數(shù),給新對象添加屬性和方法 let result=Con.apply(obj,arguments) //5.確保返回值為對象 return result instanceof Object?result:obj } //方法2 //通過分析原生的new方法可以看出,在new一個函數(shù)的時候, // 會返回一個func同時在這個func里面會返回一個對象Object, // 這個對象包含父類func的屬性以及隱藏的__proto__ function New(f) { //返回一個func return function () { var o = {"__proto__": f.prototype}; f.apply(o, arguments);//繼承父類的屬性 return o; //返回一個Object } }封裝ajax
/* 封裝ajax函數(shù) * @param {string}opt.type http連接的方式,包括POST和GET兩種方式 * @param {string}opt.url 發(fā)送請求的url * @param {boolean}opt.async 是否為異步請求,true為異步的,false為同步的 * @param {object}opt.data 發(fā)送的參數(shù),格式為對象類型 * @param {function}opt.success ajax發(fā)送并接收成功調(diào)用的回調(diào)函數(shù) */ function myAjax(opt){ opt = opt || {}; opt.method = opt.method.toUpperCase() || "POST"; opt.url = opt.url || ""; opt.async = opt.async || true; opt.data = opt.data || null; opt.success = opt.success || function () {} let xmlHttp = null; if (XMLHttpRequest) { xmlHttp = new XMLHttpRequest(); }else{ xmlHttp =new ActiveXObject("Microsoft.XMLHTTP") } let params; for (var key in opt.data){ params.push(key + "=" + opt.data[key]); } let postData = params.join("&"); if (opt.method.toUpperCase() === "POST") { xmlHttp.open(opt.method, opt.url, opt.async); xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); xmlHttp.send(postData); }else if (opt.method.toUpperCase() === "GET") { xmlHttp.open(opt.method, opt.url + "?" + postData, opt.async); xmlHttp.send(null); } xmlHttp.onreadystatechange= function () { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { opt.success(xmlHttp.responseText);//如果是json數(shù)據(jù)可以在這使用opt.success(JSON.parse( xmlHttp.responseText)) } }; }url拿參數(shù)
var url = "http://www.taobao.com/index.php?key0=0&key1=1&key2=2"; function parseQueryString(url){ var str = url.split("?")[1], //通過?得到一個數(shù)組,取?后面的參數(shù) items = str.split("&"); //分割成數(shù)組 var arr,name,value; for(var i=0; iHTTP部分 http協(xié)議 HTTP協(xié)議(超文本傳輸協(xié)議)
1.0 協(xié)議缺陷:
無法復(fù)用鏈接,完成即斷開,重新慢啟動和 TCP 3次握手
head of line blocking: 線頭阻塞,導(dǎo)致請求之間互相影響
1.1 改進(jìn):
長連接(默認(rèn) keep-alive),復(fù)用
host 字段指定對應(yīng)的虛擬站點(diǎn)
新增功能:
斷點(diǎn)續(xù)傳
身份認(rèn)證
狀態(tài)管理
cache 緩存
Cache-Control
Expires
Last-Modified
Etag
2.0:
多路復(fù)用
二進(jìn)制分幀層: 應(yīng)用層和傳輸層之間
首部壓縮
服務(wù)端推送
HTTP之請求消息Request
請求行(request line)、請求頭部(header)、空行和請求數(shù)據(jù)四個部分組成。
請求行,用來說明請求類型,要訪問的資源以及所使用的HTTP版本.
請求頭部,緊接著請求行(即第一行)之后的部分,用來說明服務(wù)器要使用的附加信息
空行,請求頭部后面的空行是必須的
請求數(shù)據(jù)也叫主體,可以添加任意的其他數(shù)據(jù)。
HTTP之響應(yīng)消息Response
HTTP響應(yīng)也由四個部分組成,分別是:狀態(tài)行、消息報頭、空行和響應(yīng)正文。
狀態(tài)行,由HTTP協(xié)議版本號, 狀態(tài)碼, 狀態(tài)消息 三部分組成。
消息報頭,用來說明客戶端要使用的一些附加信息
第三部分:空行,消息報頭后面的空行是必須的
第四部分:響應(yīng)正文,服務(wù)器返回給客戶端的文本信息。
在瀏覽器地址欄鍵入URL,按下回車之后會經(jīng)歷以下流程:瀏覽器向 DNS 服務(wù)器請求解析該 URL 中的域名所對應(yīng)的 IP 地址;
建立TCP連接(三次握手);
瀏覽器發(fā)出讀取文件(URL 中域名后面部分對應(yīng)的文件)的HTTP 請求,該請求報文作為 TCP 三次握手的第三個報文的數(shù)據(jù)發(fā)送給服務(wù)器;
服務(wù)器對瀏覽器請求作出響應(yīng),并把對應(yīng)的 html 文本發(fā)送給瀏覽器;
釋放 TCP連接(四次揮手);
瀏覽器將該 html 文本并顯示內(nèi)容;
三次握手SYN (同步序列編號)ACK(確認(rèn)字符)
第一次握手:Client將標(biāo)志位SYN置為1,隨機(jī)產(chǎn)生一個值seq=J,并將該數(shù)據(jù)包發(fā)送給Server,Client進(jìn)入SYN_SENT狀態(tài),等待Server確認(rèn)。
第二次握手:Server收到數(shù)據(jù)包后由標(biāo)志位SYN=1知道Client請求建立連接,Server將標(biāo)志位SYN和ACK都置為1,ack=J+1,隨機(jī)產(chǎn)生一個值seq=K,并將該數(shù)據(jù)包發(fā)送給Client以確認(rèn)連接請求,Server進(jìn)入SYN_RCVD狀態(tài)。
第三次握手:Client收到確認(rèn)后,檢查ack是否為J+1,ACK是否為1,如果正確則將標(biāo)志位ACK置為1,ack=K+1,并將該數(shù)據(jù)包發(fā)送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,Client和Server進(jìn)入ESTABLISHED狀態(tài),完成三次握手,隨后Client與Server之間可以開始傳輸數(shù)據(jù)了。
四次揮手第一次揮手:Client發(fā)送一個FIN,用來關(guān)閉Client到Server的數(shù)據(jù)傳送,Client進(jìn)入FIN_WAIT_1狀態(tài)。
第二次揮手:Server收到FIN后,發(fā)送一個ACK給Client,確認(rèn)序號為收到序號+1(與SYN相同,一個FIN占用一個序號),Server進(jìn)入CLOSE_WAIT狀態(tài)。
第三次揮手:Server發(fā)送一個FIN,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進(jìn)入LAST_ACK狀態(tài)。
第四次揮手:Client收到FIN后,Client進(jìn)入TIME_WAIT狀態(tài),接著發(fā)送一個ACK給Server,確認(rèn)序號為收到序號+1,Server進(jìn)入CLOSED狀態(tài),完成四次揮手。
為什么建立連接是三次握手,而關(guān)閉連接卻是四次揮手呢?這是因為服務(wù)端在LISTEN狀態(tài)下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發(fā)送給客戶端。而關(guān)閉連接時,當(dāng)收到對方的FIN報文時,僅僅表示對方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù),己方也未必全部數(shù)據(jù)都發(fā)送給對方了,所以己方可以立即close,也可以發(fā)送一些數(shù)據(jù)給對方后,再發(fā)送FIN報文給對方來表示同意現(xiàn)在關(guān)閉連接,因此,己方ACK和FIN一般都會分開發(fā)送。
網(wǎng)頁生成的過程,大致可以分為五步:html代碼轉(zhuǎn)化為dom
css代碼轉(zhuǎn)化為cssom
結(jié)合dom和cssom,生成一顆渲染樹
生成布局layout,即將所有的渲染樹的節(jié)點(diǎn)進(jìn)行平面合成
將布局繪制paint在屏幕上(可以拓展講一下減少瀏覽器渲染的回流和重繪)
HTTPS的工作原理非對稱加密與對稱加密雙劍合璧,使用非對稱加密算法傳遞用于對稱加密算法的密鑰,然后使用對稱加密算法進(jìn)行信息傳遞。這樣既安全又高效
瀏覽器緩存當(dāng)瀏覽器再次訪問一個已經(jīng)訪問過的資源時,它會這樣做:
看看是否命中強(qiáng)緩存,如果命中,就直接使用緩存了。
如果沒有命中強(qiáng)緩存,就發(fā)請求到服務(wù)器檢查是否命中協(xié)商緩存。
如果命中協(xié)商緩存,服務(wù)器會返回 304 告訴瀏覽器使用本地緩存。
否則,返回最新的資源。
強(qiáng)緩存
Expires
Cache-control
協(xié)商緩存
Last-Modified/If-Modified-Since
Etag/If-None-Match
vue&react Virtual DOM其實 VNode 是對真實 DOM 的一種抽象描述,它的核心定義無非就幾個關(guān)鍵屬性,標(biāo)簽名、數(shù)據(jù)、子節(jié)點(diǎn)、鍵值等,其它屬性都是都是用來擴(kuò)展 VNode 的靈活性以及實現(xiàn)一些特殊 feature 的。由于 VNode 只是用來映射到真實 DOM 的渲染,不需要包含操作 DOM 的方法,因此它是非常輕量和簡單的。
diff算法
Virtual DOM 除了它的數(shù)據(jù)結(jié)構(gòu)的定義,映射到真實的 DOM 實際上要經(jīng)歷 VNode 的 create(用JS對象模擬DOM樹)、diff(比較兩棵虛擬DOM樹的差異)、patch(把差異應(yīng)用到真正的DOM樹上) 等過程。diff算法比較新舊節(jié)點(diǎn)的時候,比較只會在同層級比較,不會跨層級比較
當(dāng)數(shù)據(jù)發(fā)生變化的時候會生成一個新的VNode,然后新VNode和oldNode做對比,發(fā)現(xiàn)不一樣的地方直接修改在真實的dom上,比較新舊節(jié)點(diǎn),一邊比較一邊給真是的dom打補(bǔ)丁
節(jié)點(diǎn)設(shè)置key可以高效的利用dom(key最好不要設(shè)置成index索引)
虛擬DOM diff算法主要就是對以下三種場景進(jìn)行優(yōu)化:
tree diff
對樹進(jìn)行分層比較,兩棵樹只會對同一層次的節(jié)點(diǎn)進(jìn)行比較。(因為 DOM 節(jié)點(diǎn)跨層級的移動操作少到可以忽略不計)
如果父節(jié)點(diǎn)已經(jīng)不存在,則該節(jié)點(diǎn)及其子節(jié)點(diǎn)會被完全刪除掉,不會用于進(jìn)一步的比較。
注意:
React 官方建議不要進(jìn)行 DOM 節(jié)點(diǎn)跨層級的操作,非常影響 React 性能。
在開發(fā)組件時,保持穩(wěn)定的 DOM 結(jié)構(gòu)會有助于性能的提升。例如,可以通過 CSS 隱藏或顯示節(jié)點(diǎn),而不是真的移除或添加 DOM 節(jié)點(diǎn)。component diff
如果是同一類型的組件,按照原策略繼續(xù)比較 virtual DOM tree(tree diff)。
對于同一類型的組件,有可能其 Virtual DOM 沒有任何變化,如果能夠確切的知道這點(diǎn)那可以節(jié)省大量的 diff 運(yùn)算時間,因此 React 允許用戶通過 shouldComponentUpdate() 來判斷該組件是否需要進(jìn)行 diff。
如果不是,直接替換整個組件下的所有子節(jié)點(diǎn)。element diff
對處于同一層級的節(jié)點(diǎn)進(jìn)行對比。
vue的響應(yīng)式原理
這時 React 建議:添加唯一 key 進(jìn)行區(qū)分。雖然只是小小的改動,性能上卻發(fā)生了翻天覆地的變化!
如: A B C D --> B A D C
添加 key 之前: 發(fā)現(xiàn) B != A,則創(chuàng)建并插入 B 至新集合,刪除老集合 A;以此類推,創(chuàng)建并插入 A、D 和 C,刪除 B、C 和 D。
添加 key 之后: B、D 不做任何操作,A、C 進(jìn)行移動操作,即可。
建議:在開發(fā)過程中,盡量減少類似將最后一個節(jié)點(diǎn)移動到列表首部的操作,當(dāng)節(jié)點(diǎn)數(shù)量過大或更新操作過于頻繁時,在一定程度上會影響 React 的渲染性能。
Object.defineProperty(obj, prop, descriptor)
obj 是要在其上定義屬性的對象;prop 是要定義或修改的屬性的名稱;descriptor 是將被定義或修改的屬性描述符。
比較核心的是 descriptor,它有很多可選鍵值,具體的可以去參閱它的文檔。這里我們最關(guān)心的是 get 和 set,get 是一個給屬性提供的 getter 方法,當(dāng)我們訪問了該屬性的時候會觸發(fā) getter 方法;set 是一個給屬性提供的 setter 方法,當(dāng)我們對該屬性做修改的時候會觸發(fā) setter 方法。一旦對象擁有了 getter 和 setter,我們可以簡單地把這個對象稱為響應(yīng)式對象
- 對象遞歸調(diào)用 - 數(shù)組變異方法的解決方法:代理原型/實例方法
observe
observe 方法的作用就是給非 VNode 的對象類型數(shù)據(jù)添加一個 Observer,如果已經(jīng)添加過則直接返回,否則在滿足一定條件下去實例化一個 Observer 對象實例。
observe 的功能就是用來監(jiān)測數(shù)據(jù)的變化.
Observer 是一個類,它的作用是給對象的屬性添加 getter 和 setter,用于依賴收集和派發(fā)更新:
依賴收集和派發(fā)更新
收集依賴的目的是為了當(dāng)這些響應(yīng)式數(shù)據(jù)發(fā)生變化,觸發(fā)它們的 setter 的時候,能知道應(yīng)該通知哪些訂閱者去做相應(yīng)的邏輯處理,我們把這個過程叫派發(fā)更新,其實 Watcher 和 Dep 就是一個非常經(jīng)典的觀察者設(shè)計模式的實現(xiàn)
派發(fā)更新就是數(shù)據(jù)發(fā)生變化的時候,觸發(fā) setter 邏輯,把在依賴過程中訂閱的的所有觀察者,也就是 watcher,都觸發(fā)它們的 update 過程,這個過程又利用了隊列做了進(jìn)一步優(yōu)化,在 nextTick 后執(zhí)行所有 watcher 的 run,最后執(zhí)行它們的回調(diào)函數(shù)
vue編譯Compile的過程主要分以下幾步
parse(生成AST)=> optimize(優(yōu)化靜態(tài)節(jié)點(diǎn)) => generate(生成render function)
// 解析模板字符串生成 AST const ast = parse(template.trim(), options) //優(yōu)化語法樹 optimize(ast, options) //生成代碼 const code = generate(ast, options)vue compute和watch的區(qū)別computed 是計算屬性,依賴其他屬性計算值,并且 computed 的值有緩存,只有當(dāng)計算值變化才會返回內(nèi)容。
watch 監(jiān)聽到值的變化就會執(zhí)行回調(diào),在回調(diào)中可以進(jìn)行一些邏輯操作。
所以一般來說需要依賴別的屬性來動態(tài)獲得值的時候可以使用computed,對于監(jiān)聽到值的變化需要做一些復(fù)雜業(yè)務(wù)邏輯的情況可以使用 watch。
對vuex的理解,單向數(shù)據(jù)流vuex
state: 狀態(tài)中心
mutations: 更改狀態(tài)
actions: 異步更改狀態(tài)
getters: 獲取狀態(tài)
modules: 將state分成多個modules,便于管理
mutations和action的區(qū)別
前端路由的兩種實現(xiàn)原理
Hash模式
window對象提供了onhashchange事件來監(jiān)聽hash值的改變,一旦url中的hash值發(fā)生改變,便會觸發(fā)該事件。
History 模式
popstate監(jiān)聽歷史棧信息變化,變化時重新渲染
使用pushState方法實現(xiàn)添加功能
使用replaceState實現(xiàn)替換功能
前端安全 XSS和CSRFXSS:跨站腳本攻擊,是一種網(wǎng)站應(yīng)用程序的安全漏洞攻擊,是代碼注入的一種。常見方式是將惡意代碼注入合法代碼里隱藏起來,再誘發(fā)惡意代碼,從而進(jìn)行各種各樣的非法活動。
預(yù)防:
使用XSS Filter
輸入過濾,對用戶提交的數(shù)據(jù)進(jìn)行有效性驗證,僅接受指定長度范圍內(nèi)并符合我們期望格式的的內(nèi)容提交,阻止或者忽略除此外的其他任何數(shù)據(jù)。
輸出轉(zhuǎn)義,當(dāng)需要將一個字符串輸出到Web網(wǎng)頁時,同時又不確定這個字符串中是否包括XSS特殊字符,為了確保輸出內(nèi)容的完整性和正確性,輸出HTML屬性時可以使用HTML轉(zhuǎn)義編碼(HTMLEncode)進(jìn)行處理,輸出到中,可以進(jìn)行JS編碼。
使用 HttpOnly Cookie
將重要的cookie標(biāo)記為httponly,這樣的話當(dāng)瀏覽器向Web服務(wù)器發(fā)起請求的時就會帶上cookie字段,但是在js腳本中卻不能訪問這個cookie,這樣就避免了XSS攻擊利用JavaScript的document.cookie獲取cookie。
CSRF:跨站請求偽造,也稱 XSRF,是一種挾制用戶在當(dāng)前已登錄的Web應(yīng)用程序上執(zhí)行非本意的操作的攻擊方法。與 XSS 相比,XSS利用的是用戶對指定網(wǎng)站的信任,CSRF利用的是網(wǎng)站對用戶網(wǎng)頁瀏覽器的信任。
預(yù)防:用戶操作限制——驗證碼機(jī)制
方法:添加驗證碼來識別是不是用戶主動去發(fā)起這個請求,由于一定強(qiáng)度的驗證碼機(jī)器無法識別,因此危險網(wǎng)站不能偽造一個完整的請求。
優(yōu)點(diǎn):簡單粗暴,低成本,可靠,能防范99.99%的攻擊者。
缺點(diǎn):對用戶不友好。
請求來源限制——驗證 HTTP Referer 字段
方法:在HTTP請求頭中有一個字段叫Referer,它記錄了請求的來源地址。 服務(wù)器需要做的是驗證這個來源地址是否合法,如果是來自一些不受信任的網(wǎng)站,則拒絕響應(yīng)。
優(yōu)點(diǎn):零成本,簡單易實現(xiàn)。
缺點(diǎn):由于這個方法嚴(yán)重依賴瀏覽器自身,因此安全性全看瀏覽器。
額外驗證機(jī)制——token的使用
方法:使用token來代替驗證碼驗證。由于黑客并不能拿到和看到cookie里的內(nèi)容,所以無法偽造一個完整的請求?;舅悸啡缦拢?/p>
服務(wù)器隨機(jī)產(chǎn)生token(比如把cookie hash化生成),存在session中,放在cookie中或者以ajax的形式交給前端。
前端發(fā)請求的時候,解析cookie中的token,放到請求url里或者請求頭中。
服務(wù)器驗證token,由于黑客無法得到或者偽造token,所以能防范csrf
面試相關(guān) 正在整理中的問題 寫過webpack loader嗎 vue怎么監(jiān)聽數(shù)組 手寫快排,時間復(fù)雜度,優(yōu)化 webpack用過嗎?搖樹是什么,什么場景下用過? 你遇到過最難的問題是什么 react 虛擬 dom實現(xiàn),diff算法; 手寫快排,怎么優(yōu)化;說下sort實現(xiàn)原理; 解釋一個你最近遇到的技術(shù)挑戰(zhàn)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/109325.html
摘要:在盒模型中,設(shè)置的是的寬度高度,在怪異模式中設(shè)置的是寬度高度。狀態(tài)行,由協(xié)議版本號,狀態(tài)碼,狀態(tài)消息三部分組成。第四次揮手收到后,進(jìn)入狀態(tài),接著發(fā)送一個給,確認(rèn)序號為收到序號,進(jìn)入狀態(tài),完成四次揮手。評論區(qū)可以糾錯完善,也可以留言面試題目 css部分 rem原理 rem布局的本質(zhì)是等比縮放,一般是基于寬度,假設(shè)將屏幕寬度分為100份,每份寬度是1rem,1rem的寬度是屏幕寬度/100,,...
摘要:獲取的對象范圍方法獲取的是最終應(yīng)用在元素上的所有屬性對象即使沒有代碼,也會把默認(rèn)的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對于一個光禿禿的元素,方法返回對象中屬性值如果有就是據(jù)我測試不同環(huán)境結(jié)果可能有差異而就是。 花了很長時間整理的前端面試資源,喜歡請大家不要吝嗇star~ 別只收藏,點(diǎn)個贊,點(diǎn)個star再走哈~ 持續(xù)更新中……,可以關(guān)注下github 項目地址 https:...
摘要:三年百度,五年阿里,阿里架構(gòu)師淺談我是如何順利進(jìn)入前些天在我群里認(rèn)識了以為挺有意思的老哥,他也是工作年多技術(shù)和面試都不差,最近也是在找工作,是從京城來魔都的,也和他撈了不少。 說來慚愧,也不怕你們笑話。做開發(fā)8年多,到目前還是一名不折不扣的掃地僧。年前的辭職,到現(xiàn)在還在家靜養(yǎng)中。其實也沒什么,就是回家總結(jié)一下自己這些年來在外工作與面試等做一個簡單的總結(jié)與反思。做一下自己后面一個人生規(guī)劃...
閱讀 2624·2021-11-22 09:34
閱讀 3602·2021-11-15 11:37
閱讀 2422·2021-09-13 10:37
閱讀 2179·2021-09-04 16:40
閱讀 1787·2021-09-02 15:40
閱讀 2516·2019-08-30 13:14
閱讀 3391·2019-08-29 13:42
閱讀 2006·2019-08-29 13:02