J2EE架构中获取客户端IP的方法与实践作者:张劲松作者简介张劲松,男,云电清华同方科技有限公司JAVA软件工程师,曾参与了多个大中型软件项目开发,一直使用并极力支持J2EE架构下的项目开发,对J2EE架构下项目开发中的诸多技术细节和各种开发模式均有较为丰富的实践和心得,个人拥有SCJP认证,您可以通过[email protected]与他联系。正文我们在开发的项目中服务器端常常需要获取前来访问的客户端的一些信息与资源,其中获取客户端的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的源码中做些改动即可。)
希望有启发!

解决方案 »

  1.   

    谢谢楼上的,可能是我没表达清楚我的需求~keytool -genkey -keystore myip.keystore -alias myip
    keytool -export -keystore myip.keystore -alias myip -file myip.cer
    这两步是必然要做的,但是我需要的不是在applet上通过IE加载的证书~我想应该有一个这样的证书类去做该类工作吧,望有人指教一,二
      

  2.   

    给我一个EMAIL,,我把实例发给你,但是要快点给分呀,我专家分,,不知道为什么少了200多分
      

  3.   

    [email protected]加我MSN