[置顶] OAuth工作原理随想——让你的系统提供的服务更加安全
最近這段時(shí)間,一直都在和web服務(wù)打交道。自己項(xiàng)目組的系統(tǒng)需要?jiǎng)e的項(xiàng)目組提供服務(wù)接口;別的平臺(tái)(手機(jī))平臺(tái)又需要我們這邊給它們提供接口。實(shí)現(xiàn)、調(diào)用、接口文檔都有所涉及。從中我發(fā)現(xiàn)一個(gè)非常重要的問(wèn)題——安全,這是一個(gè)被嚴(yán)重忽略的問(wèn)題。
我認(rèn)為在網(wǎng)絡(luò)這個(gè)充滿(mǎn)敵意的大環(huán)境下,應(yīng)用和服務(wù)的安全性,是一個(gè)不得不重視的問(wèn)題。去年年底的CSDN賬號(hào)泄露以及口令明文的事件,至少給了企業(yè)兩個(gè)最基本的警示:(1)不要等到出現(xiàn)問(wèn)題之后,才知道要去挽救,在這個(gè)浮躁的社會(huì)氛圍下,出現(xiàn)哪怕不是什么大問(wèn)題,都會(huì)被群起而攻之;(2)服務(wù)的提供方應(yīng)該認(rèn)識(shí)到安全的重要性。本文參考OAuth協(xié)議的工作原理,給出了我個(gè)人覺(jué)得更為安全的服務(wù)認(rèn)證和授權(quán)方式。一家之談,歡迎各位提出寶貴意見(jiàn)。
?
幾個(gè)項(xiàng)目組對(duì)于web服務(wù)的處理方式:
(1)???僅僅是一個(gè)簡(jiǎn)單的明文key,用來(lái)標(biāo)識(shí)屬于哪個(gè)平臺(tái);
(2)???服務(wù)提供方和調(diào)用方協(xié)商一種驗(yàn)證碼的生成規(guī)則,服務(wù)的調(diào)用方攜帶用戶(hù)id以及生成的驗(yàn)證碼。在服務(wù)提供方一端有個(gè)驗(yàn)證的方式,如果按照同樣的規(guī)則生成出相同的驗(yàn)證碼,則認(rèn)為調(diào)用方是合法調(diào)用者
簡(jiǎn)單的談?wù)勥@兩種方式吧,其實(shí)第一種沒(méi)什么好談的。它只是用了一個(gè)標(biāo)識(shí)符,標(biāo)識(shí)服務(wù)的調(diào)用方來(lái)自哪個(gè)平臺(tái),然后在它方法中表明應(yīng)該走入哪個(gè)分支,這顯而易見(jiàn)。還有一個(gè)我覺(jué)得沒(méi)什么好談的就是,它簡(jiǎn)直就是個(gè)“肉雞”,甚至連“肉雞”都算不上。只要你知道URL,想干嘛干嘛去吧;第二種方式,不得不說(shuō)至少比第一種方式高級(jí)得多。它至少仿照了類(lèi)似數(shù)字簽名的做法。但不得不說(shuō),還是有些簡(jiǎn)單并直接了。并且,要知道只要基于了同一種生成驗(yàn)證碼的規(guī)則(注意這里并不是hash散列算法),那么它的靈活性和隨機(jī)性就會(huì)降低。有一種比較簡(jiǎn)單而有效的攻擊手段——DOS(拒絕服務(wù)),上面兩種方式都無(wú)法逃過(guò)這樣的攻擊。原因是:
(1)???URL是定死的,或者很長(zhǎng)一段時(shí)間才會(huì)改變?yōu)榱硪环N形式的,但在服務(wù)端并沒(méi)有關(guān)于對(duì)來(lái)自同一個(gè)IP,在一段時(shí)間內(nèi)訪(fǎng)問(wèn)次數(shù)的限制
(2)???沒(méi)有對(duì)調(diào)用方進(jìn)行認(rèn)證
對(duì)于采用HTTP GET形式的Web Service調(diào)用都會(huì)有這些安全問(wèn)題。后臺(tái)引用的調(diào)用方式也難以幸免于難,因?yàn)樗鼈儽举|(zhì)上都是一樣的。其實(shí),一方需要另一方提供服務(wù),這種場(chǎng)景在互聯(lián)網(wǎng)中早已司空見(jiàn)慣。新浪、騰訊、人人、網(wǎng)易等開(kāi)放平臺(tái)都是服務(wù)的提供者,它們是如何來(lái)保證服務(wù)的安全性以達(dá)到保證平臺(tái)用戶(hù)資源的安全?沒(méi)錯(cuò),它們幾乎都是使用——OAuth這種認(rèn)證和授權(quán)協(xié)議。
?
OAuth協(xié)議簡(jiǎn)介
具體的文字解釋,參見(jiàn)wiki——OAuth
應(yīng)用場(chǎng)景:
請(qǐng)求過(guò)程示意圖:
項(xiàng)目目前對(duì)于web服務(wù)【web service/web page】的調(diào)用場(chǎng)景:
OAuth照搬?
OAuth的認(rèn)證和授權(quán)過(guò)程中,通常都有一步需要用戶(hù)授權(quán)的過(guò)程,也就是需要將用戶(hù)引導(dǎo)到第三方服務(wù)提供者的授權(quán)頁(yè)面(通常需要填寫(xiě)用戶(hù)名和密碼),并引導(dǎo)用戶(hù)完成授權(quán)。在系統(tǒng)中,并不適合引入這樣的交互模式。因?yàn)槲覀儸F(xiàn)在的系統(tǒng)從第三方提取數(shù)據(jù)對(duì)用戶(hù)來(lái)講是透明的,用戶(hù)登錄我們的系統(tǒng),并不知道,我們的數(shù)據(jù)是來(lái)自第三方提供的。所以這極其影響用戶(hù)體驗(yàn)。并且,參照資源的重要級(jí)別,并不是所有服務(wù)都需要享受這么機(jī)密的待遇(從Oath授權(quán)可以看到,需要多次的“握手”,也就是需要來(lái)回HTTP請(qǐng)求好幾次),有時(shí)資源重要性是需要考慮的一個(gè)方面,而有時(shí)保證服務(wù)正常提供、提供服務(wù)的服務(wù)器正常運(yùn)轉(zhuǎn)則更為側(cè)重。
?
如何兼顧安全、性能?
下圖展示了本人對(duì)于兼顧安全以及性能的設(shè)想:
對(duì)于步驟說(shuō)明:
第一次交互稱(chēng)之為:握手(也就是認(rèn)證和授權(quán)的過(guò)程),由于這些服務(wù)本質(zhì)上只對(duì)已知系統(tǒng)的特定用戶(hù)開(kāi)放,而非互聯(lián)網(wǎng)應(yīng)用的開(kāi)放級(jí)別。所以這里省去了第一步驗(yàn)證客戶(hù)端身份,獲取Request Token的過(guò)程(或者稱(chēng)之為合二為一)。
步驟1:請(qǐng)求方采用HTTPS協(xié)議,封送能夠認(rèn)證調(diào)用方合法身份。這里封送什么內(nèi)容呢?可以是服務(wù)提供方分配的用戶(hù)名或密碼對(duì),可以是類(lèi)似于上面的驗(yàn)證碼,還可以是提供方公開(kāi)的密鑰。以上這些針對(duì)公共資源服務(wù)就足夠了,對(duì)于類(lèi)似微博那些設(shè)計(jì)到私有用戶(hù)的資源,需要能夠提供服務(wù)方用戶(hù)檢索特定資源的標(biāo)識(shí)(很明顯這些標(biāo)識(shí)在服務(wù)調(diào)用方必須已知,比如userId等XXXID,如果不得不需要,可以在用戶(hù)注冊(cè)服務(wù)調(diào)用方系統(tǒng)的時(shí)候自行填寫(xiě))。
這里你可能有一個(gè)疑問(wèn),公共資源就算了,受限資源為什么不需要用戶(hù)在服務(wù)提供方平臺(tái)的密碼?這里還是涉及到信任級(jí)別的問(wèn)題,我認(rèn)為這確實(shí)是一個(gè)需要權(quán)衡的問(wèn)題。或者說(shuō)需要視特定應(yīng)用場(chǎng)景以及資源的保護(hù)級(jí)別而定。上面提供的那些認(rèn)證信息(包括XXXID,服務(wù)提供方會(huì)在特定的數(shù)據(jù)表中檢索,以再次驗(yàn)證請(qǐng)求的合法性),足以表明服務(wù)的調(diào)用方確實(shí)是可信的,對(duì)于保護(hù)級(jí)別不是特別高(特別是應(yīng)對(duì)公司內(nèi)部,系統(tǒng)與系統(tǒng)之間的交互場(chǎng)景),最重要的是檢索數(shù)據(jù)的服務(wù)而言,就可以允許調(diào)用方獲取它想提取的信息了。當(dāng)然如果,確實(shí)需要得到資源擁有者的授權(quán),那么把用戶(hù)定向到服務(wù)提供者的授權(quán)頁(yè)面,也未嘗不可。
?
步驟2:返回服務(wù)調(diào)用方Access Token.這是關(guān)鍵的一步。與開(kāi)始我們談到的我們既有的兩種“驗(yàn)證方式”根本的不同點(diǎn)在于——服務(wù)提供者能夠控制局面。這里可以實(shí)現(xiàn)各種不同的安全機(jī)制,限制訪(fǎng)問(wèn)時(shí)間,限制訪(fǎng)問(wèn)次數(shù),限制IP在某一時(shí)間段內(nèi)的訪(fǎng)問(wèn)次數(shù)等等。你可以在服務(wù)提供程序中,對(duì)于前來(lái)握手的服務(wù)調(diào)用方的信息進(jìn)行維護(hù),如:
Application[“172.40.38.1”]=”asdfj2093423uwqesdjfdfepclkjd”;
采用訪(fǎng)問(wèn)者的ip作為key ,服務(wù)端生成的一串a(chǎn)ccsee token作為value,在服務(wù)提供端進(jìn)行維護(hù)。當(dāng)然,你可以定義一個(gè)結(jié)構(gòu):
class visitorInfo{ private int totalCount; //允許的總訪(fǎng)問(wèn)次數(shù) private int currentCount; //當(dāng)前已經(jīng)訪(fǎng)問(wèn)次數(shù) private DateTime startTime; //會(huì)話(huà)的開(kāi)始時(shí)間 private DateTime endTime; //會(huì)話(huà)的結(jié)束時(shí)間 Private string accessToken; //訪(fǎng)問(wèn)令牌 Private string reflushToken; //刷新token(可選的) }
以進(jìn)行更合理的控制并作日志記錄,至于怎么維護(hù)這個(gè)結(jié)構(gòu),在內(nèi)存中還是持久化到數(shù)據(jù)庫(kù),這個(gè)不是這篇的話(huà)題。
步驟2的輸出就是訪(fǎng)問(wèn)令牌當(dāng)然你也可以加上一個(gè)刷新令牌(這個(gè)是可選的,主要是為了在一次會(huì)話(huà)過(guò)期后,調(diào)用方可以拿著刷新令牌,直接換取一個(gè)新的訪(fǎng)問(wèn)令牌,而不需要重新認(rèn)證,當(dāng)然你也可以選擇讓調(diào)用方重新認(rèn)證。
第二次交互:服務(wù)的請(qǐng)求和應(yīng)答,這里就沒(méi)有什么特別的了。
步驟3:調(diào)用方拿著服務(wù)提供方授予的access token或者用戶(hù)檢索受限資源的XXXID,就可以請(qǐng)求服務(wù)了(只是普通的http請(qǐng)求)。這里,局面就可以完全被服務(wù)調(diào)用方hold住,它可以對(duì)IP和Access Token進(jìn)行驗(yàn)證,要是有必要,也可以對(duì)會(huì)話(huà)是否過(guò)期,或者一段時(shí)間內(nèi)的訪(fǎng)問(wèn)次數(shù)進(jìn)行驗(yàn)證,而無(wú)需擔(dān)心惡意中間人的重放或DOS攻擊。因?yàn)榉?wù)方維護(hù)了認(rèn)證過(guò)的調(diào)用方的access token以及IP。
步驟4:應(yīng)答請(qǐng)求。
?
總結(jié)
這里參考了OAuth協(xié)議的工作原理,并加以精簡(jiǎn)以適應(yīng)某些系統(tǒng)對(duì)系統(tǒng)提供服務(wù)的場(chǎng)景。再次聲明,這里只是在安全和性能之間找了一個(gè)平衡點(diǎn),使得你的服務(wù)應(yīng)用更為堅(jiān)固。如果你想要更為安全的做法,可以完全參照OAuth的設(shè)計(jì),強(qiáng)制要求用戶(hù)進(jìn)行授權(quán)(上面已經(jīng)解釋了應(yīng)該如何處理)。
無(wú)論如何,對(duì)于這種共享數(shù)據(jù)之類(lèi)的服務(wù),協(xié)商和人為交互的頻度還是比較大的,并且效率不是太高。有沒(méi)有從根本上解決這種問(wèn)題的辦法?有,那就是不提供這些服務(wù)。那應(yīng)該怎么辦?下一篇推崇——淺談企業(yè)業(yè)務(wù)數(shù)據(jù)的整合。敬請(qǐng)期待!
轉(zhuǎn)載于:https://www.cnblogs.com/wdpp/archive/2012/03/04/2386577.html
總結(jié)
以上是生活随笔為你收集整理的[置顶] OAuth工作原理随想——让你的系统提供的服务更加安全的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 共享一个查找IP所在交换机端口的方法
- 下一篇: 生成各种统计图的C#方法