Spring Http Basic(基本)和Digest(摘要)驗證
Basic(基本)和Digest(摘要)驗證都是web應用中很受歡迎的可選機制。 Basic驗證一般用來處理無狀態的客戶端,它們在每次請求都附帶它們的證書。 很常見的用法是把它和基于表單的驗證一起使用,這里的應用會同時使用基于瀏覽器的用戶接口和web服務。 然而,basic驗證使用原文傳送密碼,所以應該只通過加密的傳輸途徑發送,比如HTTPS。
BasicAuthenticationFilter負責處理通過HTTP頭部發送來的basic驗證證書。 它可以用來像對待普通用戶代理一樣(比如IE和Navigator)認證由Spring遠程協議的調用(比如Hessian和Burlap)。 HTTP基本認證的執行標準定義在RFC 1945,11章,BasicAuthenticationFilter符合這個RFC。 基本認證是一個極具吸引力的認證方法,因為它在用戶代理發布很廣泛, 實現也特別簡單(只需要對username:password進行Base64編碼,再放到HTTP頭部里)。
要實現HTTP基本認證,要先在過濾器鏈里定義BasicAuthenticationFilter。 還要在application context里定義BasicAuthenticationFilter和協作的類:
<bean id="basicAuthenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter"> <property name="authenticationManager" ref="authenticationManager"/> <property name="authenticationEntryPoint" ref="authenticationEntryPoint"/> </bean> <bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint"> <property name="realmName" value="Name Of Your Realm"/> </bean>
配置好的AuthenticationManager會處理每個認證請求。 如果認證失敗,配置好的AuthenticationEntryPoint會用來重試認證過程。 通常你會使用BasicAuthenticationEntryPoint,它會返回一個401響應,使用對應的頭部重試HTTP基本驗證。 如果驗證成功,就把得到的Authentication對象放到SecurityContextHolder里。
如果認證事件成功,或者因為HTTP頭部沒有包含支持的認證請求所以沒有進行認證,過濾器鏈會像通常一樣繼續下去。 唯一打斷過濾器的情況是在認證失敗并調用AuthenticationEntryPoint的時候,向上面段落里討論的那樣。
Spring Security提供了一個 DigestAuthenticationFilter,它可以處理HTTP頭部中的摘要認證證書。 摘要認證在嘗試著解決許多基本認證的缺陷,特別是保證不會通過純文本發送證書。 許多用戶支持摘要式認證,包括FireFox和IE。 HTTP摘要式認證的執行標準定義在RFC 2617,它是對RFC 2069這個早期摘要式認證標準的更新。 Spring Security DigestAuthenticationFilter會保證"auth"的安全質量(qop),它訂明在RFC 2617中,并與RFC 2069提供了兼容。 如果你需要使用沒有加密的HTTP(比如沒有TLS/HTTP),還希望認證達到最大的安全性的時候,摘要式認證便具有很高吸引力。 事實上,摘要式認證是WebDAV協議的強制性要求,寫在RFC 2518的17.1章,所以我們應該期望看到更多的代替基本認證。
摘要式認證,是表單認證,基本認證和摘要式認證中最安全的選擇,不過更安全也意味著更復雜的用戶代理實現。 摘要式認證的中心是一個“nonce”。 這是由服務器生成的一個值。 Spring Security的nonce采用下面的格式:
base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
expirationTime: The date and time when the nonce expires, expressed in milliseconds
key: A private key to prevent modification of the nonce token
這個DigestAuthenticationEntryPoint有一個屬性,通過指定一個key來生成nonce標志,通過nonceValiditySeconds屬性來決定過期時間(默認300,等于5分鐘)。 只要nonce是有效的,摘要就會通過串聯字符串計算出來,包括用戶名,密碼,nonce,請求的URI,一個客戶端生成nonce(僅僅是一個隨機值,用戶代理每個請求生成一個),realm名稱等等,然后執行一次MD5散列。 服務器和用戶代理都要執行這個摘要計算,如果他們包含的值不同(比如密碼),就會生成不同的散列碼。 在Spring Security的實現中,如果服務器生成的nonce已經過期(但是摘要還是有效),DigestAuthenticationEntryPoint會發送一個"stale=true"頭信息。 這告訴用戶代理,這里不再需要打擾用戶(像是密碼和用戶其他都是正確的),只是簡單嘗試使用一個新nonce。
DigestAuthenticationEntryPoint的 nonceValiditySeconds參數,會作為一個適當的值依附在你的程序上。 對安全要求很高的用戶應該注意,一個被攔截的認證頭部可以用來假冒主體,直到nonce達到expirationTime。 在選擇合適的配置的時候,這是一個必須考慮到的關鍵性條件,但是在對安全性要求很高的程序里,第一次請求都會首先運行在TLS/HTTPS之上。
因為摘要式認證需要更復雜的實現,這里常常有用戶代理的問題。 比如,IE不能在同一個會話的請求進程里阻止"透明"標志。 因此Spring Security把所有狀態信息都概括到"nonce"標記里。 在我們的測試中,Spring Security在FireFox和IE里都可以工作,正確的處理nonce超時等等。
現在我們重新看一下理論,讓我們看看如何使用它。 為了實現HTTP摘要認證,必須在過濾器鏈里定義DigestAuthenticationFilter。 application context還需要定義DigestAuthenticationFilter和它需要的合作伙伴:
<bean id="digestnFilter" class=
"org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
<property name="userDetailsService" ref="jdbcDaoImpl"/>
<property name="authenticationEntryPoint" ref="digestEntryPoint"/>
<property name="userCache" ref="userCache"/>
</bean>
<bean id="digestEntryPoint" class=
"org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
<property name="realmName" value="Contacts Realm via Digest Authentication"/>
<property name="key" value="acegi"/>
<property name="nonceValiditySeconds" value="10"/>
</bean>
需要配置一個UserDetailsService,因為 DigestAuthenticationFilter必須直接訪問用戶的純文本密碼。 如果你在DAO中使用編碼過的密碼,摘要式認證就沒法工作。 DAO合作者,與UserCache一起,通常使用DaoAuthenticationProvider直接共享。 這個AuthenticationEntryPoint屬性必須是DigestAuthenticationEntryPoint,這樣DigestAuthenticationFilter可以在進行摘要計算時獲得正確的realmName和key。
像BasicAuthenticationFilter一樣,如果認證成功,會把Authentication請求標記放到SecurityContextHolder中。 如果認證事件成功,或者認證不需要執行,因為HTTP頭部沒有包含摘要認證請求,過濾器鏈會正常繼續。 過濾器鏈中斷的唯一情況是,如果認證失敗,就會像上面討論的那樣調用AuthenticationEntryPoint。
摘要式認證的RFC要求附加功能范圍,來更好的提升安全性。 比如,nonce可以在每次請求的時候變換。 但是,Spring Security的設計思路是最小復雜性的實現(毫無疑問,用戶代理會出現不兼容),也避免保存服務器端的狀態。 如果你想研究這些功能的更多細節,我們推薦你看一下RFC 2617。 像我們知道的那樣,Spring Security實現類遵守了RFC的最低標準。
來自: http://blog.csdn.net//mrcharles/article/details/50475467