为什么带有IPv6地址的HttpServletRequest.getRemoteAddr()会返回额外的字符

时间:2015-10-16 10:56:32

标签: java tomcat servlets ipv6

在我的Tomcat托管的Web应用程序中,doGet(...)方法中的前两行是:

String ip = request.getRemoteAddr();
System.out.println("ip = " + ip);

在我们的本地网络上使用IPv6地址,它输出:

ip = fe80:0:0:0:ac40:98cb:ca2e:c03c%4

最后的%4似乎无关紧要。它导致我们的地理定位服务请求失败。这个%4应该在那里吗?如果是这样,它意味着什么?有没有可靠的方法从没有%4的HttpServletRequest实例获取IPv6地址?

1 个答案:

答案 0 :(得分:4)

它是scope ID。使用原生API,在java.net.InetAddressInet6Address#getScopeId()的帮助下摆脱它的最佳选择如下:

String ip = request.getRemoteAddr();
InetAddress inetAddress = InetAddress.getByName(ip);

if (inetAddress instanceof Inet6Address) {
    Inet6Address inet6Address = (Inet6Address) inetAddress;
    int scopeId = inet6Address.getScopeId();

    if (scopeId > 0) {
        ip = inet6Address.getHostName().replaceAll("%" + scopeId + "$", "");
    }
}

这种笨拙是因为标准的java.net.Inet6Address API没有任何方法可以返回没有作用域ID的裸主机名。

另一方面,我不知道有问题的地理定位服务是否应该考虑到这一点。如果甚至没有在其API文档中明确排除对IPv6范围的支持,那么我将在其问题跟踪器中提交问题。