目录

1:HttpServletRequest类的常用方法

1.1:HttpServletRequest类有什么用

1.2:HttpServletRequest常用方法

1.3:示例:

2:客户端访问jsp,jsp获取客户端ip

3:客户端访问jsp,jsp请求接口,这个时候接口获取到的就是服务器ip

4:request.getRemoteAddr()获取客户端地址的坑(经过反向代理等转发)

4.1:原因

4.2:解决方法

4.3:提供获取客户端ip地址的工具类


1:HttpServletRequest类的常用方法

1.1:HttpServletRequest类有什么用

每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request 对象中。然后传递到 service 方法(doGet 和 doPost)中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。

1.2:HttpServletRequest常用方法

  • getRequestURI() 获取请求的资源路径
  • getScheme() 返回用以作出请求消息的方案的名称,如 http, https, 或ftp等

  • getServerPort() 返回收到请求的端口号

  • getServerName() 返回收到请求的服务器主机的名字

  • getRemoteHost() 获得客户端的主机名
  • getRemoteAddr()  获得客户端的ip地址
  • getHeader() 获取请求头
  • getParameter() 获取请求的参数
  • getParameterValues() 获取请求的参数(多个值的时候使用)
  • getMethod() 获取请求的方式 GET 或 POST
  • setAttribute(key, value); 设置域数据
  • getAttribute(key); 获取域数据
  • getRequestDispatcher() 获取请求转发对象

1.3:示例:

服务器地址:172.20.10.2,客户端地址:172.20.10.4

 String requestURI = request.getRequestURI();//   /SSO/lDAPLogin.jsp
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  requestURI---"+requestURI);

    String Scheme = request.getScheme();//http
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  Scheme---"+Scheme);

    String contextPath = request.getContextPath();
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  contextPath---"+contextPath);

    int serverPort = request.getServerPort();//8080
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  serverPort---"+serverPort);

    String serverName = request.getServerName();//172.20.10.2
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  serverName---"+serverName);

    String servletPath = request.getServletPath();///SSO/lDAPLogin.jsp
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  servletPath---"+servletPath);

    String pathInfo = request.getPathInfo();
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  pathInfo---"+pathInfo);
    String remoteHost = request.getRemoteHost();//172.20.10.4
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  remoteHost---"+remoteHost);

    String remoteAddr = request.getRemoteAddr();//172.20.10.4
    new BaseBean().writeLog(this.getClass().getName()+"------JspClass : jsp_service_method  remoteAddr---"+remoteAddr);

2:客户端访问jsp,jsp获取客户端ip

服务器地址:172.20.10.2,客户端地址:172.20.10.4,request.getRemoteAddr()获取到地址是172.20.10.4

注:针对前后端分离的项目, request.getRemoteAddr();获取的是客户的真实IP,而非前端IP。因为用户请求前端服务器,前端将HTML和JS代码渲染到本地,本地再去调用服务端。

3:客户端访问jsp,jsp请求接口,这个时候接口获取到的就是服务器ip

服务器地址:172.20.10.2,客户端地址:172.20.10.4,接口中request.getRemoteAddr()获取到地址是172.20.10.2

如果想要

4:request.getRemoteAddr()获取客户端地址的坑(经过反向代理等转发)

4.1:原因

客户端的请求经过服务器Nginx反向代理后,RemoteAddr地址为Nginx的地址。

Nginx反向代理后,Servlet应用通过request.getRemoteAddr()取到的IP是Nginx的IP地址,并非客户端真实的IP,通过request.getRequestURL()获取的域名、协议、端口都是Nginx访问Web应用时域名、协议、端口,而非客户端浏览器地址栏上的真实域名、协议、端口。

这是因为Nginx的反向代理实际上是客户端和真实应用服务器之间的一个桥梁,客户端(一般是浏览器)访问Nginx服务器,Nginx再去访问Web服务器。对于Web应用来说,这次HTTP请求的客户端是Nginx而非真实的客户端浏览器,如果不加特殊处理的话,Web应用会把Nginx当做请求的客户端,获取到的客户端信息就是Nginx的信息。


4.2:解决方法

在配置Nginx反向代理的时候,添加一些请求Header

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
  • Host:包含客户端真实的域名和端口号。
  • X-Forwarded-Proto:表示客户端真实的协议(http还是https)。
  • X-Real-IP:表示客户端真实的IP
  • X-Forwarded-For:这个Header和X-Real-IP类似,但是它在多层代理时会包含真实客户端及中间每个代理服务器的IP。

4.3:提供获取客户端ip地址的工具类

/**
     * 在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。
     * 但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了
     * 经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。
     * 但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息。用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址
     * 如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,
     * 取X-Forwarded-For中第一个非unknown的有效IP字符串。
     *
     * */
public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if ((ip.indexOf(",") >= 0)){
            ip = ip.substring(0 , ip.indexOf(","));
        }
        return ip;
    }

注:如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串ip值,究竟哪个才是真正的用户端的真实IP呢?
答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100,用户真实IP为: 192.168.1.110

5:java中获取当前服务器的Ip地址

public static void main(String[] args) {
      try {
             InetAddress address = InetAddress.getLocalHost();//获取的是本地的IP地址 //PC-20140317PXKX/192.168.0.121
             String hostAddress = address.getHostAddress());//192.168.0.121
             InetAddress address1 = InetAddress.getByName("www.wodexiangce.cn");//获取的是该网站的ip地址,比如我们所有的请求都通过nginx的,所以这里获取到的其实是nginx服务器的IP地
             String hostAddress1 = address1.getHostAddress());//124.237.121.122
             InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");//根据主机名返回其可能的所有InetAddress对象
             for(InetAddress addr:addresses){
             System.out.println(addr);//www.baidu.com/14.215.177.38
             //www.baidu.com/14.215.177.37
           }
        } catch (UnknownHostException e) {
             e.printStackTrace();
      }
 }

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐