獲取客戶端IP

我們在開發的項目中服務器端常常需要獲取前來訪問的客戶端的一些信息與資源,其中獲取客戶端的IP地址是最常用的。


在JAVA裏HttpServletRequest接口提供了getRemoteAddr()方法來獲取客戶端IP地址(其實是繼承自ServletRequest接口的),使用很簡單,方法如下:


假設已有HttpServletRequest對象request(Jsp中默認)

String ipaddress = request.getRemoteAddr();

但是這一方法有致命缺陷,就是不能穿透代理服務器。當系統架構中使用了代理服務器時,上述方法抓到的就是代理服務器的IP地址。在大中型J2EE架構的項目開發中,Java應用服務器常常需要使用集羣與代理,故而上述方法便不可行了。筆者曾歷查J2EE技術有關資料,未能發現可以一箭貫透代理服務器的直接可用的IP抓取方法。但J2EE是強大的,解決之道當然是不缺的,這裏介紹一下我們的解決方法--使用帶數字簽名的Applet。

我們知道Applet是下載到客戶端,在客戶端的JVM上運行的,當Applet運行不涉及客戶端的本地資源時使用Applet是個小Case(許多股票網站裏動態顯示交易曲線的技術就是這一招),但當要獲取本地資源信息(即便只是抓個IP地址)時,就一定要對APPLET進行數字簽名和認證(詳情參見有關Java安全機制)。

帶數字簽名和認證的APPLET開發過程如下:


(1)開發APPLET的Java源程序並對其進行編譯。

抓取本機(即客戶機)IP的APPLET代碼如下:
import java.applet.*;
import java.net.*;
import java.awt.*;

public class getipapp extends Applet
{
public String myip()
{

String ipd="";
try{
//使用抓取本機Ip的方法getLocalHost(),返回一個InetAddress對象
InetAddress addr=InetAddress.getLocalHost();

//從InetAddress對象中取出數據放到byte類型的數組中
byte[] ipAddr=addr.getAddress();
int i=0;
int ipget=0;
//組裝String類型的IP地址
while(i<ipAddr.length){
ipget=ipAddr[i];
//對返回的數值進行轉換整理
if(ipget<0){ipget=256+ipget;}
if(i==0){
ipd=ipd+ipget;
}else{
ipd=ipd+"."+ipget;
}
i++;
}
}catch(UnknownHostException e){
}
return ipd;
}

public getipapp()
{
}

//Initialize the applet
public void start()
{
}
}

(2)用JAR工具對類文件和資源文件進行封裝。

  當前目錄下:
jar cvf myip.jar *.class

(3)用keytool創建公鑰和密鑰,生成X。509V1簽名證書,輸出證書。

  當前目錄下:
keytool -genkey -keystore myip.keystore -alias myip

說明:keystore將用來存放密匙(private keys)和公共鑰匙的認證,此命令生成了一個名爲myip.keystore的keystore文件,接着這條命令,系統會接着有提示的要求填寫若干內容,比如創建人、公司名稱、地址、設定的密碼等等,隨便填寫後完成。


(4)將公共鑰匙導入到安全證書cer文件中。

當前目錄下:
keytool -export -keystore myip.keystore -alias myip -file myip.cer

說明:此命令生成一個名爲myip.cer的安全證書文件(這也是客戶端運行訪問本地資源的applet時需要的文件),使用命令當中會提示你輸入密碼,輸入先前設定的密碼即可。


至此,一個帶數字簽名和認證的APPLET開發完成。此APPLET運行時一旦通過客戶端的許可驗證(詳情下述),便能抓取到客戶機的IP地址,然後是將此地址傳遞到服務器上。我們在實踐中使用javascript腳本直接與applet通訊,將抓取到的IP地址存放到頁面元素中,然後通過表單將IP地址提交到服務器,方法如下。


(5)WEB(一般是登錄頁)獲取applet參數的設置方法:

在<body>與</body>之間加入:
<applet code="getipapp.class" codebase = "" archive = "myip.jar"
width="0" height="0" name="getipapp">
</applet>
和<input type="hidden" name="iptxt">(這是網頁中用來存放applet參數的頁面元素)

很重要:

在<head>與</head>之間加入:
<SCRIPT LANGUAGE=javascript>
function getmyip()
{
//假設<input type="hidden" name="iptxt">元素在form1表單中
window.document.form1.iptxt.value=window.document.getipapp.myip();
}
</ SCRIPT >

說明:利用javascript中將applet視爲頁面元素並提供簡單通訊的方法直接從頁面上取得applet獲取的客戶端IP地址,並通過表單提交給服務器(方法略)。


現在,客戶端需要做的就是安裝jre虛擬機(建議1.4.1以上版本),在Windows系統中成功安裝後在控制面板中會看見一個"Java Plug-in"圖標,打開該程序後在"瀏覽器"中確認將系統使用的瀏覽器鉤上(IE或NetScape)。重啓瀏覽器,訪問服務器上裝有applet的網頁,此時會自動彈出安全證書的驗證信息,當確認該證書可行後,帶有該證書的applet就可以在你的機器上爲所欲爲了(呵呵,也沒幹什麼,就打聽了一下你機器上的IP地址),同時在"Java Plug-in"的"證書→帶簽名的小程序"中會自動導入你所簽發的安全證書。


說了這麼多,其實主要介紹了穿透代理服務器獲取客戶端IP的applet的一個完整方案。相信在J2EE架構下解決方法還很多,希望大家多多交流。(另外,這個方案中只獲取了本機的主IP,若要取到本機的所有IP則在applet的源碼中做些改動即可。)

 
發佈了83 篇原創文章 · 獲贊 0 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章