最近想拿乙個小專案來試水restful web api,專案只有幾個呼叫,比較簡單,但同樣需要身份驗證,如果是傳統的**的話,那不用說,肯定是使用者名稱+密碼在登入頁獲得登入token,並把登入token記在cookie和session中作為身份標識的這種方式,但現在不同了,關鍵是restful,這意味著我們設計出來的這些api是無狀態的(stateless),下一次的呼叫請求和這一次的呼叫請求應該是完全無關的,也就是說,正宗的restful web api應該是每次呼叫都應該包含了完整的資訊,沒錯,包括身份資訊!
那如何確保安全?傳輸時給密碼做md5加密?得了吧!這樣做只能讓你自己感覺「安全」點,其實沒什麼任何用處,利用現在的技術(有種叫什麼rainbow table啥的來著?本人外行,不是很懂)很快就能算出明文密碼了,而且如何防止挾持和重發攻擊?
也許你想到了,ssl,如果你打算採用ssl,請忘記一切自行設計的加密方案,因為ssl已經幫你做好了一切,包括防止監聽,防止挾持,防止重發……一切都幫你考慮好了,你大膽地把明文密碼寫在你的包中就ok了,我向你保證沒問題。
但ssl的缺點是伺服器端配置相對有點複雜,更關鍵的就是客戶端對此支援可能不好,那你考慮一種自己的加密方法,有木有?我這裡提供一種方法,思路來自於:我只是把上面的內容中整理了一下變成了我的方法。(傳說中的剽竊?呵呵)方法描述如下:
假設有乙個使用者,使用者名稱是guogangj,密碼是123456(呃……這也能叫密碼?)
他要get
於是把 這個url和乙個新生成的guid拼在一起,再用123456這個密碼執行對稱加密,生成的密文為***xoooo***xoooo(假設而已)
資料報中帶上使用者名稱guogangj和***xoooo***xoooo這個密文,傳送給伺服器
伺服器收到包後,根據guogangj這個使用者名稱到資料庫中查詢到123456這個密碼
伺服器使用123456這個密碼來解密***xoooo***xoooo這個密文,得到了明文,即這個url和前面由客戶端生成的那個guid
伺服器到乙個全域性的集合中查詢這個guid,看看是否已經存在,如果存在,則驗證不通過,如果不存在,就將其放入這個集合中。這是為了避免重發攻擊。這個全域性的集合會越來越大,所以還要定期清理。
伺服器再比對解密出來的url和使用者真實請求的url是否一致,如果一致,那麼認為這是合法使用者,驗證通過!
這是大致過程,如果資料庫裡找不到該使用者,或者解密錯誤,都被認為驗證不通過。以下是一些改進:
資料庫中的密碼最好做一下摘要(md5之類的),客戶端對應地也要做一下。
在生成密文的時候可以考慮加入另外一些不希望被明文傳輸的敏感內容,甚至可以加入ip位址,並在伺服器端驗證。
並非每次都要真正去資料庫裡拿一次使用者資訊,也許你有更好的辦法,比如乙個簡單的快取(不過需要處理快取更新的問題),或者當你的系統大到一定程度的時候,你考慮使用統一的服務來獲取使用者資訊,這就不是快取那麼簡單了,裡面的文章很多,我相信現在大規模的門戶**都有自己的一套複雜的機制,所以表明上看restful web api很「低效」,但這種restful的思路和模式卻在實際中有很大的可塑性和威力。
這種方法應該足夠安全了!
密碼根本沒有在網路上傳輸,密文採用的是非驗證的對稱加密,沒有金鑰就無法逆轉,url驗證避免了傳統的身份挾持攻擊(即攔截乙個使用者的包並冒充此使用者來訪問其它的資源,即便無法破解使用者密碼), 再用guid來避免了重發攻擊,唯一需要擔心的是使用者洩露了自己的密碼
如何實現佇列
實現乙個佇列的資料結構,使其具有入佇列,出佇列,檢視佇列首尾元素,檢視佇列大小等功能。方法一 陣列實現 class myqueue1 def init self self.arr self.front 0 self.rear 0 判斷佇列是否為空 def isempty self return se...
如何實現 virtual dom
相信大部分前端同學之前早已無數次聽過或了解過vnode 虛擬節點 那麼什麼是vnode?vnode應該是什麼樣的?如果不使用前端框架,我們可能會寫出這樣的頁面 不難發現,整個文件樹的根節點只有乙個html,然後巢狀各種子標籤,如果使用某種資料結構來表示這棵樹,那麼它可能是這樣。但是實際開發中,整個文...
ConcurentHashMap如何實現執行緒安全
hashmap是非執行緒安全,在多執行緒環境不能夠使用。hashtable 本身比較低效,因為它的實現基本就是將 put get size 等各種方法加上 synchronized 簡單來說 這就導致了所有併發操作都要競爭同一把鎖,乙個執行緒在進行同步操 作時,其他執行緒只能等待,大大降低了併發操作...