基于 HTTP 的應(yīng)用程序
java.net 包中的類和接口提供了可用于低層和高層網(wǎng)絡(luò)編程的 API。低層 API 可以讓你直接訪問網(wǎng)絡(luò)協(xié)議,但是為此你不得不使用低層的 TCP 套接字和 UDP 數(shù)據(jù)包。高層的 API (如 URL, URLConnection 和 httpURLConnection 等類) 可以使你更快的開發(fā)網(wǎng)絡(luò)應(yīng)用,卻不需要寫很多代碼。
另一篇文章,《Network Programming with J2SE 1.4》會(huì)告訴你如何使用低層的套接字進(jìn)行網(wǎng)絡(luò)編程。這篇文章的重點(diǎn)則放在如何使用 java.net 包中的高層 API 開發(fā)基于 HTTP 的應(yīng)用程序。
這篇文章將有如下內(nèi)容:
- 概覽 HTTP
- 概覽 java.net 包的高層 API
- 示例說明如何使用高層 API
- 制作一個(gè)可以下載股票行情的應(yīng)用程序
- 演示如何提交數(shù)據(jù)到網(wǎng)頁服務(wù)器
- 概覽 HTTP 的驗(yàn)證并展示如何保護(hù)你的網(wǎng)絡(luò)資源
- 提供代碼實(shí)例演示如何執(zhí)行 HTTP 的驗(yàn)證
概覽 HTTP
超文本傳輸協(xié)議 (Hypertext Transfer Protocol, HTTP) 是一個(gè)“請(qǐng)求-回應(yīng)”的應(yīng)用協(xié)議。這個(gè)協(xié)議支持一套固定的方法如 GET、POST、PUT、DELETE 等。一般用 GET 方法向服務(wù)器請(qǐng)求資源。這里有兩個(gè) GET 請(qǐng)求的例子:
GET / HTTP/1.1
GET /names.html HTTP/1.1
另外,你可以使用 GET 和 POST 方法向服務(wù)器發(fā)送數(shù)據(jù),它們向服務(wù)器發(fā)送數(shù)據(jù)的方式是不同的:
- GET 方法:輸入的數(shù)據(jù)將作為 URL 的一部分發(fā)送
- POST 方法:輸入數(shù)據(jù)作為一個(gè)獨(dú)立的實(shí)體發(fā)送
考慮一下下面的 HTML 表單:
<form action="http://www.javacourses.com/servlets/getMarks method="GET">
Student#:
<input type=text name=number size=30>
<input type=submit name=GetMarks value=GetMarks>
</form>
這個(gè)表單會(huì)提交到 http://www.javacourses.com/servlet/getMarks 由 Servlet 處理。該表單使用了 GET 方法來傳輸信息。如果用戶輸入一個(gè)學(xué)號(hào)——比如 556677——并點(diǎn)擊 GetMarks 按鈕,表單數(shù)據(jù)就會(huì)作為 URL 的一部分傳送到 Servlet 中。經(jīng)過編碼之后的 URL 就是:http://www.javacourses.com/servlets/getMarks?number=556677。
在使用 POST 方法的情況下,傳輸數(shù)據(jù)時(shí)不會(huì)將數(shù)據(jù)作為 URL 的一部分;它們會(huì)作為一個(gè)獨(dú)立的實(shí)體來傳輸。因此,POST 方法更安全,你也可以用這個(gè)方法傳輸更多的數(shù)據(jù)。而且用 POST 傳輸?shù)臄?shù)據(jù)不一定要是文本,用 GET 方法傳輸?shù)膮s一定要是文本。
消息息格式
請(qǐng)求消息指定了方法名稱 (GET 或者 POST)、URL、協(xié)議版本號(hào)、頭部消息和可選消息。頭部消息也許會(huì)包含請(qǐng)求信息和客戶端信息,如接受的內(nèi)容類型、瀏覽器名稱以及驗(yàn)證數(shù)據(jù)。返回消息指定了協(xié)議版本、響應(yīng)代碼和原因。不管執(zhí)行是否成功,響應(yīng)代碼和原因都會(huì)報(bào)告。一些響應(yīng)代碼如下:
200 OK: Request succeeded. The requested resource can be found later in this message.
301 Moved Permanently: Requested resource has moved. New location is specified later in this message.
400 Bad Request: Request message is not understood by the server.
404 Not Found: Requested document is not found on this server.
關(guān)于 HTTP 和所有返回代碼的信息可以在 HTTP 1.1 規(guī)范 RFC2616 中找到。
下面是一個(gè)請(qǐng)求消息由瀏覽器到服務(wù)器的例子。這里請(qǐng)求的 URL 是 http://java.sun.com:
GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/vnd.ms-powerpoint, application/vnd.ms-excel,
application/msword, */*
Accept-Language: en-ca
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows 98; YComp 5.0.0.0)
Host: java.sun.com
Connection: Keep-Alive
Cookie: SUN_ID=24.80.19.177:28346100732290;
SunONEUserId=24.80.19.177:86521021960770
然后這里是服務(wù)器對(duì)這個(gè)請(qǐng)求的回復(fù)消息:
HTTP/1.1 200 OK
Server: Netscape-Enterprise/6.0
Date: Mon, 14 Oct 2002 15:18:04 GMT
Content-type: text/html
Connection: close
概覽 java.net 包的高層 API
java.net 包中含有高層 API。它們實(shí)現(xiàn)了一些最常用的基于 TCP 的協(xié)議,如 HTTP 和 FTP 等。其中兩個(gè)主要的類是 URL 和 URLConnection。另一個(gè)有用的類是 HttpURLConnection,它是 URLConnection 的子類,支持 HTTP 的特性。
URL (Uniform Resource Locator,統(tǒng)一資源定位器) 是一個(gè)描述 Internet 中文檔 (或者其它常見的資源) 位置的地址。URL 的樣子就像這樣:
protocol://machineName:port/resource
注意 URL 類不是基于 HTTP 的,這一點(diǎn)非常重要。它支持 FTP、HTTPS 和 FILE
Java 高層網(wǎng)絡(luò)編程
原文:Java 高層網(wǎng)絡(luò)編程
這篇文章將有如下內(nèi)容: · 概覽 HTTP · 概覽 java.net 包的高層 API · 示例說明如何使用高層 API · 制作一個(gè)可以下載股票行情的應(yīng)用程序 · 演示如何提交數(shù)據(jù)到網(wǎng)頁服務(wù)器 · 概覽 HTTP 的驗(yàn)證并展示如何保護(hù)你的網(wǎng)絡(luò)資源 · 提供代碼實(shí)例演示如何執(zhí)行 HTTP 的驗(yàn)證 概覽 HTTP 超文本傳輸協(xié)議 (Hypertext Transfer Protocol, HTTP) 是一個(gè)“請(qǐng)求-回應(yīng)”的應(yīng)用協(xié)議。這個(gè)協(xié)議支持一套固定的方法如 GET、POST、PUT、DELETE 等。一般用 GET 方法向服務(wù)器請(qǐng)求資源。這里有兩個(gè) GET 請(qǐng)求的例子: GET / HTTP/1.1 GET /names.html HTTP/1.1 另外,你可以使用 GET 和 POST 方法向服務(wù)器發(fā)送數(shù)據(jù),它們向服務(wù)器發(fā)送數(shù)據(jù)的方式是不同的: · GET 方法:輸入的數(shù)據(jù)將作為 URL 的一部分發(fā)送 · POST 方法:輸入數(shù)據(jù)作為一個(gè)獨(dú)立的實(shí)體發(fā)送 考慮一下下面的 HTML 表單:
這個(gè)表單會(huì)提交到 http://www.javacourses.com/servlet/getMarks 由 Servlet 處理。該表單使用了 GET 方法來傳輸信息。如果用戶輸入一個(gè)學(xué)號(hào)——比如 556677——并點(diǎn)擊 GetMarks 按鈕,表單數(shù)據(jù)就會(huì)作為 URL 的一部分傳送到 Servlet 中。經(jīng)過編碼之后的 URL 就是:http://www.javacourses.com/servlets/getMarks?number=556677。 在使用 POST 方法的情況下,傳輸數(shù)據(jù)時(shí)不會(huì)將數(shù)據(jù)作為 URL 的一部分;它們會(huì)作為一個(gè)獨(dú)立的實(shí)體來傳輸。因此,POST 方法更安全,你也可以用這個(gè)方法傳輸更多的數(shù)據(jù)。而且用 POST 傳輸?shù)臄?shù)據(jù)不一定要是文本,用 GET 方法傳輸?shù)膮s一定要是文本。 消息息格式 請(qǐng)求消息指定了方法名稱 (GET 或者 POST)、URL、協(xié)議版本號(hào)、頭部消息和可選消息。頭部消息也許會(huì)包含請(qǐng)求信息和客戶端信息,如接受的內(nèi)容類型、瀏覽器名稱以及驗(yàn)證數(shù)據(jù)。返回消息指定了協(xié)議版本、響應(yīng)代碼和原因。不管執(zhí)行是否成功,響應(yīng)代碼和原因都會(huì)報(bào)告。一些響應(yīng)代碼如下:
關(guān)于 HTTP 和所有返回代碼的信息可以在 HTTP 1.1 規(guī)范 RFC2616 中找到。 下面是一個(gè)請(qǐng)求消息由瀏覽器到服務(wù)器的例子。這里請(qǐng)求的 URL 是 http://java.sun.com:
然后這里是服務(wù)器對(duì)這個(gè)請(qǐng)求的回復(fù)消息:
概覽 java.net 包的高層 API java.net 包中含有高層 API。它們實(shí)現(xiàn)了一些最常用的基于 TCP 的協(xié)議,如 HTTP 和 FTP 等。其中兩個(gè)主要的類是 URL 和 URLConnection。另一個(gè)有用的類是 HttpURLConnection,它是 URLConnection 的子類,支持 HTTP 的特性。 URL (Uniform Resource Locator,統(tǒng)一資源定位器) 是一個(gè)描述 Internet 中文檔 (或者其它常見的資源) 位置的地址。URL 的樣子就像這樣: protocol://machineName:port/resource 注意 URL 類不是基于 HTTP 的,這一點(diǎn)非常重要。它支持 FTP、HTTPS 和 FILE 協(xié)議。所以,對(duì)于 URL 類來說,下面所有 URL 都是有效的。 http://java.sun.com http://localhost:8080/myApplication http://www.yahoo.com/index.html http://www.yahoo.com ftp://ftp.borland.com ftp://ftp.sun.com https://www.scotiaonline.scotiabank.com https://central.sun.net file:///C:/j2sdk1.4/docs/api/index.html 你在瀏覽器里輸入一個(gè) URL 的時(shí)候,瀏覽器產(chǎn)生一個(gè) HTTP GET (或者 POST) 命令尋找 (或者查詢) URL 請(qǐng)求的資源。如果沒有指定要查詢的的資源,被查詢的就會(huì)是默認(rèn)文檔 (通常是 index.html)。 讀取 URL 的內(nèi)容 讓我們以一個(gè)簡單的應(yīng)用程序開始,它將會(huì)直接從 URL 讀取內(nèi)容。不妨先嘗試一下使用低層的套接字來讀取,請(qǐng)看示例代碼 1。在這個(gè)例子中,用戶在命令行輸入資源的 URL,然后在 80 端口 (默認(rèn)的 HTTP 服務(wù)器端口號(hào)) 打開一個(gè)套接字并建立相應(yīng)的輸入輸出流。輸出流用來向 HTTP 服務(wù)器發(fā)送 HTTP 命令 (比如 GET),輸入流則用來讀取 HTTP 服務(wù)器的返饋。注意,在這個(gè)例子中,服務(wù)器回應(yīng)的頭信息也會(huì)被讀入 (這是 URL 內(nèi)容之外的東西)。 示例代碼 1: ReadURL1.java
你運(yùn)行這個(gè)例子的時(shí)候請(qǐng)注意,URL 必須是一個(gè)域名如 java.sun.com 或者 IP 地址。不能加上 http:// 作為 URL 的一部分。如果你要解決這個(gè)問題,你就得解析輸入的內(nèi)容并找出它使用什么協(xié)議,端口號(hào)和要請(qǐng)求什么資源。你也可以使用 URL 類,它提供了一些非常有用的方法,如 getProtocal、getPort、getHost 和 getFile 等。 使用 URL 類 要從 URL 讀取內(nèi)容,可以用 URL 類非常容易的實(shí)現(xiàn),就像示例代碼 2 所展示的那樣。這使得直接從 URL 讀取內(nèi)容變得簡單。用這種方法讀取的內(nèi)容不包含服務(wù)器回應(yīng)的頭信息,所以不需要你去解析它們了。運(yùn)行這個(gè)例子時(shí)要輸入有效的 URL ,就像 protocol://domainName:port/resource 這樣。URL 類會(huì)解析輸入的 URL 并處理低層的麻煩的工作。 示例代碼 2:ReadURL2.java
在你運(yùn)行 ReadURL2 的時(shí)候,你會(huì)看到你輸入的 URL 所請(qǐng)求的文檔內(nèi)容命令窗口中顯示出來。 如果你想做除了讀取之外的其它事情,請(qǐng)使用 openConnection 來建立到 URL 的連接。這個(gè)方法返回一個(gè) URLConnection 對(duì)象,你可以用這個(gè)對(duì)象來與 URL 通信,如讀、寫、查詢等。一但 openConnetion 方法創(chuàng)建了連接,你就可以使用 getContentType、getContentLength、getContentEncoding 等非常有用的方法了。 使用 URLConnection 類 我們現(xiàn)在要?jiǎng)?chuàng)建一個(gè)從 http://quote.yahoo.com 獲取股票信息的應(yīng)用程序來演示如何使用 URLConnection。為了獲取特別的股票信息,用戶輸入股票標(biāo)號(hào) (比如 SUNW、IBM 或者 MOT),由應(yīng)用程序從 Yahoo Quote 服務(wù)器獲取相應(yīng)的股票信息。應(yīng)用程序會(huì)顯示出該股票的名稱、價(jià)格和日期。 有兩種方法 (可以用在這個(gè)應(yīng)用程序中的) 用來從 Yahoo Quote 服務(wù)器獲取股票信息。第一種方法的格式如下: http://quote.yahoo.com/d/quotes.csv?s=SUNW&f=slc1wop 如果你在瀏覽器的地址欄輸入這個(gè) URL,你將會(huì)看到像圖 1 所示的那些內(nèi)容。 圖 2: 獲取股票行情的另一種方法 你可以看到第一種方法的結(jié)果是一行文本,解析時(shí)會(huì)比第二種容易許多,也快許多,因?yàn)榈诙N方法的結(jié)果含有大量的文字,包括許多廣告和格式化信息。所以我用第一種方法實(shí)現(xiàn)這個(gè)關(guān)于股票的應(yīng)用程序,它由兩個(gè)類組成:Stock.java 和 StockReader.java。 Stock.java 類 這個(gè)類將從 Yahoo Quote 服務(wù)器獲得的字符串解析成字段 (例如股票名稱、價(jià)格和日期)。示例代碼 3 中展示了一個(gè)實(shí)現(xiàn)的例子。示例代碼 4 中的 StockReader 類會(huì)用到這個(gè)工具類。 示例代碼 3:Stock.java
StockReader.java 類 這個(gè)類的任務(wù)是連接到 Yahoo Quote 服務(wù)器,并從服務(wù)器上獲取股票行情。它使用 Stock 類解析從服務(wù)器返回的字符串。示例代碼 4 是它的一個(gè)實(shí)現(xiàn)。 示例代碼 4:StockReader.java
將數(shù)據(jù)提交到網(wǎng)頁服務(wù)器 在上面的例子中,數(shù)據(jù)是作為 URL 的一部分被送到服務(wù)器的,使用的 GET 方法。現(xiàn)在來看一個(gè)使用 POST 方法發(fā)送數(shù)據(jù)的例子。這個(gè)例子中,http://www.javacourses.com/cgi-bin 中的 CGI 腳本 (名為 .cgi) 需要 name 和 email 值。如果用戶提交 Sally McDonald 作為 name 值,smc@yahoo.com 作為 email 值,CGI 腳本會(huì)獲取輸入并對(duì)消息進(jìn)行解析、解碼,再將提交的內(nèi)容返回給客戶端。這個(gè) CGI 腳本做事情并不多,但我們要用它來演示如何向服務(wù)器提交數(shù)據(jù)。 還有一點(diǎn)非常重要——請(qǐng)注意使用 POST 方法時(shí),消息內(nèi)容的類型是 application/x-www-form-urlencoded,這種類型會(huì): · 指定常規(guī)數(shù)據(jù)編碼 · 將空格轉(zhuǎn)換為加號(hào) (+) · 將非文本內(nèi)容轉(zhuǎn)換成十六進(jìn)制數(shù)后接百分號(hào) (%) 的形式 · 在每個(gè) name=value 對(duì)之間放置 & 符號(hào) 根據(jù)這個(gè)編碼規(guī)則,消息 (name=Sally McDonald and email=smc@yahoo.com) 在發(fā)送給 CGI 腳本之前必須被編碼成: name=Sally+McDonald&email=smc@yahoo.com CGI 腳本收到這個(gè)已編碼的消息后會(huì)對(duì)它進(jìn)行解碼。不過非常幸運(yùn),你不必為手工進(jìn)行編碼操作。你可以使用 java.net.URLEncoder 類來對(duì)消息進(jìn)行編碼,就像下面的例子中那樣。相應(yīng)地你可以使用 java.net.URLDecoder 來對(duì)消息進(jìn)行解碼。 示例代碼 5 中是這個(gè)例子的實(shí)現(xiàn) (使用 HttpURLConnection 類),它展示了如何使用 POST 方法向服務(wù)器發(fā)送數(shù)據(jù)。你會(huì)看到: · 為 CGI 腳本打開連接和 I/O 流 · 設(shè)置請(qǐng)求方法為 POST · 使用 URLEncoder.encode 方法對(duì)消息進(jìn)行編碼 (URLDecoder.decode 方法可以用于解碼) · 向 CGI 腳本發(fā)送已經(jīng)編碼的消息 · 接收服務(wù)器返回的消息并在控制臺(tái)打印出來 示例代碼 5:PostExample.java
代理服務(wù)器和防火墻 如果你使用了防火墻,你就得把代理服務(wù)器以及端口號(hào)的詳細(xì)信息告訴 Java,這樣才能訪問到防火墻外的主機(jī)。你可以通過定義一些 HTTP 或者 FTP 屬性來做到:
http.proxyHost 和 http.proxyPort 用來指定 HTTP 協(xié)議處理器需要使用的代理服務(wù)器和端口號(hào)。http.nonProxyHosts 用來指定哪些主機(jī)是直接連接的 (即不通過代理服務(wù)器來連接)。http.nonProxyHosts 屬性的值是一個(gè)由 | 分隔開的主機(jī)列表,它可以使用正則表達(dá)式來表示所匹配的主機(jī),如:*.sfbay.sun.com 將匹配 sfbay 域中的任何主機(jī)。
ftp.proxyHost 和 ftp.proxyPort 用來指定 FTP 協(xié)議處理器需要使用的代理服務(wù)器和端口號(hào)。ftp.nonProxyHosts 用來指定哪些主機(jī)是直接聯(lián)系的,指定的方法與 http.nonProxyHosts 類似。 你可以在應(yīng)用程序啟動(dòng)的時(shí)候設(shè)置這些屬性: Prompt> java -Dhttp.proxyHost=HostName -Dhttp.proxyPort=PortNumber yourApp HTTP 驗(yàn)證 HTTP 協(xié)議提供驗(yàn)證機(jī)制來保護(hù)資源。當(dāng)一個(gè)請(qǐng)求要求取得受保護(hù)的資源時(shí),網(wǎng)頁服務(wù)器回應(yīng)一個(gè) 401 Unauthorized error 錯(cuò)誤碼。這個(gè)回應(yīng)包含一個(gè)指定了驗(yàn)證方法和領(lǐng)域的 WWW-Authenticate 頭信息。把這個(gè)領(lǐng)域想像成一個(gè)存儲(chǔ)著用戶名和密碼的數(shù)據(jù)庫,它將被用來標(biāo)識(shí)受保護(hù)資源的有效的用戶。比如,你試著去訪問某個(gè)網(wǎng)站上標(biāo)識(shí)為“Personal Files”的資源,服務(wù)器響應(yīng)可能是:WWW-Authenticate: Basic realm="Personal Files" (假設(shè)驗(yàn)證方法是 Basic)。 驗(yàn)證方法 現(xiàn)在有幾種用于網(wǎng)絡(luò)應(yīng)用的驗(yàn)證方法,其中最廣泛使用的是基本驗(yàn)證 (Basic Authentication) 和摘要驗(yàn)證 (Digest Authentication)。 當(dāng)用戶想要訪問有限的資源時(shí),使用基本驗(yàn)證方法的網(wǎng)頁服務(wù)器會(huì)要求瀏覽器詢顯示一個(gè)對(duì)話框,并要求用戶輸入用戶名和密碼。如果用戶輸入的用戶名和密碼正確,服務(wù)器就允許他訪問這些資源;否則,在接連三次嘗試失敗之后,會(huì)顯示一個(gè)錯(cuò)誤消息頁面。這個(gè)方法的缺點(diǎn)是用戶名和密碼都是用 Base64 編碼 (全是可讀文本) 之后傳輸過去的。也就是說,這個(gè)驗(yàn)證方法的安全程度只是和 Telnet 一樣,并不是非常安全。 數(shù)據(jù)驗(yàn)證方法不會(huì)在網(wǎng)絡(luò)中傳輸密碼,而是生成一些數(shù)字 (根據(jù)密碼和其它一些需要的數(shù)據(jù)產(chǎn)生的) 來代替密碼,而這些數(shù)字是經(jīng)過 MD5 (Message Digest Algorithm) 加密的。生成的值在網(wǎng)絡(luò)有隨著服務(wù)器需要用來校難密碼的其它信息一起傳輸。這個(gè)方法明顯更為安全。 基于表單的驗(yàn)證方法和基本驗(yàn)證方法類似,只是服務(wù)器使用你自定義的登錄頁面來代替了標(biāo)準(zhǔn)的登錄對(duì)話框。 最后,客戶證書驗(yàn)證使用 SLL (Secure Socket Layer,安全套接層) 和客戶證明。 在 Tomcat 下保護(hù)資源 你可以在 tomcat-users.xml 文件中寫一個(gè)用戶及其角色的列表。這個(gè)文件在 TOMCAT_HOME (你安裝 Tomcat 的目錄) 下的 conf 目錄中。這個(gè)文件默認(rèn)包含了三個(gè)用戶 (tomcat、role1、both) 的定義。下面一段 XML 代碼是我添加了兩個(gè)新用戶 (qusay 和 reader) 之后的 tomcat-users.xml:
新添加的兩個(gè)用戶 (qusay 和 reader) 的 roles 分別設(shè)置為 author 和 reader。角色屬性非常重要,因?yàn)楫?dāng)你創(chuàng)建安全規(guī)則的時(shí)候,每個(gè)受限制的資源都是與可訪問它的角色相關(guān)聯(lián) (稍后你會(huì)看到)。 下面做個(gè)實(shí)驗(yàn) (假設(shè)你已經(jīng)安裝并配置好了 Tomcat)。為你期望的頁應(yīng)用程序建立一個(gè)目錄。可以按下列步驟做好準(zhǔn)備: 1. 在你安裝了 Tomcat 的目錄下,有一個(gè)目錄是 webapps。在這個(gè)目錄下建立一個(gè)目錄 (如:learn)。 2. 在第一步建立的目錄下建立一個(gè)子目錄,命名為 chapter。 3. 在 chapter 目錄中,建立一個(gè) HTML 文件,內(nèi)容自定,文件名為 index.html。 4. 在第一步建立的目錄下建立一個(gè)名為 WEB-INF 的子目錄。 5. 在 WEB-INF 目錄中創(chuàng)建一個(gè)名為 web.xml 的文件,該文件內(nèi)容如下:
web.xml 配置描述 web.xml 是描述配置的文件,這里集中說明一下安全相關(guān)的配置元素。 <security-constraint>:這個(gè)元素限制對(duì)一個(gè)或者多個(gè)資源的訪問,可以在配置信息中出現(xiàn)多次。上面的配置信息中,它限制了 chapter 目錄 (http://localhost:8080/learn/chapter) 下所有資源的訪問。<security-constraint> 包含了下列元素: o <web-resource-collection>:這個(gè)元素用于標(biāo)識(shí)你想限制訪問的資源。你可以定義 URL 模式 和 HTTP 方法 (用 <http-method> 元素定義 HTTP 方法)。如果沒有定義 HTTP 方法,那么限制將應(yīng)用于所有方法。在上面的應(yīng)用中,我想限制訪問的資源是 http://localhost:8080/learn/chapter/*,也就是 chapter 目錄下的所有文檔。 o <auth-constraint>:這個(gè)元素可以訪問上面定義的受限資源的用戶角色。在上面的應(yīng)用中,tomcat、author 和 erader 這三個(gè)角色可以訪問這些資源。 <login-config>:這個(gè)元素用于指定驗(yàn)證方法。它包含下列元素: o <auth-method>:指定驗(yàn)證方法。它的值可能是下列值集中的一個(gè):BASIC (基本驗(yàn)證)、DIGEST (摘要驗(yàn)證)、FORM (基于表單的驗(yàn)證) 或者 CLIENT-CERT (客戶證書驗(yàn)證)。 o <realm-name>:如果選用 BASIC 方法進(jìn)行驗(yàn)證的時(shí)候,標(biāo)準(zhǔn)登錄對(duì)話框中的一個(gè)描述名稱。 示例 上述配置中使用了 BASIC 驗(yàn)證方法。下面我們做個(gè)實(shí)驗(yàn):啟動(dòng)你的 Tomcat 服務(wù)器并向它發(fā)送到 http://localhost:8080/learn/chapter 的請(qǐng)求。這時(shí)候,就會(huì)有像圖 3 所示那樣的對(duì)話框提示你輸入用戶和密碼: 圖 4:HTTP 摘要驗(yàn)證 (Digest Authentication) 服務(wù)器在幕后的回復(fù) 當(dāng)使用基本驗(yàn)證方法保護(hù)資源的時(shí)候,服務(wù)器發(fā)回類似于圖 5 所示的響應(yīng)信息: 圖 6:服務(wù)器回復(fù) (摘要驗(yàn)證) Java 支持 HTTP 驗(yàn)證 J2SE (1.2 或者更高版本) 通過 Authenticator 類為驗(yàn)證提供了本地支持。你所要做的只是繼承這個(gè)類并實(shí)現(xiàn)它的 getPasswordAuthentication 方法。這個(gè)方法取得用戶名和密碼并用它們生成一個(gè) PasswordAuthentication 對(duì)象返回。完成之后,你還得使用 Authenticator.setDefault 方法注冊(cè)你的 Authenticator 實(shí)例。現(xiàn)在,只要你想訪問受保護(hù)的資源,就會(huì)調(diào)用 getPasswordAuthentication。Authenticator 類管理著所有低層的詳細(xì)資料。它不受 HTTP 的限制,可以應(yīng)用于所有網(wǎng)絡(luò)連接,這不能不說是一個(gè)好消息。 示例代碼 6 中是實(shí)現(xiàn) Authenticator 的一個(gè)示例。正如你所看到的,在請(qǐng)求驗(yàn)證的時(shí)候,getPasswordAuthentication 方法會(huì)彈出一個(gè)登錄對(duì)話框。 示例代碼 6:AuthImpl.java
示例代碼 7 用來做測(cè)試的代碼。我做的第一件事情就是用 Authenticator.setDefault 讓我的 Authenticator 實(shí)例開始運(yùn)行。我不必去解析任何服務(wù)器返回的信息以檢查是否需要驗(yàn)證,因?yàn)?Authenticator 類非常聰明,它知道是否需要驗(yàn)證。 示例代碼 7:BasicReader.java
運(yùn)行下面的命令,用 Tomcat 來進(jìn)行測(cè)試: prompt> java BasicReader http://localhost:8080/learn/chapter 如果你進(jìn)入的站點(diǎn)需要驗(yàn)證 (它也這樣做了),那會(huì)像圖 7 那樣的對(duì)話框就會(huì)顯示出來。
|