摘要:狀態(tài)行,由協(xié)議版本號,狀態(tài)碼,狀態(tài)消息三部分組成。第四次揮手收到后,進入狀態(tài),接著發(fā)送一個給,確認序號為收到序號,進入狀態(tài),完成四次揮手。否則,返回最新的資源。
題庫長期更新維護 css部分 rem原理
rem布局的本質(zhì)是等比縮放,一般是基于寬度,假設將屏幕寬度分為100份,每份寬度是1rem,1rem的寬度是屏幕寬度/100,,然后子元素設置rem單位的屬性,
通過改變html元素的字體大小,就可以設置子元素的實際大小。
rem布局加載閃爍的問題
解決方案,媒體查詢設置根元素字體大小,比如設計稿是750px;對應的開發(fā)方式是1rem=100px,那375px的font-size 大小就是50px(具體方法可以百度一下)
比rem更好的方案(缺點兼容不好)
vw(1vw是視口寬度的1%,100vw就是視口寬度),vh(100vh就是視口高度)
實現(xiàn)三欄布局(兩側(cè)定寬,中間自適應)采用了 absolute,導致父元素脫離了文檔流,那所有的子元素也需要脫離文檔流。如果頁面復雜,那開發(fā)的難度可想而知
利用浮動 當中間內(nèi)容高于兩側(cè)時,兩側(cè)高度不會隨中間內(nèi)容變高而變高
彈性盒子布局(flex)
利用負邊距和浮動,實現(xiàn)起來比較復雜
利用網(wǎng)格布局
.container { display: grid; grid-template-columns: 100px auto 200px; }BFC(塊級格式化上下文)
BFC 的原理
其實也就是 BFC 的渲染規(guī)則(能說出以下四點就夠了)。包括:
1. BFC 內(nèi)部的子元素,在垂直方向,邊距會發(fā)生重疊。 2. BFC在頁面中是獨立的容器,外面的元素不會影響里面的元素,反之亦然。 3. BFC區(qū)域不與旁邊的float box區(qū)域重疊。(可以用來清除浮動帶來的影響)。 4. 計算BFC的高度時,浮動的子元素也參與計算。
如何生成BFC
方法1:overflow: 不為visible,可以讓屬性是 hidden、auto?!咀畛S谩?/p>
方法2:浮動中:float的屬性值不為none。意思是,只要設置了浮動,當前元素就創(chuàng)建了BFC。
方法3:定位中:只要posiiton的值不是 static或者是relative即可,可以是absolute或fixed,也就生成了一個BFC。
方法4:display為inline-block, table-cell, table-caption, flex, inline-flex
BFC應用
阻止margin重疊
可以包含浮動元素 —— 清除內(nèi)部浮動(清除浮動的原理是兩個div都位于同一個 BFC 區(qū)域之中)
自適應兩欄布局
可以阻止元素被浮動元素覆蓋
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方法,來改變當前這個函數(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)標記 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"){ //復雜數(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是單線程語言,任務設計成了兩類,同步任務和異步任務
同步和異步任務分別進入不同的執(zhí)行“場所”,同步進入主線程,異步進入Event Table并注冊函數(shù)。當指定的事情完成時,Event Table會將這個函數(shù)移入Event Queue。主線程內(nèi)的任務執(zhí)行完畢為空,回去了Event Queue讀取對應的函數(shù),進入主線程。
上述過程會不斷重復,也就是常說的Event Loop(事件循環(huán))。
但是,JS異步還有一個機制,就是遇到宏任務,先執(zhí)行宏任務,將宏任務放入event queue,然后再執(zhí)行微任務,將微任務放入eventqueue,但是,這兩個queue不是一個queue。當你往外拿的時候先從微任務里拿這個回調(diào)函數(shù),然后再從宏任務的queue拿宏任務的回調(diào)函數(shù)
宏任務一般包括:整體代碼script,setTimeout,setInterval。
微任務:Promise,process.nextTick
事件捕獲
處于目標階段
事件冒泡階段
事件委托 事件委托是指將事件綁定目標元素的到父元素上,利用冒泡機制觸發(fā)該事件
可以減少事件注冊,節(jié)省大量內(nèi)存占用可以將事件應用于動態(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.設置空對象的原型 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é)議缺陷:
無法復用鏈接,完成即斷開,重新慢啟動和 TCP 3次握手
head of line blocking: 線頭阻塞,導致請求之間互相影響
1.1 改進:
長連接(默認 keep-alive),復用
host 字段指定對應的虛擬站點
新增功能:
斷點續(xù)傳
身份認證
狀態(tài)管理
cache 緩存
Cache-Control
Expires
Last-Modified
Etag
2.0:
多路復用
二進制分幀層: 應用層和傳輸層之間
首部壓縮
服務端推送
HTTP之請求消息Request
請求行(request line)、請求頭部(header)、空行和請求數(shù)據(jù)四個部分組成。
請求行,用來說明請求類型,要訪問的資源以及所使用的HTTP版本.
請求頭部,緊接著請求行(即第一行)之后的部分,用來說明服務器要使用的附加信息
空行,請求頭部后面的空行是必須的
請求數(shù)據(jù)也叫主體,可以添加任意的其他數(shù)據(jù)。
HTTP之響應消息Response
HTTP響應也由四個部分組成,分別是:狀態(tài)行、消息報頭、空行和響應正文。
狀態(tài)行,由HTTP協(xié)議版本號, 狀態(tài)碼, 狀態(tài)消息 三部分組成。
消息報頭,用來說明客戶端要使用的一些附加信息
第三部分:空行,消息報頭后面的空行是必須的
第四部分:響應正文,服務器返回給客戶端的文本信息。
在瀏覽器地址欄鍵入URL,按下回車之后會經(jīng)歷以下流程:瀏覽器向 DNS 服務器請求解析該 URL 中的域名所對應的 IP 地址;
建立TCP連接(三次握手);
瀏覽器發(fā)出讀取文件(URL 中域名后面部分對應的文件)的HTTP 請求,該請求報文作為 TCP 三次握手的第三個報文的數(shù)據(jù)發(fā)送給服務器;
服務器對瀏覽器請求作出響應,并把對應的 html 文本發(fā)送給瀏覽器;
釋放 TCP連接(四次揮手);
瀏覽器將該 html 文本并顯示內(nèi)容;
三次握手SYN (同步序列編號)ACK(確認字符)
第一次握手:Client將標志位SYN置為1,隨機產(chǎn)生一個值seq=J,并將該數(shù)據(jù)包發(fā)送給Server,Client進入SYN_SENT狀態(tài),等待Server確認。
第二次握手:Server收到數(shù)據(jù)包后由標志位SYN=1知道Client請求建立連接,Server將標志位SYN和ACK都置為1,ack=J+1,隨機產(chǎn)生一個值seq=K,并將該數(shù)據(jù)包發(fā)送給Client以確認連接請求,Server進入SYN_RCVD狀態(tài)。
第三次握手:Client收到確認后,檢查ack是否為J+1,ACK是否為1,如果正確則將標志位ACK置為1,ack=K+1,并將該數(shù)據(jù)包發(fā)送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,Client和Server進入ESTABLISHED狀態(tài),完成三次握手,隨后Client與Server之間可以開始傳輸數(shù)據(jù)了。
四次揮手第一次揮手:Client發(fā)送一個FIN,用來關(guān)閉Client到Server的數(shù)據(jù)傳送,Client進入FIN_WAIT_1狀態(tài)。
第二次揮手:Server收到FIN后,發(fā)送一個ACK給Client,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號),Server進入CLOSE_WAIT狀態(tài)。
第三次揮手:Server發(fā)送一個FIN,用來關(guān)閉Server到Client的數(shù)據(jù)傳送,Server進入LAST_ACK狀態(tài)。
第四次揮手:Client收到FIN后,Client進入TIME_WAIT狀態(tài),接著發(fā)送一個ACK給Server,確認序號為收到序號+1,Server進入CLOSED狀態(tài),完成四次揮手。
為什么建立連接是三次握手,而關(guān)閉連接卻是四次揮手呢?這是因為服務端在LISTEN狀態(tài)下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發(fā)送給客戶端。而關(guān)閉連接時,當收到對方的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é)點進行平面合成
將布局繪制paint在屏幕上(可以拓展講一下減少瀏覽器渲染的回流和重繪)
HTTPS的工作原理非對稱加密與對稱加密雙劍合璧,使用非對稱加密算法傳遞用于對稱加密算法的密鑰,然后使用對稱加密算法進行信息傳遞。這樣既安全又高效
瀏覽器緩存當瀏覽器再次訪問一個已經(jīng)訪問過的資源時,它會這樣做:
看看是否命中強緩存,如果命中,就直接使用緩存了。
如果沒有命中強緩存,就發(fā)請求到服務器檢查是否命中協(xié)商緩存。
如果命中協(xié)商緩存,服務器會返回 304 告訴瀏覽器使用本地緩存。
否則,返回最新的資源。
強緩存
Expires
Cache-control
協(xié)商緩存
Last-Modified/If-Modified-Since
Etag/If-None-Match
vue&react Virtual DOM其實 VNode 是對真實 DOM 的一種抽象描述,它的核心定義無非就幾個關(guān)鍵屬性,標簽名、數(shù)據(jù)、子節(jié)點、鍵值等,其它屬性都是都是用來擴展 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(把差異應用到真正的DOM樹上) 等過程。diff算法比較新舊節(jié)點的時候,比較只會在同層級比較,不會跨層級比較
當數(shù)據(jù)發(fā)生變化的時候會生成一個新的VNode,然后新VNode和oldNode做對比,發(fā)現(xiàn)不一樣的地方直接修改在真實的dom上,比較新舊節(jié)點,一邊比較一邊給真是的dom打補丁
節(jié)點設置key可以高效的利用dom(key最好不要設置成index索引)
虛擬DOM diff算法主要就是對以下三種場景進行優(yōu)化:
tree diff
對樹進行分層比較,兩棵樹只會對同一層次的節(jié)點進行比較。(因為 DOM 節(jié)點跨層級的移動操作少到可以忽略不計)
如果父節(jié)點已經(jīng)不存在,則該節(jié)點及其子節(jié)點會被完全刪除掉,不會用于進一步的比較。
注意:
React 官方建議不要進行 DOM 節(jié)點跨層級的操作,非常影響 React 性能。
在開發(fā)組件時,保持穩(wěn)定的 DOM 結(jié)構(gòu)會有助于性能的提升。例如,可以通過 CSS 隱藏或顯示節(jié)點,而不是真的移除或添加 DOM 節(jié)點。component diff
如果是同一類型的組件,按照原策略繼續(xù)比較 virtual DOM tree(tree diff)。
對于同一類型的組件,有可能其 Virtual DOM 沒有任何變化,如果能夠確切的知道這點那可以節(jié)省大量的 diff 運算時間,因此 React 允許用戶通過 shouldComponentUpdate() 來判斷該組件是否需要進行 diff。
如果不是,直接替換整個組件下的所有子節(jié)點。element diff
對處于同一層級的節(jié)點進行對比。
vue的響應式原理
這時 React 建議:添加唯一 key 進行區(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 進行移動操作,即可。
建議:在開發(fā)過程中,盡量減少類似將最后一個節(jié)點移動到列表首部的操作,當節(jié)點數(shù)量過大或更新操作過于頻繁時,在一定程度上會影響 React 的渲染性能。
Object.defineProperty(obj, prop, descriptor)
obj 是要在其上定義屬性的對象;prop 是要定義或修改的屬性的名稱;descriptor 是將被定義或修改的屬性描述符。
比較核心的是 descriptor,它有很多可選鍵值,具體的可以去參閱它的文檔。這里我們最關(guān)心的是 get 和 set,get 是一個給屬性提供的 getter 方法,當我們訪問了該屬性的時候會觸發(fā) getter 方法;set 是一個給屬性提供的 setter 方法,當我們對該屬性做修改的時候會觸發(fā) setter 方法。一旦對象擁有了 getter 和 setter,我們可以簡單地把這個對象稱為響應式對象
- 對象遞歸調(diào)用 - 數(shù)組變異方法的解決方法:代理原型/實例方法
observe
observe 方法的作用就是給非 VNode 的對象類型數(shù)據(jù)添加一個 Observer,如果已經(jīng)添加過則直接返回,否則在滿足一定條件下去實例化一個 Observer 對象實例。
observe 的功能就是用來監(jiān)測數(shù)據(jù)的變化.
Observer 是一個類,它的作用是給對象的屬性添加 getter 和 setter,用于依賴收集和派發(fā)更新:
依賴收集和派發(fā)更新
收集依賴的目的是為了當這些響應式數(shù)據(jù)發(fā)生變化,觸發(fā)它們的 setter 的時候,能知道應該通知哪些訂閱者去做相應的邏輯處理,我們把這個過程叫派發(fā)更新,其實 Watcher 和 Dep 就是一個非常經(jīng)典的觀察者設計模式的實現(xiàn)
派發(fā)更新就是數(shù)據(jù)發(fā)生變化的時候,觸發(fā) setter 邏輯,把在依賴過程中訂閱的的所有觀察者,也就是 watcher,都觸發(fā)它們的 update 過程,這個過程又利用了隊列做了進一步優(yōu)化,在 nextTick 后執(zhí)行所有 watcher 的 run,最后執(zhí)行它們的回調(diào)函數(shù)
vue編譯Compile的過程主要分以下幾步
parse(生成AST)=> optimize(優(yōu)化靜態(tài)節(jié)點) => 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 的值有緩存,只有當計算值變化才會返回內(nèi)容。
watch 監(jiān)聽到值的變化就會執(zhí)行回調(diào),在回調(diào)中可以進行一些邏輯操作。
所以一般來說需要依賴別的屬性來動態(tài)獲得值的時候可以使用computed,對于監(jiān)聽到值的變化需要做一些復雜業(yè)務邏輯的情況可以使用 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)站應用程序的安全漏洞攻擊,是代碼注入的一種。常見方式是將惡意代碼注入合法代碼里隱藏起來,再誘發(fā)惡意代碼,從而進行各種各樣的非法活動。
預防:
使用XSS Filter
輸入過濾,對用戶提交的數(shù)據(jù)進行有效性驗證,僅接受指定長度范圍內(nèi)并符合我們期望格式的的內(nèi)容提交,阻止或者忽略除此外的其他任何數(shù)據(jù)。
輸出轉(zhuǎn)義,當需要將一個字符串輸出到Web網(wǎng)頁時,同時又不確定這個字符串中是否包括XSS特殊字符,為了確保輸出內(nèi)容的完整性和正確性,輸出HTML屬性時可以使用HTML轉(zhuǎn)義編碼(HTMLEncode)進行處理,輸出到中,可以進行JS編碼。
使用 HttpOnly Cookie
將重要的cookie標記為httponly,這樣的話當瀏覽器向Web服務器發(fā)起請求的時就會帶上cookie字段,但是在js腳本中卻不能訪問這個cookie,這樣就避免了XSS攻擊利用JavaScript的document.cookie獲取cookie。
CSRF:跨站請求偽造,也稱 XSRF,是一種挾制用戶在當前已登錄的Web應用程序上執(zhí)行非本意的操作的攻擊方法。與 XSS 相比,XSS利用的是用戶對指定網(wǎng)站的信任,CSRF利用的是網(wǎng)站對用戶網(wǎng)頁瀏覽器的信任。
預防:用戶操作限制——驗證碼機制
方法:添加驗證碼來識別是不是用戶主動去發(fā)起這個請求,由于一定強度的驗證碼機器無法識別,因此危險網(wǎng)站不能偽造一個完整的請求。
優(yōu)點:簡單粗暴,低成本,可靠,能防范99.99%的攻擊者。
缺點:對用戶不友好。
請求來源限制——驗證 HTTP Referer 字段
方法:在HTTP請求頭中有一個字段叫Referer,它記錄了請求的來源地址。 服務器需要做的是驗證這個來源地址是否合法,如果是來自一些不受信任的網(wǎng)站,則拒絕響應。
優(yōu)點:零成本,簡單易實現(xiàn)。
缺點:由于這個方法嚴重依賴瀏覽器自身,因此安全性全看瀏覽器。
額外驗證機制——token的使用
方法:使用token來代替驗證碼驗證。由于黑客并不能拿到和看到cookie里的內(nèi)容,所以無法偽造一個完整的請求。基本思路如下:
服務器隨機產(chǎn)生token(比如把cookie hash化生成),存在session中,放在cookie中或者以ajax的形式交給前端。
前端發(fā)請求的時候,解析cookie中的token,放到請求url里或者請求頭中。
服務器驗證token,由于黑客無法得到或者偽造token,所以能防范csrf
面試相關(guān) 正在整理中的問題 寫過webpack loader嗎 vue怎么監(jiān)聽數(shù)組 手寫快排,時間復雜度,優(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://m.specialneedsforspecialkids.com/yun/109325.html
摘要:獲取的對象范圍方法獲取的是最終應用在元素上的所有屬性對象即使沒有代碼,也會把默認的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對于一個光禿禿的元素,方法返回對象中屬性值如果有就是據(jù)我測試不同環(huán)境結(jié)果可能有差異而就是。 花了很長時間整理的前端面試資源,喜歡請大家不要吝嗇star~ 別只收藏,點個贊,點個star再走哈~ 持續(xù)更新中……,可以關(guān)注下github 項目地址 https:...
摘要:三年百度,五年阿里,阿里架構(gòu)師淺談我是如何順利進入前些天在我群里認識了以為挺有意思的老哥,他也是工作年多技術(shù)和面試都不差,最近也是在找工作,是從京城來魔都的,也和他撈了不少。 說來慚愧,也不怕你們笑話。做開發(fā)8年多,到目前還是一名不折不扣的掃地僧。年前的辭職,到現(xiàn)在還在家靜養(yǎng)中。其實也沒什么,就是回家總結(jié)一下自己這些年來在外工作與面試等做一個簡單的總結(jié)與反思。做一下自己后面一個人生規(guī)劃...
閱讀 2571·2021-11-22 09:34
閱讀 3548·2021-11-15 11:37
閱讀 2351·2021-09-13 10:37
閱讀 2111·2021-09-04 16:40
閱讀 1587·2021-09-02 15:40
閱讀 2466·2019-08-30 13:14
閱讀 3334·2019-08-29 13:42
閱讀 1910·2019-08-29 13:02