摘要:延伸這里再順便提一下,新架構(gòu)下的防御。不過,還有一點(diǎn)值得一提前后端分離框架下,路由由控制我自己要獲取的后端參數(shù)和需要用在業(yè)務(wù)邏輯的參數(shù),在主觀上前端同學(xué)更好把握一些。
原文: http://feclub.cn/post/content...
背景 1、什么是CSRF攻擊?這里不再介紹CSRF,已經(jīng)了解CSRF原理的同學(xué)可以直接跳到:“3、前后端分離下有何不同?”。
不太了解的同學(xué)可以看這兩篇對CSRF介紹比較詳細(xì)的參考文章:
CSRF 攻擊的應(yīng)對之道
淺談CSRF攻擊方式
如果來不及了解CSRF的原理,可以這么理解:有一個(gè)人發(fā)給你一個(gè)搞(mei)笑(nv)圖片鏈接,你打開這個(gè)鏈接之后,便立刻收到了短信:你的銀行里的錢已經(jīng)轉(zhuǎn)移到這個(gè)人的帳戶了。
2、有哪些防御方案?上面這個(gè)例子當(dāng)然有點(diǎn)危言聳聽,當(dāng)然可以確定的是確實(shí)會(huì)有這樣的漏洞:你打開了一個(gè)未知域名的鏈接,然后你就自動(dòng)發(fā)了條廣告帖子、你的Gmail的郵件內(nèi)容就泄露了、你的百度登錄狀態(tài)就沒了……
防御方案在上面的兩篇文章里也有提到,總結(jié)下,無外乎三種:
用戶操作限制,比如驗(yàn)證碼;
請求來源限制,比如限制HTTP Referer才能完成操作;
token驗(yàn)證機(jī)制,比如請求數(shù)據(jù)字段中添加一個(gè)token,響應(yīng)請求時(shí)校驗(yàn)其有效性;
第一種方案明顯嚴(yán)重影響了用戶體驗(yàn),而且還有額外的開發(fā)成本;第二種方案成本最低,但是并不能保證100%安全,而且很有可能會(huì)埋坑;第三種方案,可??!
token驗(yàn)證的CSRF防御機(jī)制是公認(rèn)最合適的方案,也是本文討論的重點(diǎn)。
3、前后端分離下有何不同?《CSRF 攻擊的應(yīng)對之道》這篇文章里有提到:
要把所有請求都改為 XMLHttpRequest 請求,這樣幾乎是要重寫整個(gè)網(wǎng)站,這代價(jià)無疑是不能接受的
我們前端架構(gòu)早已經(jīng)告別了服務(wù)端語言(PHP/JAVA等)綁定路由、攜帶數(shù)據(jù)渲染模板引擎的方式(畢竟是2011年的文章了,我們笑而不語)。
當(dāng)然, 前端不要高興的太早:前后端分離之后,Nodejs不具備完善的服務(wù)端SESSION、數(shù)據(jù)庫等功能。
總結(jié)一下,在“更先進(jìn)”的前端架構(gòu)下,與以往的架構(gòu)會(huì)有一些區(qū)別:
Nodejs層不處理SESSION,無法直接實(shí)現(xiàn)會(huì)話狀態(tài)數(shù)據(jù)保存;
所有的數(shù)據(jù)通過Ajax異步獲取,可以靈活實(shí)現(xiàn)token方案;
實(shí)現(xiàn)思路如上文提到,這里僅僅討論在“更先進(jìn)”的前端后端架構(gòu)背景下的token防御方案的實(shí)現(xiàn)。
1、可行性方案token防御的整體思路是:
第一步:后端隨機(jī)產(chǎn)生一個(gè)token,把這個(gè)token保存在SESSION狀態(tài)中;同時(shí),后端把這個(gè)token交給前端頁面;
第二步:下次前端需要發(fā)起請求(比如發(fā)帖)的時(shí)候把這個(gè)token加入到請求數(shù)據(jù)或者頭信息中,一起傳給后端;
第三步:后端校驗(yàn)前端請求帶過來的token和SESSION里的token是否一致;
上文提到過,前后端分離狀態(tài)下,Nodejs是不具備SESSION功能的。那這種token防御機(jī)制是不是就無法實(shí)現(xiàn)了呢?
肯定不是。我們可以借助cookie把這個(gè)流程升級下:
第一步:后端隨機(jī)產(chǎn)生一個(gè)token,基于這個(gè)token通過SHA-56等散列算法生成一個(gè)密文;
第二步:后端將這個(gè)token和生成的密文都設(shè)置為cookie,返回給前端;
第三步:前端需要發(fā)起請求的時(shí)候,從cookie中獲取token,把這個(gè)token加入到請求數(shù)據(jù)或者頭信息中,一起傳給后端;
第四步:后端校驗(yàn)cookie中的密文,以及前端請求帶過來的token,進(jìn)行正向散列驗(yàn)證;
當(dāng)然這樣實(shí)現(xiàn)也有需要注意的:
散列算法都是需要計(jì)算的,這里會(huì)有性能風(fēng)險(xiǎn);
token參數(shù)必須由前端處理之后交給后端,而不能直接通過cookie;
cookie更臃腫,會(huì)不可避免地讓頭信息更重;
現(xiàn)在方案確定了,具體該如何實(shí)現(xiàn)呢?
2、具體實(shí)現(xiàn)我們的技術(shù)棧是 koa(服務(wù)端) + Vue.js(前端) 。有興趣可以看這些資料:
趣店前端團(tuán)隊(duì)基于koajs的前后端分離實(shí)踐
koa-grace——基于koa的標(biāo)準(zhǔn)前后端分離框架
grace-vue-webpack-boilerplate
在服務(wù)端,實(shí)現(xiàn)了一個(gè)token生成的中間件,koa-grace-csrf:
// 注意:代碼有做精簡 const tokens = require("./lib/tokens"); return function* csrf(next) { let curSecret = this.cookies.get("密文的cookie"); // 其他如果要獲取參數(shù),則為配置參數(shù)值 let curToken = "請求http頭信息中的token"; // token不存在 if (!curToken || !curSecret) { return this.throw("CSRF Token Not Found!",403) } // token校驗(yàn)失敗 if (!tokens.verify(curSecret, curToken)) { return this.throw("CSRF token Invalid!",403) } yield next; // 無論何種情況都種兩個(gè)cookie // cookie_key: 當(dāng)前token的cookie_key,httpOnly let secret = tokens.secretSync(); this.cookies.set(options.cookie_key, secret); // cookie_token: 當(dāng)前token的的content,不需要httpOnly let newToken = tokens.create(secret); this.cookies.set(options.cookie_token, newToken) }
在前端代碼中,對發(fā)送ajax請求的封裝稍作優(yōu)化:
this.$http.post(url, data, { headers: { "http請求頭信息字段名": "cookie中的token" } }).then((res) => {})
總結(jié)一下:
Nodejs生成一個(gè)隨機(jī)數(shù),通過隨機(jī)數(shù)生成散列密文;并將隨機(jī)數(shù)和密文存到cookie;
客戶端JS獲取cookie中的隨機(jī)數(shù),通過http頭信息交給Nodejs;
Nodejs響應(yīng)請求,校驗(yàn)cookie中的密文和頭信息中的隨機(jī)數(shù)是否匹配;
這里依舊有個(gè)細(xì)節(jié)值得提一下:Nodejs的上層一般是nginx,而nginx默認(rèn)會(huì)過濾頭信息中不合法的字段(比如頭信息字段名包含“_”的),這里在寫頭信息的時(shí)候需要注意。
"One more thing..."上文也提到,通過cookie及http頭信息傳遞加密token會(huì)有很多弊端;有沒有更優(yōu)雅的實(shí)現(xiàn)方案呢?
1、cookie中samesite屬性回溯下CSRF產(chǎn)生的根本原因:cookie會(huì)被第三方發(fā)起的跨站請求攜帶,這本質(zhì)上是HTTP協(xié)議設(shè)計(jì)的漏洞。
那么,我們能不能通過cookie的某個(gè)屬性禁止cookie的這個(gè)特性呢?
好消息是,在最新的RFC規(guī)范中已經(jīng)加入了“samesite”屬性。細(xì)節(jié)這里不再贅述,可以參考:
SameSite Cookie,防止 CSRF 攻擊
Same-site Cookies
2、更優(yōu)雅的架構(gòu)當(dāng)然,目前為止,客戶端對samesite屬性的支持并不是特別好;回到前后端分離架構(gòu)下,我們明確下前后端分離框架的基本原則:
后端(Java / PHP )職責(zé):
服務(wù)層顆粒化接口,以便前端Nodejs層異步并發(fā)調(diào)用;
用戶狀態(tài)保存,實(shí)現(xiàn)用戶權(quán)限等各種功能;
前端(Nodejs + Javascript)職責(zé):
Nodejs層完成路由托管及模板引擎渲染功能
Nodejs層不負(fù)責(zé)實(shí)現(xiàn)任何SESSION和數(shù)據(jù)庫功能
我們提到,前端Nodejs層不負(fù)責(zé)實(shí)現(xiàn)任何SESSION和數(shù)據(jù)庫功能,但有沒有可能把后端緩存系統(tǒng)做成公共服務(wù)提供給Nodejs層使用呢?想想感覺前端整條路都亮了有木有?!這里先挖一個(gè)坑,后續(xù)慢慢填。
3、延伸這里再順便提一下,新架構(gòu)下的XSS防御。
猶記得,在狼廠使用PHP的年代,經(jīng)常被安全部門曝出各類XSS漏洞,然后就在smaty里添加各種escape濾鏡,但是添加之后發(fā)現(xiàn)竟然把原始數(shù)據(jù)也給轉(zhuǎn)義了。
當(dāng)然,現(xiàn)在更多要?dú)w功于各種MVVM單頁面應(yīng)用:使得前端完全不需要通過讀取URL中的參數(shù)來控制VIEW。
不過,還有一點(diǎn)值得一提:前后端分離框架下,路由由Nodejs控制;我自己要獲取的后端參數(shù)和需要用在業(yè)務(wù)邏輯的參數(shù),在主觀上前端同學(xué)更好把握一些。
所以, 在koa(服務(wù)端) + Vue.js(前端)架構(gòu)下基本不用顧慮XSS問題(至少不會(huì)被全安組追著問XSS漏洞啥時(shí)候修復(fù))。
總結(jié)要不學(xué)PHP、看Java、玩Python做全棧好了?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80427.html
摘要:使用緩存兩個(gè)前提條件數(shù)據(jù)訪問熱點(diǎn)不均衡數(shù)據(jù)某時(shí)段內(nèi)有效,不會(huì)很快過期反向代理本地緩存分布式緩存異步旨在系統(tǒng)解耦。 大型網(wǎng)站技術(shù)架構(gòu)-入門梳理 標(biāo)簽 : 架構(gòu)設(shè)計(jì) [TOC] 羅列了大型網(wǎng)站架構(gòu)涉及到的概念,附上了簡單說明 前言 本文是對《大型網(wǎng)站架構(gòu)設(shè)計(jì)》(李智慧 著)一書的梳理,類似文字版的思維導(dǎo)圖 全文主要圍繞性能,可用性,伸縮性,擴(kuò)展性,安全這五個(gè)要素 性能,可用性,伸縮性...
摘要:更新嘗試了一下實(shí)現(xiàn)前后端分離,新的文章如下前后端分離之初試更新可另外用實(shí)現(xiàn)前后端分離,這篇文章可能局限性太大,只是個(gè)人的入門實(shí)踐剛剛學(xué)習(xí)前端快一年,后臺方面了解甚少,于是決定踩踩坑,學(xué)習(xí)一下。 2018.9.6更新:嘗試了一下REST framework實(shí)現(xiàn)前后端分離,新的文章如下Django前后端分離之REST framework初試 2018.8.27更新:可另外用 restful...
摘要:對的請求,也是要有一個(gè)了解,比如協(xié)議,請求方式,請求過程,結(jié)果狀態(tài)碼等。教程協(xié)議詳解經(jīng)典面試題一個(gè)故事講完響應(yīng)狀態(tài)碼上面提到響應(yīng)狀態(tài)碼,在這里也簡單寫下。 勸了別人無數(shù)次,讓別人喝了雞湯,幫別人填坑,自己卻掉了坑 1.前言 在前端學(xué)習(xí)里面,很多人都是注重學(xué)習(xí)代碼(html,css,js)。或者是一些框架,庫(jquery,vue,react),或者是各種工具(webpack,gulp)...
閱讀 1889·2021-09-22 15:45
閱讀 1674·2019-08-30 15:55
閱讀 1856·2019-08-29 11:16
閱讀 3329·2019-08-26 11:44
閱讀 739·2019-08-23 17:58
閱讀 2719·2019-08-23 12:25
閱讀 1654·2019-08-22 17:15
閱讀 3643·2019-08-22 16:09