Java中從HTTP請求獲取客戶端信息
1. 概述
Web應用程式主要工作在請求-回應模型上,該模型描述了用戶端和Web伺服器之間使用HTTP協定進行資料交換。在接受或拒絕請求的伺服器端,了解發出該請求的客戶端非常重要。
在本教程中,我們將學習如何從 HTTP 請求中擷取客戶端資訊。
2.HTTP請求對象
在學習HTTP請求之前,我們首先應該了解Servlet
。 Servlet
是 Java 實作的基本部分,用於擴展 Web 開發的能力,以便處理 HTTP 請求並在回應中產生動態內容。
HttpServletRequest
是 Java Servlet API 中的一個接口,表示客戶端發出的 HTTP 請求。 HttpServletRequest
物件在擷取有關客戶端的重要資訊方面非常方便。 HttpServletRequest 提供開箱即用的方法,例如getRemoteAddr()
、 getRemoteHost()
、 getHeader(), and getRemoteUser()
,這些方法有助於擷取客戶端資訊。
2.1.取得客戶端IP位址
我們可以使用getRemoteAddr()
方法來取得客戶端的 IP 位址:
String remoteAddr = request.getRemoteAddr(); // 198.167.0.1
需要注意的是,此方法會擷取伺服器所看到的 IP 位址,由於代理伺服器、負載平衡器等因素,可能不會總是代表真實的用戶端 IP 位址。
2.2.取得遠端主機
我們可以使用getRemoteHost()
方法來取得客戶端的主機名稱:
String remoteHost = request.getRemoteHost(); // baeldung.com
2.3.取得遠端用戶
如果經過身份驗證,我們可以使用getRemoteUser()
方法來取得客戶端使用者名稱:
String remoteUser = request.getRemoteUser(); // baeldung
值得注意的是,如果客戶端未經過身份驗證,那麼我們可能會得到null
。
2.4.取得客戶端標頭
我們可以使用getHeader(headerName)
方法來讀取客戶端傳遞的標頭值:
String contentType = request.getHeader("content-type"); // application/json
取得客戶端資訊的重要標頭之一是User-Agent
標頭。它包括客戶端的軟體、系統等資訊。一些重要資訊可能包括瀏覽器、作業系統、裝置資訊、插件、附加元件等。
以下是User-Agent
字串的範例:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
我們可以使用 HttpServletRequest 提供的getHeader(String headerName)
方法來讀取User-Agent
標頭HttpServletRequest.
由於其動態特性,解析User-Agent
字串本質上可能很複雜。但是,有不同程式語言的程式庫可以簡化此任務。對於 Java 生態系統, [uap-java](https://github.com/ua-parser/uap-java)
是一個流行的選擇。
除了上述方法之外,還有其他方法,例如getSessionID()
、 getMethod()
、 getRequestURL()
等,根據用例可能會有所幫助。
3. 擷取客戶資訊
如上一節所討論的,為了解析User-Agent
,我們可以使用[uap-java](https://mvnrepository.com/artifact/com.github.ua-parser/uap-java)
函式庫。為此,我們需要在pom.xml
檔案中加入以下 XML 片段:
<dependency>
<groupId>com.github.ua-parser</groupId>
<artifactId>uap-java</artifactId>
<version>1.5.4</version>
</dependency>
配置完依賴項後,讓我們建立一個簡單的AccountServlet,
它充當客戶端的 HTTP 端點並接受請求:
@WebServlet(name = "AccountServlet", urlPatterns = "/account")
public class AccountServlet extends HttpServlet {
public static final Logger log = LoggerFactory.getLogger(AccountServlet.class);
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
AccountLogic accountLogic = new AccountLogic();
Map<String, String> clientInfo = accountLogic.getClientInfo(request);
log.info("Request client info: {}, " + clientInfo);
response.setStatus(HttpServletResponse.SC_OK);
}
}
然後,我們可以將請求物件傳遞給AccountLogic,
後者從使用者請求中提取客戶端資訊。然後,我們可以建立一個AccountLogic
類,主要包含獲取客戶資訊的所有邏輯。我們可以使用之前討論過的所有常見輔助方法:
public class AccountLogic {
public Map<String, String> getClientInfo(HttpServletRequest request) {
String remoteAddr = request.getRemoteAddr();
String remoteHost = request.getRemoteHost();
String remoteUser = request.getRemoteUser();
String contentType = request.getHeader("content-type");
String userAgent = request.getHeader("user-agent");
Parser uaParser = new Parser();
Client client = uaParser.parse(userAgent);
Map<String, String> clientInfo = new HashMap<>();
clientInfo.put("os_family", client.os.family);
clientInfo.put("device_family", client.device.family);
clientInfo.put("userAgent_family", client.userAgent.family);
clientInfo.put("remote_address", remoteAddr);
clientInfo.put("remote_host", remoteHost);
clientInfo.put("remote_user", remoteUser);
clientInfo.put("content_type", contentType);
return clientInfo;
}
}
最後,我們準備好寫一個簡單的單元測試來驗證功能:
@Test
void givenMockHttpServletRequestWithHeaders_whenGetClientInfo_thenReturnsUserAGentInfo() {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
when(request.getHeader("user-agent")).thenReturn("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36, acceptLanguage:en-US,en;q=0.9");
when(request.getHeader("content-type")).thenReturn("application/json");
when(request.getRemoteAddr()).thenReturn("198.167.0.1");
when(request.getRemoteHost()).thenReturn("baeldung.com");
when(request.getRemoteUser()).thenReturn("baeldung");
AccountLogic accountLogic = new AccountLogic();
Map<String, String> clientInfo = accountLogic.getClientInfo(request);
assertThat(clientInfo.get("os_family")).isEqualTo("Mac OS X");
assertThat(clientInfo.get("device_family")).isEqualTo("Mac");
assertThat(clientInfo.get("userAgent_family")).isEqualTo("Chrome");
assertThat(clientInfo.get("content_type")).isEqualTo("application/json");
assertThat(clientInfo.get("remote_user")).isEqualTo("baeldung");
assertThat(clientInfo.get("remote_address")).isEqualTo("198.167.0.1");
assertThat(clientInfo.get("remote_host")).isEqualTo("baeldung.com");
}
4。結論
在本文中,我們了解了HttpServletRequest
對象,它提供了有用的方法來捕獲有關請求客戶端的信息。我們也了解了User-Agent
標頭,它為客戶端提供系統級訊息,例如瀏覽器系列、作業系統系列等。
後來我們也實作了從請求物件中捕獲客戶端資訊的邏輯。
與往常一樣,範例程式碼可以在 GitHub 上取得。