1. 程式人生 > >HTTP 驗證 Tomcat中進行基本驗證 (Basic Authentication) 和摘要驗證 (Digest Authentication)

HTTP 驗證 Tomcat中進行基本驗證 (Basic Authentication) 和摘要驗證 (Digest Authentication)

HTTP 驗證

HTTP 協議提供驗證機制來保護資源。當一個請求要求取得受保護的資源時,網頁伺服器迴應一個 401 Unauthorized error 錯誤碼。這個迴應包含一個指定了驗證方法和領域的 WWW-Authenticate 頭資訊。把這個領域想像成一個儲存著使用者名稱和密碼的資料庫,它將被用來標識受保護資源的有效的使用者。比如,你試著去訪問某個網站上標識為“Personal Files”的資源,伺服器響應可能是:WWW-Authenticate: Basic realm="Personal Files" (假設驗證方法是 Basic)。

驗證方法

現在有幾種用於網路應用的驗證方法,其中最廣泛使用的是基本驗證 (Basic Authentication) 和摘要驗證 (Digest Authentication)。



當用戶想要訪問有限的資源時,使用基本驗證方法的網頁伺服器會要求瀏覽器詢顯示一個對話方塊,並要求使用者輸入使用者名稱和密碼。如果使用者輸入的使用者名稱和密碼正確,伺服器就允許他訪問這些資源;否則,在接連三次嘗試失敗之後,會顯示一個錯誤訊息頁面。這個方法的缺點是使用者名稱和密碼都是用 Base64 編碼 (全是可讀文字) 之後傳輸過去的。也就是說,這個驗證方法的安全程度只是和 Telnet 一樣,並不是非常安全。

資料驗證方法不會在網路中傳輸密碼,而是生成一些數字 (根據密碼和其它一些需要的資料產生的) 來代替密碼,而這些數字是經過 MD5 (Message Digest Algorithm) 加密的。生成的值在網路有隨著伺服器需要用來校難密碼的其它資訊一起傳輸。這個方法明顯更為安全。


基於表單的驗證方法和基本驗證方法類似,只是伺服器使用你自定義的登入頁面來代替了標準的登入對話方塊。

最後,客戶證書驗證使用 SLL (Secure Socket Layer,安全套接層) 和客戶證明。

在 Tomcat 下保護資源

你可以在 tomcat-users.xml 檔案中寫一個使用者及其角色的列表。這個檔案在 TOMCAT_HOME (你安裝 Tomcat 的目錄) 下的 conf 目錄中。這個檔案預設包含了三個使用者 (tomcat、role1、both) 的定義。下面一段 XML 程式碼是我添加了兩個新使用者 (qusay 和 reader) 之後的 tomcat-users.xml:


<tomcat-users>
<user name="tomcat" password="tomcat" roles="tomcat" />
<user name="role1" password="tomcat" roles="role1" />
<user name="both" password= "tomcat" roles="tomcat,role1" />
<user name="qusay" password="guesswhat" roles="author" />
<user name="reader" password="youguess" roles="reader" />
</tomcat-users>



新新增的兩個使用者 (qusay 和 reader) 的 roles 分別設定為 author 和 reader。角色屬性非常重要,因為當你建立安全規則的時候,每個受限制的資源都是與可訪問它的角色相關聯 (稍後你會看到)。

下面做個實驗 (假設你已經安裝並配置好了 Tomcat)。為你期望的頁應用程式建立一個目錄。可以按下列步驟做好準備:

1. 在你安裝了 Tomcat 的目錄下,有一個目錄是 webapps。在這個目錄下建立一個目錄 (如:learn)。 
2. 在第一步建立的目錄下建立一個子目錄,命名為 chapter。 
3. 在 chapter 目錄中,建立一個 HTML 檔案,內容自定,檔名為 index.html。 
4. 在第一步建立的目錄下建立一個名為 WEB-INF 的子目錄。 
5. 在 WEB-INF 目錄中建立一個名為 web.xml 的檔案,該檔案內容如下: 



6. <?xml version="1.0" encoding="ISO-8859-1"?>
7. 
8. <!DOCTYPE web-app
9. PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
10. "http://java.sun.com/dtd/web-app_2_3.dtd">
11. 
12. <web-app>
13. 
14. <description>
15. Learning Web Programming
16. </description>
17. 
18. <security-constraint>
19. <web-resource-collection>
20. <web-resource-name>
21. Restricted Area
22. </web-resource-name>
23. <url-pattern>/chapter/*</url-pattern>
24. </web-resource-collection>
25. <auth-constraint>
26. <role-name>tomcat</role-name>
27. <role-name>author</role-name>
28. <role-name>reader</role-name>
29. </auth-constraint>
30. </security-constraint>
31. 
32. <login-config>
33. <auth-method>BASIC</auth-method>
34. <realm-name>Authenticate yourself</realm-name>
35. </login-config>
36. 
</web-app>




web.xml 配置描述

web.xml 是描述配置的檔案,這裡集中說明一下安全相關的配置元素。

<security-constraint>:這個元素限制對一個或者多個資源的訪問,可以在配置資訊中出現多次。上面的配置資訊中,它限制了 chapter 目錄 (http://localhost:8080/learn/chapter) 下所有資源的訪問。<security-constraint> 包含了下列元素:
o <web-resource-collection>:這個元素用於標識你想限制訪問的資源。你可以定義 URL 模式 和 HTTP 方法 (用 <http-method> 元素定義 HTTP 方法)。如果沒有定義 HTTP 方法,那麼限制將應用於所有方法。在上面的應用中,我想限制訪問的資源是 http://localhost:8080/learn/chapter/*,也就是 chapter 目錄下的所有文件。
o <auth-constraint>:這個元素可以訪問上面定義的受限資源的使用者角色。在上面的應用中,tomcat、author 和 erader 這三個角色可以訪問這些資源。 

<login-config>:這個元素用於指定驗證方法。它包含下列元素:
o <auth-method>:指定驗證方法。它的值可能是下列值集中的一個:BASIC (基本驗證)、DIGEST (摘要驗證)、FORM (基於表單的驗證) 或者 CLIENT-CERT (客戶證書驗證)。
o <realm-name>:如果選用 BASIC 方法進行驗證的時候,標準登入對話方塊中的一個描述名稱。 

示例

上述配置中使用了 BASIC 驗證方法。下面我們做個實驗:啟動你的 Tomcat 伺服器並向它傳送到 http://localhost:8080/learn/chapter 的請求。這時候,就會有像圖 3 所示那樣的對話方塊提示你輸入使用者和密碼:


圖 3:HTTP 基本驗證 (Basic Authentication)



輸入一個使用者及其密碼 (你可以看看 tomcat-users.xml 檔案),這個使用者的角色應該在配置 (web.xml) 中存在。如果你輸入的使用者名稱和密碼正確,你就能訪問到那些資源;否則,你還可以再試兩次。

使用摘要驗證來實驗:

· 關閉你的 Tomcat 伺服器。 
· 修改你的配置檔案 (web.xml),把 BASIC 換成 DIGEST。 
· 重新啟動你的 Tomcat 伺服器。 
· 開啟一個新的瀏覽器視窗。 
· 在位址列中輸入 http://localhost:8080/learn/chapter 並回車。 

你會看到類似的對話方塊。從圖 4 你可以看到,這個登入對話方塊是安全的,因為使用了摘要驗證。



圖 4:HTTP 摘要驗證 (Digest Authentication)



伺服器在幕後的回覆

當使用基本驗證方法保護資源的時候,伺服器發回類似於圖 5 所示的響應資訊:


圖 5:伺服器回覆 (基本驗證)



如果是使用的摘要驗證方法來保護的資源,伺服器發回的響應資訊就像圖 6 所示的那樣:



圖 6:伺服器回覆 (摘要驗證)



Java 支援 HTTP 驗證

J2SE (1.2 或者更高版本) 通過 Authenticator 類為驗證提供了本地支援。你所要做的只是繼承這個類並實現它的 getPasswordAuthentication 方法。這個方法取得使用者名稱和密碼並用它們生成一個 PasswordAuthentication 物件返回。完成之後,你還得使用 Authenticator.setDefault 方法註冊你的 Authenticator 例項。現在,只要你想訪問受保護的資源,就會呼叫 getPasswordAuthentication。Authenticator 類管理著所有低層的詳細資料。它不受 HTTP 的限制,可以應用於所有網路連線,這不能不說是一個好訊息。

示例程式碼 6 中是實現 Authenticator 的一個示例。正如你所看到的,在請求驗證的時候,getPasswordAuthentication 方法會彈出一個登入對話方塊。

示例程式碼 6:AuthImpl.java


import java.net.*;
import java.awt.*;
import javax.swing.*;

public class AuthImpl extends Authenticator {
protected PasswordAuthentication getPasswordAuthentication() {
JTextField username = new JTextField();
JTextField password = new JPasswordField();
JPanel panel = new JPanel(new GridLayout(2,2));
panel.add(new JLabel("User Name"));
panel.add(username);
panel.add(new JLabel("Password") );
panel.add(password);
int option= JOptionPane.showConfirmDialog(null,
new Object[] {"Site: "+getRequestingHost(),
"Realm: "+getRequestingPrompt(),panel},
"Enter Network Password",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
if ( option == JOptionPane.OK_OPTION ) {
String user = username.getText();
char pass[] = password.getText().toCharArray();
return new PasswordAuthentication(user, pass);
} else {
return null;
}
}
}



示例程式碼 7 用來做測試的程式碼。我做的第一件事情就是用 Authenticator.setDefault 讓我的 Authenticator 例項開始執行。我不必去解析任何伺服器返回的資訊以檢查是否需要驗證,因為 Authenticator 類非常聰明,它知道是否需要驗證。

示例程式碼 7:BasicReader.java


import java.io.*;
import java.net.*;

public class BasicReader {
public static void main(String argv[]) throws Exception {
Authenticator.setDefault(new AuthImpl());
if (argv.length != 1) {
System.err.println("Usage: java BasicReader <site>");
System.exit(1);
}
URL url = new URL(argv[0]);
URLConnection connection = url.openConnection();
BufferedReader in= new BufferedReader(new InputStreamReader(connection.getInputStream()));

String line;
StringBuffer sb = new StringBuffer();
while ((line = in.readLine()) != null) {
sb.append(line);
}
in.close();
System.out.println(sb.toString());
System.exit(0);
}
}



執行下面的命令,用 Tomcat 來進行測試:

prompt> java BasicReader http://localhost:8080/learn/chapter

如果你進入的站點需要驗證 (它也這樣做了),那會像圖 7 那樣的對話方塊就會顯示出來。


圖 7:Java 處理 HTTP 驗證



一旦你輸入了正確的使用者名稱和密碼,伺服器就會允許你訪問。BasicReader 會讀取被請求頁面的 HTML 內容並顯示在你的控制檯視窗。

特別注意:在 Tomcat 4.0 中使用摘要驗證時你可能會遇到問題,這是由 J2SE 1.4.0 和 J2SE 1.4.1 的一個 BUG 引起的。不過這個問題已經在 J2SE 1.4.2 中解決了。詳情情看這裡。 

總結

這篇文章是一篇教程,它介紹了 java.net 包的高層 API。這些 API 使你可以快速簡捷地建立有用的網路應用程式,如 StockReader。這裡也討論了 HTTP 驗證,並用例項演示瞭如何使用你自己的驗證方案。URL 和 URLConnection 還有一些優勢沒有在文中提到,它們包括:自動重定向、自動管理保持的連線等。不過現在你已經從文中獲得基礎知識,可以自己解決這些問題了。