Web认证及API的 使用TOKEN的一些思考
首先貼一下看過(guò)的文章:
1.http://www.cnblogs.com/xiekel...
2.http://blog.leapoahead.com/20...
3.http://blog.leapoahead.com/20...
4.jwt demo :https://github.com/bigmeow/JWT
5.https://github.com/jwtk/jjwt 這里面有幾篇比較好的算是官方推薦的
6.http://blog.csdn.net/koastal/... 基于timestamp和nonce的防止重放攻擊方案
公司目前的WEB設(shè)計(jì)都是基于HTTP Basic Auth,一直覺(jué)得會(huì)有很大的安全問(wèn)題,重放攻擊就很簡(jiǎn)單實(shí)現(xiàn)。
引用第一篇文章的一段話:HTTP Basic Auth簡(jiǎn)單點(diǎn)說(shuō)明就是每次請(qǐng)求API時(shí)都提供用戶的username和password,簡(jiǎn)言之,Basic Auth是配合RESTful API 使用的最簡(jiǎn)單的認(rèn)證方式,只需提供用戶名密碼即可,但由于有把用戶名密碼暴露給第三方客戶端的風(fēng)險(xiǎn),在生產(chǎn)環(huán)境下被使用的越來(lái)越少。因此,在開(kāi)發(fā)對(duì)外開(kāi)放的RESTful API時(shí),盡量避免采用HTTP Basic Auth。
覺(jué)得采用TOKEN的方式實(shí)現(xiàn)WEB和API的認(rèn)證。 JSON WEB TOKEN 算是比較成熟的解決方案,因此采用JSON WEB TOKEN。 JSON WEB TOKEN的基本介紹請(qǐng)看 文章開(kāi)頭的后面3個(gè)連接。
JWT解決了:
1.作為T(mén)OKEN驗(yàn)證使用時(shí)解決了用戶直接輸入賬號(hào)和密碼的進(jìn)行認(rèn)證的問(wèn)題。
2.部分?jǐn)?shù)據(jù)安全傳輸?shù)膯?wèn)題(例如第2個(gè)鏈接的文章,是添加關(guān)注,服務(wù)器生成的連接,可以安全的通過(guò)郵件發(fā)送給目標(biāo)客戶,而不暴露操作用戶的相關(guān)信息)。
作為T(mén)OKEN使用,JWT的payload需要有關(guān)于用戶信息的字段,不然怎么知道是哪個(gè)用戶在操作,一般不要填寫(xiě)敏感信息,如用戶密碼等,因?yàn)槭峭ㄟ^(guò)base64編碼,是可以破解的。用戶登錄和獲取TOKEN的接口是需要HTTPS加密的,否則用戶賬號(hào)和密碼是會(huì)暴露的,也就沒(méi)有什么安全性可言了。
請(qǐng)求時(shí)TOKEN的上傳可以用以下方式:
1.通過(guò)cookie
2.通過(guò)HTTP Authorization Head中
3.GET/POST方法,直接通過(guò)參數(shù)形式。
安全性:
1.首先要保證登錄和獲得TOKEN的接口需要HTTPS加密
2.防止重放攻擊:目前想到的 客戶端和服務(wù)器間有一個(gè)共享的秘鑰,在調(diào)用API時(shí)需要將API的方法、參數(shù)、TOKEN做一次簽名(可用jwt)。服務(wù)器首先驗(yàn)證方法、參數(shù)、TOKEN的簽名是否正確,然后驗(yàn)證TOKEN的簽名是否正確。第一次簽名時(shí)保證即使請(qǐng)求被劫持,劫持者也沒(méi)有辦法假冒其它請(qǐng)求或者修改參數(shù),在一定程度上保證了安全性。 第二次簽名驗(yàn)證主要是驗(yàn)證TOKEN的有效性,驗(yàn)證用戶身份。
以上步驟需要服務(wù)器上保存兩種秘鑰,第一種是生產(chǎn)TOKEN的秘鑰,這個(gè)只有服務(wù)器程序知道。第二種秘鑰是針對(duì)每個(gè)使用接口的開(kāi)發(fā)者的共享秘鑰,這個(gè)秘鑰只需要服務(wù)器和開(kāi)發(fā)者知道(開(kāi)發(fā)者可以登錄網(wǎng)站,在申請(qǐng)使用接口時(shí),自定義自己的共享秘鑰)。
3.共享秘鑰的保存:共享秘鑰需要安全的保存,不能被泄漏。
-----------------------以下拷貝自第6個(gè)鏈接------------------------------------------
以前總是通過(guò)timestamp來(lái)防止重放攻擊,但是這樣并不能保證每次請(qǐng)求都是一次性的。今天看到了一篇文章介紹的通過(guò)nonce(Number used once)來(lái)保證一次有效,感覺(jué)兩者結(jié)合一下,就能達(dá)到一個(gè)非常好的效果了。
重放攻擊是計(jì)算機(jī)世界黑客常用的攻擊方式之一,所謂重放攻擊就是攻擊者發(fā)送一個(gè)目的主機(jī)已接收過(guò)的包,來(lái)達(dá)到欺騙系統(tǒng)的目的,主要用于身份認(rèn)證過(guò)程。
首先要明確一個(gè)事情,重放攻擊是二次請(qǐng)求,黑客通過(guò)抓包獲取到了請(qǐng)求的HTTP報(bào)文,然后黑客自己編寫(xiě)了一個(gè)類(lèi)似的HTTP請(qǐng)求,發(fā)送給服務(wù)器。也就是說(shuō)服務(wù)器處理了兩個(gè)請(qǐng)求,先處理了正常的HTTP請(qǐng)求,然后又處理了黑客發(fā)送的篡改過(guò)的HTTP請(qǐng)求。
基于timestamp的方案
每次HTTP請(qǐng)求,都需要加上timestamp參數(shù),然后把timestamp和其他參數(shù)一起進(jìn)行數(shù)字簽名。因?yàn)橐淮握5腍TTP請(qǐng)求,從發(fā)出到達(dá)服務(wù)器一般都不會(huì)超過(guò)60s,所以服務(wù)器收到HTTP請(qǐng)求之后,首先判斷時(shí)間戳參數(shù)與當(dāng)前時(shí)間相比較,是否超過(guò)了60s,如果超過(guò)了則認(rèn)為是非法的請(qǐng)求。
假如黑客通過(guò)抓包得到了我們的請(qǐng)求url:
http://koastal.site/index/Inf...
其中
$sign=md5($uid.$token.$stime);
// 服務(wù)器通過(guò)uid從數(shù)據(jù)庫(kù)中可讀出token
一般情況下,黑客從抓包重放請(qǐng)求耗時(shí)遠(yuǎn)遠(yuǎn)超過(guò)了60s,所以此時(shí)請(qǐng)求中的stime參數(shù)已經(jīng)失效了。
如果黑客修改stime參數(shù)為當(dāng)前的時(shí)間戳,則sign參數(shù)對(duì)應(yīng)的數(shù)字簽名就會(huì)失效,因?yàn)楹诳筒恢纓oken值,沒(méi)有辦法生成新的數(shù)字簽名。
但這種方式的漏洞也是顯而易見(jiàn)的,如果在60s之內(nèi)進(jìn)行重放攻擊,那就沒(méi)辦法了,所以這種方式不能保證請(qǐng)求僅一次有效。
基于nonce的方案
nonce的意思是僅一次有效的隨機(jī)字符串,要求每次請(qǐng)求時(shí),該參數(shù)要保證不同,所以該參數(shù)一般與時(shí)間戳有關(guān),我們這里為了方便起見(jiàn),直接使用時(shí)間戳的16進(jìn)制,實(shí)際使用時(shí)可以加上客戶端的ip地址,mac地址等信息做個(gè)哈希之后,作為nonce參數(shù)。
我們將每次請(qǐng)求的nonce參數(shù)存儲(chǔ)到一個(gè)“集合”中,可以json格式存儲(chǔ)到數(shù)據(jù)庫(kù)或緩存中。
每次處理HTTP請(qǐng)求時(shí),首先判斷該請(qǐng)求的nonce參數(shù)是否在該“集合”中,如果存在則認(rèn)為是非法請(qǐng)求。
假如黑客通過(guò)抓包得到了我們的請(qǐng)求url:
http://koastal.site/index/Inf...
其中
$sign=md5($uid.$token.$nonce);
// 服務(wù)器通過(guò)uid從數(shù)據(jù)庫(kù)中可讀出token
nonce參數(shù)在首次請(qǐng)求時(shí),已經(jīng)被存儲(chǔ)到了服務(wù)器上的“集合”中,再次發(fā)送請(qǐng)求會(huì)被識(shí)別并拒絕。
nonce參數(shù)作為數(shù)字簽名的一部分,是無(wú)法篡改的,因?yàn)楹诳筒磺宄oken,所以不能生成新的sign。
這種方式也有很大的問(wèn)題,那就是存儲(chǔ)nonce參數(shù)的“集合”會(huì)越來(lái)越大,驗(yàn)證nonce是否存在“集合”中的耗時(shí)會(huì)越來(lái)越長(zhǎng)。我們不能讓nonce“集合”無(wú)限大,所以需要定期清理該“集合”,但是一旦該“集合”被清理,我們就無(wú)法驗(yàn)證被清理了的nonce參數(shù)了。也就是說(shuō),假設(shè)該“集合”平均1天清理一次的話,我們抓取到的該url,雖然當(dāng)時(shí)無(wú)法進(jìn)行重放攻擊,但是我們還是可以每隔一天進(jìn)行一次重放攻擊的。而且存儲(chǔ)24小時(shí)內(nèi),所有請(qǐng)求的“nonce”參數(shù),也是一筆不小的開(kāi)銷(xiāo)。
基于timestamp和nonce的方案
那我們?nèi)绻瑫r(shí)使用timestamp和nonce參數(shù)呢?
nonce的一次性可以解決timestamp參數(shù)60s的問(wèn)題,timestamp可以解決nonce參數(shù)“集合”越來(lái)越大的問(wèn)題。
我們?cè)趖imestamp方案的基礎(chǔ)上,加上nonce參數(shù),因?yàn)閠imstamp參數(shù)對(duì)于超過(guò)60s的請(qǐng)求,都認(rèn)為非法請(qǐng)求,所以我們只需要存儲(chǔ)60s的nonce參數(shù)的“集合”即可。
假如黑客通過(guò)抓包得到了我們的請(qǐng)求url:
http://koastal.site/index/Inf...
其中
$sign=md5($uid.$token.$stime.$nonce);
// 服務(wù)器通過(guò)uid從數(shù)據(jù)庫(kù)中可讀出token
如果在60s內(nèi),重放該HTTP請(qǐng)求,因?yàn)閚once參數(shù)已經(jīng)在首次請(qǐng)求的時(shí)候被記錄在服務(wù)器的nonce參數(shù)“集合”中,所以會(huì)被判斷為非法請(qǐng)求。超過(guò)60s之后,stime參數(shù)就會(huì)失效,此時(shí)因?yàn)楹诳筒磺宄oken的值,所以無(wú)法重新生成簽名。
綜上,我們認(rèn)為一次正常的HTTP請(qǐng)求發(fā)送不會(huì)超過(guò)60s,在60s之內(nèi)的重放攻擊可以由nonce參數(shù)保證,超過(guò)60s的重放攻擊可以由stime參數(shù)保證。
因?yàn)閚once參數(shù)只會(huì)在60s之內(nèi)起作用,所以只需要保存60s之內(nèi)的nonce參數(shù)即可。
我們并不一定要每個(gè)60s去清理該nonce參數(shù)的集合,只需要在新的nonce到來(lái)時(shí),判斷nonce集合最后一次修改時(shí)間,超過(guò)60s的話,就清空該集合,存放新的nonce參數(shù)集合。其實(shí)nonce參數(shù)集合可以存放的時(shí)間更久一些,但是最少是60s。
驗(yàn)證流程
//判斷stime參數(shù)是否有效
if( $now - $stime > 60){
}
//判斷nonce參數(shù)是否在“集合”已存在
if( in_array($nonce,$nonceArray) ){
}
//驗(yàn)證數(shù)字簽名
if ( $sign != md5($uid.$token.$stime.$nonce) ){
}
//判斷是否需要清理nonce集合
if( $now - $nonceArray->lastModifyTime > 60 ){
}
//記錄本次請(qǐng)求的nonce參數(shù)
$nonceArray.push($nonce);
//開(kāi)始處理合法的請(qǐng)求
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Web认证及API的 使用TOKEN的一些思考的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [leetcode-515-Find L
- 下一篇: CenterOS6.5 + OneinS