技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 系统运维 --> 在tomcat应用中获得原始IP

在tomcat应用中获得原始IP

浏览:2055次  出处信息

   Apache/Nginx 通常被放在tomcat前作为http代理。

   browser -> apache -> tomcat

   但是缺点是丢失了很多原有的网络信息:ip、hostname、protocol(用的是http还是 https)

   比如,当java程序想生成http重定向请求的时候会遇到麻烦。因为HTTP头部的Location字段的值必须是绝对URL。重定向的问题勉强可以交给前面的proxy来解决(让apache重写header),但是藏在http body中的各种链接问题就棘手多了。比如当从一个html页面载入一个外部资源时,资源的链接到底是写http的还是https的呢?

   通过修改apache和tomcat的配置,可以让这个问题得到较为完美的解决。

首先是要apache把这些丢失的信息通过http header发到后面去。

   1. Host字段

   HTTP头部的Host字段用来写网站的域名。如果服务器(此处指tomcat)需要支持virtual host,即同一个IP服务多个域名,那么这个字段很重要。

   在配置mod_proxy时加上ProxyPreserveHost,就会让apache往后端转发的时候,Host字段依然填它从browser收到的那个域名。

   2. Apache默认会发送的字段

   默认情况下apache在做http逆向代理时会给后端发送以下字段

   X-Forwarded-For client的IP地址

   X-Forwarded-Host client所请求的域名,即client发来的的http header中Host字段的值。

   X-Forwarded-Server 这台代理服务器(apache)的域名。

   3. 需要添加的

   纵使有了以上信息,我们还是不知道client用的到底是http还是https访问的apache。所以要加下面这行:

   RequestHeader set X-Forwarded-Proto “https” env=HTTPS

   这行代码的意思是,如果当前含有“HTTPS”这个环境变量,那么往后端转发请求时,在头部加上X-Forwarded-Proto字段,值为”https”。

   类似的还可添加其它信息。如HTTPS/SPDY的具体信息,假如前端用的是spdy,那么当前请求不仅具有HTTPS这个环境变量,还有一个名为SPDY_VERSION的环境变量,它的值就是spdy 的版本号。

   RequestHeader set X-SPDY-VERSION “%{SPDY_VERSION}e” env=SPDY_VERSION

   等等。其它需要什么添加什么。如果想知道apache有哪些环境变量,把以下三行保存为php文件放到apache上,然后用浏览器访问一下就知道了。

   <?php

   phpinfo();

   ?>

其次,是让tomcat理解这些额外的header。

   tomcat的Valves,能在收到请求时拦截并修改相应的值。https://tomcat.apache.org/tomcat-7.0-doc/config/valve.html

   其中与我在此讨论的问题相关的是org.apache.catalina.valves.RemoteIpValve。它的主要功能是:

   1. replaces the apparent client remote IP address and hostname for the request with the IP address list presented by a proxy or a load balancer via a request headers (e.g. “X-Forwarded-For”).

   2. replaces the apparent scheme (http/https) and server port with the scheme presented by a proxy or a load balancer via a request header (e.g. “X-Forwarded-Proto”).

   简单点说,就是把下面这行代码添加到tomcat的server.xml中的Engine或Host element下。

   <Valve  className=”org.apache.catalina.valves.RemoteIpValve”    remoteIpHeader=”x-forwarded-for”    proxiesHeader=”x-forwarded-by”    protocolHeader=”x-forwarded-proto”    />

    然后写个servlet测试下,看看对不对:

public class DumpHeaders extends HttpServlet {
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
    response.setContentType("text/plain");
    response.setCharacterEncoding("UTF-8");
    try(java.io.PrintWriter writer=response.getWriter()){
      writer.println("isSecure:"+request.isSecure());
      writer.println("server name:"+request.getServerName());
      writer.println("remote addr:"+request.getRemoteAddr());
      writer.println("headers:");
      java.util.Enumeration<String> names=request.getHeaderNames();
      while(names.hasMoreElements()){
        String headerName=names.nextElement();
        java.util.Enumeration<String> values=request.getHeaders(headerName);
        while(values.hasMoreElements()){
          String headerValue=values.nextElement();
          writer.println(headerName+"\t"+headerValue);
        }
      }
    }
  }
}

   HTTP下:
isSecure:false
server name:www.sunchangming.com
remote addr:60.10.169.130
headers:
host  www.sunchangming.com
accept  text/html, application/xhtml+xml, */*
accept-language  zh-CN
user-agent  Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
accept-encoding  gzip, deflate
cache-control  no-cache
connection  Keep-Alive
x-forwarded-host  www.sunchangming.com
x-forwarded-server  www.sunchangming.com

HTTPS下:
isSecure:true
server name:www.sunchangming.com
remote addr:60.10.169.130
headers:
host  www.sunchangming.com
accept  text/html, application/xhtml+xml, */*
accept-language  zh-CN
user-agent  Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
accept-encoding  gzip, deflate
cache-control  no-cache
x-forwarded-proto  https
connection  Keep-Alive
x-forwarded-host  www.sunchangming.com
x-forwarded-server  www.sunchangming.com

建议继续学习:

  1. tomcat catalina.out日志切割每天生成一个文件    (阅读:8135)
  2. 使用python来抓取新浪的IP数据    (阅读:7436)
  3. 获取指定(访客)IP的所有信息,地址、邮政编码、国家、经纬度等的API    (阅读:5407)
  4. 命令行获取主机外网IP,相当于ip138的功能    (阅读:5048)
  5. 计算机网络协议包头赏析-IP    (阅读:4917)
  6. 当网站使用CDN后获取客户端真实IP的方法    (阅读:4654)
  7. Tomcat 5源码分析    (阅读:4376)
  8. nginx在fastcgi模块中转发真实的后端IP    (阅读:4088)
  9. 获取客户端真实IP方法    (阅读:3897)
  10. Tomcat内存溢出的原因    (阅读:3384)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1