[Java]-RestAPI请求中获取源IP地址

Servlet API中,有一个HttpServletRequest接口(继承自ServletRequest接口),专门用来封装HTTP请求消息。其中定义了获取请求行、请求头和请求消息体的相关方法(对应HTTP请求消息中的:请求行、请求消息头和请求消息体三部分)。

HttpServletRequest接口

访问Servlet时,请求消息的请求行中包含:请求方法、请求资源名、请求路径等信息。

请求行

HttpServletRequest接口中,定义了一系列用于获取请求行的方法:

  • String getMethod():获取HTTP请求消息中的请求方式(如GET、POST等);
  • String getRequestURI():获取请求行中资源名称部分,即位于URL的主机和端口之后、参数部分之前的部分;
  • String getQueryString():获取请求行中的参数部分,也就是资源路径后面问号(?)以后的所有内容;
  • String getProtocol():获取请求行中的协议名和版本(如HTTP/1.0或HTTP/1.1);
  • String getScheme():获取请求的协议名(如http、https或ftp);
  • String getContextPath():获取请求URL中属于WEB应用程序的路径,这个路径以“/”开头,表示相对于整个WEB站点的根目录,路径结尾不含“/”;
  • String getServletPath():获取Servlet所映射的路径(url-pattern);

消息头

HttpServletRequest接口中,定义了一系列用于获取HTTP请求头字段的方法:

  • String getHeader(String name):获取一个指定头字段的值,如果请求消息中没有包含指定的头字段,getHeader()方法返回null;如果请求消息中包含有多个指定名称的头字段,getHeader()方法返回其中第一个头字段的值;
  • Enumeration getHeaders(String name):返回一个Enumeration集合对象,该集合对象由请求消息中出现的某个指定名称的所有头字段值组成;
  • Enumeration getHeaderNames():获取一个包含所有请求头字段的Enumeration对象
  • int getIntHeader(String name):获取指定名称的头字段,并且将其值转为int类型(如果指定名称的头字段不存在,返回值为-1;如果获取到的头字段的值不能转为int类型,将发生NumberFormatException异常);
  • Long getDateHeader(String name):获取指定头字段的值,并将其按GMT时间格式转换成UNIX时间戳(毫秒数);

请求参数

HttpServletRequest接口中,定义了一系列获取请求参数的方法:

  • String getParameter(String name):获取某个指定名称的参数值,如果请求消息中没有包含指定名称的参数,getParameter()方法返回null;
  • String[] getParameterValues(String name):获得同一个参数名所对应的所有参数值;
  • Enumeration getParameterNames():获得请求消息中所有参数名的Enumeration对象
  • Map getParameterMap():获得参数名和值的Map对象;

请求源地址

通过HttpServletRequest,可以获取请求源的IP地址,方便调试与记录。

获取源地址

客户端的一个请求,在到达服务端前,可能会经过多次转发(包括Ngix等),我们只能尽快能尝试获取请求来源:

public static String getRequestIP(HttpServletRequest request) {
    final String UnknownIP = "unknown";
    final String LoopbackIP = "127.0.0.1";

    String strAddr = null;
    try {
        strAddr = request.getHeader("x-forwarded-for");
        if (strAddr == null || strAddr.length() == 0 || UnknownIP.equalsIgnoreCase(strAddr)) {
            strAddr = request.getHeader("Proxy-Client-IP");
        }
        if (strAddr == null || strAddr.length() == 0 || UnknownIP.equalsIgnoreCase(strAddr)) {
            strAddr = request.getHeader("WL-Proxy-Client-IP");
        }
        if (strAddr == null || strAddr.length() == 0 || UnknownIP.equalsIgnoreCase(strAddr)) {
            strAddr = request.getRemoteAddr();
            if (LoopbackIP.equals(strAddr)) {
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                strAddr = inet.getHostAddress();
            }
        }
        // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
        if (strAddr != null && strAddr.length() > 15) { // "***.***.***.***".length()
            if (strAddr.indexOf(",") > 0) {
                strAddr = strAddr.substring(0, strAddr.indexOf(","));
            }
        }
    } catch (Exception e) {
        strAddr = "";
    }

    return strAddr;
}

RestAPI接口调用

默认情况下,swagger-RestAPI接口中只列出请求相关的参数:

@RestController
@RequestMapping("test")
public class TestController {

   @PostMapping("testPostData")
   ResponseResult testPostData(String name, @RequestBody String request){
   }
}

通过@RequestBody修饰的参数会放在body中传递,其他参数放在Header中。

为了获取请求相关数据,需要在参数中增加HttpServletRequest(其他参数不变,客户端请求调用也无任何影响):

@PostMapping("testPostData")
ResponseResult testPostData(HttpServletRequest servlet, String name, @RequestBody String request){
 String strIP = getRequestIP(servlet);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值