關於WSSE驗證-- 一種驗證使用者的方法
阿新 • • 發佈:2019-02-03
轉自: http://www.iteye.com/topic/434867
大家通常驗證使用者做法:
1. BASIC驗證模式: 把使用者名稱和密碼採用Base64編碼之後,放在HTTP HEADER裡,發到伺服器的。
2. FORM驗證模式: 就什麼都不處理,直接發到伺服器。
3. 還有其他證書驗證,摘要驗證等,這些不在這篇文章討論範圍。
由於是明文傳輸,密碼很容易被截獲,從而造成密碼的丟失。今天和老大討論RESTful的模式時,想到了認證的問題,因為REST提倡無狀態,我們老大提到了WSSE的問題,於是我就搜尋一下。
密碼傳輸的問題通常是用HTTPS來解決,當然這個很完美,但有些限制。有些情況下不能用HTTPS來解決,例如多個應用使用一個單獨IP地址來訪問時,由於伺服器證書裡的資訊和域名是必須匹配的,所以一個應用使用了HTTPS, 而另一個就不能用了。還有一個辦法就是用摘要驗證,當然也可以解決這個問題,但是需要在伺服器上配置相應的功能模組。如果伺服器不可控(例如臨時借用別人的伺服器)也沒有辦法做到。
而WSSE的驗證模式可以解決以上問題。不需在伺服器做額外配置。具體過程如下:
1. 開始於兩個資訊: 使用者名稱和密碼。
2. 建立一個隨機的nonce(不知道應該譯成什麼,反正就是隨機的一個只能用一次的字串),這個產生演算法要夠強健,不能讓人猜出下一個產生的是什麼。
3.建立一個"產生時間戳", 並轉換成W3DTF格式
4.建立一個密碼摘要:
PasswordDigest = Base64 \ (SHA1 (Nonce + CreationTimestamp + Password))
舉例說明:
1.使用者發一個請求:
Http程式碼
-
POST /atom.cgi HTTP/1.1
- Host: bob.example.com
- Content-Type: application/atom+xml
- <?xml version="1.0" encoding="utf-8"?>
- <entry xmlns="http://purl.org/atom/ns#">
- <title>My Entry Title</title>
- <created>2003-12-15T14:43:07Z</created>
-
<content type="application/xhtml+xml" xml:lang="en"
- <div xmlns="http://www.w3.org/1999/xhtml">
- <p>Hello, <em>weblog</em> world!</p>
- <p>This is my third post <strong>ever</strong>!</p>
- </div>
- </content>
- </entry>
2. 由於沒有驗證資訊,伺服器以401來響應:
Http程式碼
- HTTP/1.1 401 Unauthorized
- WWW-Authenticate: WSSE realm="foo", profile="UsernameToken"
注:還有的文章講這裡伺服器生成一個nonce, 然後在下一步附加到Request裡,一塊參與摘要生成。這個server nonce本身好像沒有什麼用途,但由於客戶端nonce沒有生成規則和長度限制(甚至如果伺服器不儲存以前使用過的,都無法判斷是不是每次都一樣的),而生成一個server nonce參與生成摘要可以保證摘要的變化性,就是每次都不一致。由於這個nonce是臨時生成,一次有效,中間被人截獲也無所謂。在驗證時,由於是摘要驗證,伺服器必須儲存這個nonce到驗證結束,然後再及時清除。不過加了server nonce的限制,必然會使訪問服務的客戶端訪問兩次伺服器才能真正訪問服務,就是不能直接把身份資訊附加上,直接訪問服務。感覺這個就是標準的摘要驗證差不多了,就變成了"請求-響應"模式了。
3. 使用者輸入使用者名稱和密碼,並且生成摘要,以UserToken形式傳送到伺服器:
Http程式碼
- POST /atom.cgi HTTP/1.1
- Host: bob.example.com
- Content-Type: application/atom+xml
- Authorization: WSSE profile="UsernameToken"
- X-WSSE: UsernameToken Username="bob", PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=", Nonce="d36e316282959a9ed4c89851497a717f", Created="2003-12-15T14:43:07Z"
- <?xml version="1.0" encoding="utf-8"?>
- <entry xmlns="http://purl.org/atom/ns#">
- <title>My Entry Title</title>
- <created>2003-12-15T14:43:07Z</created>
- <content type="application/xhtml+xml" xml:lang="en">
- <div xmlns="http://www.w3.org/1999/xhtml">
- <p>Hello, <em>weblog</em> world!</p>
- <p>This is my third post <strong>ever</strong>!</p>
- </div>
- </content>
- </entry>
4.伺服器通過時間戳和Nonce以及伺服器儲存的密碼進行生成摘要,如果通過驗證就可以允許使用者訪問資源。
這樣一個過程,我覺得能解決一些問題,但是還有一些疑問:
1.由於客戶要生成摘要和client nonce,客戶端必須具有生成它們的能力,或者瀏覽器支援這種協議。
現在客戶端的能力都比較強大,javascript就可以實現摘要的生成。具體程式參考:http://pajhome.org.uk/crypt/md5/,目前為止好像不沒有哪個瀏覽器支援這種協議的。
2.由於只發送摘要,並沒有真正傳送密碼,解決中間攻擊的擔憂。
這個不錯,就要的這種效果。
3.由於nonce是隻用一次,下次就隨機產生另一個,由於這個是在客戶端產生的,如果產生暴力猜測密碼的情況怎麼辦?
這裡的nonce只用一次就失效,可以防止黑客的replay攻擊。但這過程中沒有防止暴力攻擊,不過有一個時間戳應該可以利用,如在伺服器判斷3或者1,2秒之內不能重試登入, 這個雖然不能完全避免,但至少可以減少一些攻擊次數。其實最好的解決辦法就是強口令,一個強口令就把這個問題解決的比較徹底了。如果不能強制使用者使用強口令的話,我們可以加入通常採用的驗證碼的機制。還有就是上面提到的server nonce應該也可以直到一些作用。
4.如果伺服器不儲存真正的密碼,而是隻儲存摘要的話,那用這種方法豈不是不能驗證使用者的合法性了?
如果伺服器不儲存真正的密碼,而是摘要。如LDAP裡一般就不儲存明文密碼,一般資料庫裡也不會儲存真正明文密碼,這個問題我還真想不到什麼辦法。如果伺服器的摘要演算法和客戶端完全一致的話,可以用以下方法生成客戶端摘要:
PasswordDigest = Base64 \ (SHA1 (Nonce + CreationTimestamp + DIGEST(Password)))。
就是把Password生成摘要,然後再用組合生成新的摘要。這樣在伺服器端也能順利的驗證使用者的合法性。
我覺得這個方法可以和其他方法結合使用,應該效果不錯。至少多了一層防護。
本文的思想主要來自:http://www.xml.com/pub/a/2003/12/17/dive.html, 也引用他的測試的HTTP資料。加上我自己的理解。
如有不妥,希望能夠得到指正。最後感謝“Atom Authentication”文章作者Mark。但是這裡面的Atom和WSSE有什麼關係,並沒有搞清楚,可能Atom只是WSSE的一種實現? 望知道的哥們姐妹給一些提示。