简体   繁体   English

如何在 Spring MVC 控制器获取调用中提取 IP 地址?

[英]How to extract IP Address in Spring MVC Controller get call?

I am working on Spring MVC controller project in which I am making a GET URL call from the browser -我正在从事 Spring MVC 控制器项目,在该项目中我正在从浏览器进行 GET URL 调用 -

Below is the url by which I am making a GET call from the browser -下面是我从浏览器进行 GET 调用的 url -

http://127.0.0.1:8080/testweb/processing?workflow=test&conf=20140324&dc=all

And below is the code in which the call comes after hitting at the browser -下面是点击浏览器后调用的代码 -

@RequestMapping(value = "processing", method = RequestMethod.GET)
public @ResponseBody ProcessResponse processData(@RequestParam("workflow") final String workflow,
    @RequestParam("conf") final String value, @RequestParam("dc") final String dc) {

        System.out.println(workflow);
        System.out.println(value);
        System.out.println(dc);

        // some other code
    }

Problem Statement:-问题陈述:-

Now is there any way, I can extract IP Address from some header?现在有什么办法,我可以从一些标头中提取 IP 地址吗? Meaning I would like to know from which IP Address, call is coming, meaning whoever is calling above URL, I need to know their IP Address.意思是我想知道来自哪个 IP 地址的呼叫来了,这意味着无论是谁在上面的 URL 上呼叫,我都需要知道他们的 IP 地址。 Is this possible to do?这可能吗?

The solution is解决办法是

@RequestMapping(value = "processing", method = RequestMethod.GET)
public @ResponseBody ProcessResponse processData(@RequestParam("workflow") final String workflow,
    @RequestParam("conf") final String value, @RequestParam("dc") final String dc, HttpServletRequest request) {

        System.out.println(workflow);
        System.out.println(value);
        System.out.println(dc);
        System.out.println(request.getRemoteAddr());
        // some other code
    }

Add HttpServletRequest request to your method definition and then use the Servlet APIHttpServletRequest request添加到您的方法定义中,然后使用 Servlet API

Spring Documentation here said in Spring文档在这里

15.3.2.3 Supported handler method arguments and return types 15.3.2.3 支持的处理程序方法参数和返回类型

Handler methods that are annotated with @RequestMapping can have very flexible signatures.
Most of them can be used in arbitrary order (see below for more details).

Request or response objects (Servlet API). Choose any specific request or response type,
for example ServletRequest or HttpServletRequest

I am late here, but this might help someone looking for the answer.我来晚了,但这可能有助于寻找答案的人。 Typically servletRequest.getRemoteAddr() works.通常servletRequest.getRemoteAddr()工作。

In many cases your application users might be accessing your web server via a proxy server or maybe your application is behind a load balancer.在许多情况下,您的应用程序用户可能通过代理服务器访问您的 Web 服务器,或者您的应用程序可能位于负载均衡器之后。

So you should access the X-Forwarded-For http header in such a case to get the user's IP address.因此,在这种情况下,您应该访问X-Forwarded-For http 标头以获取用户的 IP 地址。

eg String ipAddress = request.getHeader("X-FORWARDED-FOR");例如String ipAddress = request.getHeader("X-FORWARDED-FOR");

Hope this helps.希望这可以帮助。

I use such method to do this我使用这种方法来做到这一点

public class HttpReqRespUtils {

    private static final String[] IP_HEADER_CANDIDATES = {
        "X-Forwarded-For",
        "Proxy-Client-IP",
        "WL-Proxy-Client-IP",
        "HTTP_X_FORWARDED_FOR",
        "HTTP_X_FORWARDED",
        "HTTP_X_CLUSTER_CLIENT_IP",
        "HTTP_CLIENT_IP",
        "HTTP_FORWARDED_FOR",
        "HTTP_FORWARDED",
        "HTTP_VIA",
        "REMOTE_ADDR"
    };

    public static String getClientIpAddressIfServletRequestExist() {

        if (RequestContextHolder.getRequestAttributes() == null) {
            return "0.0.0.0";
        }

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        for (String header: IP_HEADER_CANDIDATES) {
            String ipList = request.getHeader(header);
            if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
                String ip = ipList.split(",")[0];
                return ip;
            }
        }

        return request.getRemoteAddr();
    }
}

You can get the IP address statically from the RequestContextHolder as below :您可以从RequestContextHolder静态获取 IP 地址,如下所示:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
        .getRequest();

String ip = request.getRemoteAddr();

Below is the Spring way, with autowired request bean in @Controller class:下面是 Spring 方式,在@Controller类中使用autowired请求 bean:

@Autowired 
private HttpServletRequest request;

System.out.println(request.getRemoteHost());

Put this method in your BaseController:将此方法放在您的 BaseController 中:

@SuppressWarnings("ConstantConditions")
protected String fetchClientIpAddr() {
    HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.getRequestAttributes())).getRequest();
    String ip = Optional.ofNullable(request.getHeader("X-FORWARDED-FOR")).orElse(request.getRemoteAddr());
    if (ip.equals("0:0:0:0:0:0:0:1")) ip = "127.0.0.1";
    Assert.isTrue(ip.chars().filter($ -> $ == '.').count() == 3, "Illegal IP: " + ip);
    return ip;
}

See below.见下文。 This code works with spring-boot and spring-boot + apache CXF/SOAP.此代码适用于 spring-boot 和 spring-boot + apache CXF/SOAP。

    // in your class RequestUtil
    private static final String[] IP_HEADER_NAMES = { 
                                                        "X-Forwarded-For",
                                                        "Proxy-Client-IP",
                                                        "WL-Proxy-Client-IP",
                                                        "HTTP_X_FORWARDED_FOR",
                                                        "HTTP_X_FORWARDED",
                                                        "HTTP_X_CLUSTER_CLIENT_IP",
                                                        "HTTP_CLIENT_IP",
                                                        "HTTP_FORWARDED_FOR",
                                                        "HTTP_FORWARDED",
                                                        "HTTP_VIA",
                                                        "REMOTE_ADDR"
                                                    };

    public static String getRemoteIP(RequestAttributes requestAttributes)
    {
        if (requestAttributes == null)
        {
            return "0.0.0.0";
        }
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        String ip = Arrays.asList(IP_HEADER_NAMES)
            .stream()
            .map(request::getHeader)
            .filter(h -> h != null && h.length() != 0 && !"unknown".equalsIgnoreCase(h))
            .map(h -> h.split(",")[0])
            .reduce("", (h1, h2) -> h1 + ":" + h2);
        return ip + request.getRemoteAddr();
    }

    //... in service class:
    String remoteAddress = RequestUtil.getRemoteIP(RequestContextHolder.currentRequestAttributes());

:) :)

In my case, I was using Nginx in front of my application with the following configuration:就我而言,我在我的应用程序前面使用了 Nginx,配置如下:

location / {
     proxy_pass        http://localhost:8080/;
     proxy_set_header  X-Real-IP $remote_addr;
     proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header  Host $http_host;
     add_header Content-Security-Policy 'upgrade-insecure-requests';
}

so in my application I get the real user ip like so:所以在我的应用程序中,我得到了真正的用户 ip,如下所示:

String clientIP = request.getHeader("X-Real-IP");
private static final String[] IP_HEADER_CANDIDATES = {
            "X-Forwarded-For",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR"
    };

    public static String getIPFromRequest(HttpServletRequest request) {
        String ip = null;
        if (request == null) {
            if (RequestContextHolder.getRequestAttributes() == null) {
                return null;
            }
            request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        }

        try {
            ip = InetAddress.getLocalHost().getHostAddress();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!StringUtils.isEmpty(ip))
            return ip;

        for (String header : IP_HEADER_CANDIDATES) {
            String ipList = request.getHeader(header);
            if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
                return ipList.split(",")[0];
            }
        }

        return request.getRemoteAddr();
    }

I combie the code above to this code work for most case.对于大多数情况,我将上面的代码与此代码结合使用。 Pass the HttpServletRequest request you get from the api to the method将你从 api 获取的HttpServletRequest request传递给方法

In my case, I am using this piece of code:就我而言,我正在使用这段代码:

private String getRemoteAddr(HttpServletRequest req) {
    if (!StringUtils.isEmpty(req.getHeader("X-Real-IP"))) {
        return req.getHeader("X-Real-IP");
    }
    return req.getRemoteAddr();
}

In my case request.getRemoteAddr() contains the IP address of system from which user is trying to access the application.在我的例子中,request.getRemoteAddr() 包含用户尝试访问应用程序的系统的 IP 地址。 and in case, if I am running my application on localhost or 127.0.0.1 it is returning "0:0:0:0:0:0:0:1"以防万一,如果我在本地主机或 127.0.0.1 上运行我的应用程序,它会返回“0:0:0:0:0:0:0:1”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM