Java 如何在Spring MVC控制器get call中提取IP地址?
我正在从事SpringMVC控制器项目,在该项目中,我正在从浏览器中进行一个GET URL调用-Java 如何在Spring MVC控制器get call中提取IP地址?,java,spring-mvc,ip-address,Java,Spring Mvc,Ip Address,我正在从事SpringMVC控制器项目,在该项目中,我正在从浏览器中进行一个GET URL调用- http://127.0.0.1:8080/testweb/processing?workflow=test&conf=20140324&dc=all 下面是我从浏览器拨打GET电话的url- http://127.0.0.1:8080/testweb/processing?workflow=test&conf=20140324&dc=all 下面是点击浏览器后调
http://127.0.0.1:8080/testweb/processing?workflow=test&conf=20140324&dc=all
下面是我从浏览器拨打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地址,这意味着无论谁在URL上方呼叫,我都需要知道他们的IP地址。这可能吗?解决方案是
@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
添加到方法定义中,然后使用Servlet API
Spring文档在
15.3.2.3支持的处理程序方法参数和返回类型
我来晚了,但这可能有助于寻找答案。通常
servletRequest.getRemoteAddr()
可以正常工作
在许多情况下,您的应用程序用户可能通过代理服务器访问您的web服务器,或者您的应用程序位于负载平衡器后面
因此,在这种情况下,您应该访问http头以获取用户的IP地址
e、 g.String ipAddress=request.getHeader(“X-FORWARDED-FOR”)代码>
希望这能有所帮助。您可以从RequestContextHolder
静态获取IP地址,如下所示:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.getRequest();
String ip = request.getRemoteAddr();
下面是Spring方式,在@Controller
类中使用自动连线的请求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+ApacheCxf/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");
我将上面的代码与此代码结合起来,在大多数情况下都能工作。将从api获得的HttpServletRequest请求
传递给方法,感谢Koitoer的帮助。一个简单的问题,假设调用来自负载平衡器而不是特定的机器,那么这也可以工作吗?我想不是…不,但是,在负载均衡器中有一些配置可以发送IP,因为它们不存在,可能这是你的CaseChIP,可能负载均衡器可以在头文件中发送这些值,所以考虑使用HeTpServestRevest.GoeTead方法。但是除了HttpServletRequest还有其他方法。这是不推荐的。请注意,X-Forwarded-For
通常是一个以逗号分隔的IP列表,链中的每个代理都会将它看到的远程地址添加到列表中。因此,一个好的实现通常会有一个可信代理列表,并在从右到左读取此标头时“跳过”这些ip。如何将ip地址获取为111.111.111.111/X请注意,例如,Tomcat有RemoteIpValve
,它解析X-Forwarded-For
标头并将其设置在HttpServletRequest
上,因此,servletRequest.getRemoteAddr()
返回正确的最终用户IP地址。在Spring Boot中,可以通过server.tomcat.remote ip header=X-Forwarded-For
应用程序属性启用它。这可能会导致多线程并发使用控制器时出现问题。只能使用@Autowired
将单例注入@Controller
实例。否则,您必须在控制器类上使用@Scope(BeanDefinition.Scope\u PROTOTYPE)
,以确保每个请求都生成控制器的新实例。这效率较低,但如果必须将某些内容作为属性注入控制器类,则这是一种变通方法。请尝试使用Spring AOP并处理HttpServletRequest。我在哪里使用它?
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();
}