rest風格api實踐初探

經常聽到rest風格api這個詞,那麼到底什麼是rest api呢?(Representational State Transfer)?表述性狀態轉移?《Spring實戰》上說:REST就是將資源的狀態已最合適的形式從服務器端轉移到客戶端。我在看了很多博客和資料後仍然感覺到頭大,我個人感覺關於這方面的資料很混亂,當然我確實也沒有那個心思去看REST提出者Roy Fielding的那篇博士論文Architectural Styles and the Design of Network-based Software Architecture 


很多資料上比較混亂的地方和我比較疑惑的地方是,比如:(1)協議到底要不要帶版本號呢?帶的話,標準做法是放到url中還是放到header中呢?對此,很多文章各持己見。(2)很多人自稱自己的做法是rest的,但是很多接口不區分增刪改查都用的是post方法,或者只用get(用於查詢資源),和post(用於增加、刪除和修改) (3)按照“標準”,查詢資源應該是get方法,可是有時候有些接口很複雜,查詢參數可能有幾十甚至上百個那麼多,很有可能會超過get請求的url長度最大限制啊。所以,我一度懷疑rest api是否真的適用於複雜接口的設計。(4)接口的url設計到底怎樣是“標準”的。比如,查詢作者名爲tom的、分類爲文學的書籍,http://域名/books/author/tom/class/literature  還是 http://域名/books?author=tom&class=literature  ,這兩種那種是標準的呢?或者這兩種都可以?


或者,我感覺實在是沒必要鑽牛角尖。那麼,我就談談我對rest api的幾點粗淺的認識吧:

(1)rest api操作的是資源,一個url就是一個資源,url中不應該出現動詞

(2)rest api對資源的操作包括C(Create) R(Read)  U(Update)  D(Delete),即增、查、改、刪,分別對應的http方法是 post、get、put 、delete。不同的接口可能對應的是同一個url,這時候不同的http方法就構成了不同的操作了。

(3)rest api是無狀態的,請求之間不應該有依賴。回想常見的網站架構,用戶登錄後將相關信息存放到session中,該用戶以後的相關操作從session中驗證權限。在rest中,要放棄session的使用,每一個請求之間是獨立的,每個需要鑑權的接口都要帶上鑑權信息。這種無狀態性有利於服務器的擴展。


下面,我簡單介紹下我最近寫的一個demo。

(1)項目簡介

這個demo很簡單,是一個記賬小工程。用戶可以註冊、修改密碼,可以記賬、查找記賬記錄等。


(2)接口介紹

用戶操作相關:

post        /users                    用戶註冊

post       /users/login       用戶登錄(這裏我把login當成一個名詞)

put         /users/pwd?userId=xxx&sign=xxx       用戶修改密碼

delete   /users?uerId=xxx&sign=xxx         刪除用戶


記賬記錄操作相關:

post    /records?userId=xxx&sign=xxx                          增加一條記賬記錄

get    /records/:id?userId=xxx&sign=xxx                     查詢一條記賬記錄詳情

put  /records/:id?userId=xxx&sign=xxx                      修改一條記賬記錄詳情                    

get    /records?查詢參數&userId=xxx&sign=xxx         分頁查詢記賬記錄 

delete  /records/:id?userId=xxx&sign=xxx                刪除一條記賬記錄


其中url中帶sign參數的表示該接口需要鑑權,sign必須是url中最後一個參數。具體的鑑權方法是:用戶登錄後,服務器生成返回一個token,然後客戶端要注意保存這個token,需要鑑權的接口加上sign簽名,sign=MD5(除sign外的url+token),這樣可以避免直接傳token從而泄露了token。這裏我覺得接口最好還帶一個時間戳參數timestamp,然後可以在服務端比較時間差,從而避免重放攻擊。而且這樣還有一個好處,就是如果有人截獲了我們的請求,他想僞造我們的請求則不得不改時間戳參數(因爲我們在服務器端會比較時間),這樣一來sign勢必會改變,他是無法得知這個sign的。如果我們沒有加時間戳參數的話,那麼,他截獲了請求url,再重發這個請求勢必又是一次合法的請求。我在這裏爲了簡單一些,就不加時間戳了,因爲這在開發測試階段實在是太麻煩了。


(3)關於redis和數據庫的說明

服務端在用戶登錄後,生成token,並將token保存到redis中。後面在接口鑑權的時候會取出token計算簽名,進行比對。

這個demo搭建了一個redis主從複製,具體可以參考:http://download.csdn.net/detail/zhutulang/9585010

數據庫使用mysql,腳本在 src/main/resources/accounting.sql


(4)項目地址

關於demo的細節這裏就不在詳述了,這個工程以後會再優化。demo可以在這裏下載:http://download.csdn.net/detail/zhutulang/9586998






發佈了119 篇原創文章 · 獲贊 46 · 訪問量 68萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章