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