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

我正在从事 Spring MVC 控制器项目,在这个项目中,我从浏览器发出了一个 GET URL 调用-

下面是我从浏览器发出 GET 调用的 URL-

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

下面是在浏览器点击之后调用的代码-

@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
}

问题陈述:-

现在有没有办法,我可以提取 IP 地址从一些头?意思是我想知道从哪个 IP 地址,呼叫是来,意思是谁是呼叫以上的网址,我需要知道他们的 IP 地址。这可能吗?

212820 次浏览

解决办法就是

@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
}

HttpServletRequest request添加到方法定义中,然后使用 ServletAPI

Spring 文档 给你

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

我在这里迟到了,但这可能有助于有人寻找答案。通常 servletRequest.getRemoteAddr()工程。

在许多情况下,您的应用程序用户可能通过代理服务器访问您的 Web 服务器,或者您的应用程序位于负载平衡器之后。

因此,在这种情况下,您应该访问 < strong > X- 转发-For http 头,以获得用户的 IP 地址。

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

希望这个能帮上忙。

你可以从 RequestContextHolder静态地得到 IP 地址,如下所示:

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


String ip = request.getRemoteAddr();

下面是 Spring 方式,在 @Controller类中使用 autowired请求 bean:

@Autowired
private HttpServletRequest request;


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

我用这种方法来做这件事

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();
}
}

将此方法放入 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;
}

这段代码适用于 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());

:)

在我的例子中,我在应用程序前使用 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';
}

所以在我的应用程序中,我得到了真正的用户 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();
}

在大多数情况下,我将上面的代码与这个代码结合使用。将从 api 获得的 HttpServletRequest request传递给方法

在我的例子中,我使用这段代码:

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

在我的示例中,request.getRemoteAddr ()包含用户试图从中访问应用程序的系统的 IP 地址。 在这种情况下,如果我在 localhost 或127.0.0.1上运行应用程序,它将返回“0:0:0:0:0:0:0.1”