Gibt es eine Möglichkeit, die ursprüngliche IP-Adresse des Clients zu erhalten, der zum Server kommt? Ich kann request.getRemoteAddr()
verwenden, aber ich scheine immer die IP des Proxy oder des Webservers zu erhalten.
Ich möchte die IP-Adresse erfahren, die der Client für die Verbindung zu mir verwendet. Gibt es überhaupt, dass ich es bekommen könnte?
versuche dies:
public static String getClientIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
request.getRemoteAddr()
ist der Weg. Es scheint, dass Ihr Proxy die Quell-IP ändert. Wenn einige Stellvertreter dies tun, fügen sie die ursprüngliche IP-Adresse in einem benutzerdefinierten http-Header hinzu. Verwenden Sie request.getHeaderNames()
und request.getHeaders(name)
und drucken Sie alle, um zu sehen, ob nichts Interessantes vorliegt. Wie X-CLIENT-IP
(hat das gemacht, aber sie sehen so aus)
Die beste Lösung, die ich je benutzt habe
public String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
Sie können dies nicht sinnvoll tun.
Der Proxy kann einen Proxied-for-Header hinzufügen oder auch nicht. In vielen Fällen handelt es sich jedoch um eine interne Adresse, die für Sie sinnlos ist. Die meisten Proxies am Rand einer Organisation sind so konfiguriert, dass sie ohnehin so wenig wie möglich über die internen Komponenten des Netzwerks informieren.
Wofür wollen Sie diese Informationen verwenden?
Da dies in der Regel eher ein Bereitstellungsproblem als ein Anwendungsproblem ist, besteht ein anderer Ansatz darin, den Anwendungscontainer entsprechend zu konfigurieren. Nach der Konfiguration überprüft der Container den entsprechenden Header und Ihre Anwendung verwendet weiterhin request.getRemoteAddr()
.
In Tomcat können Sie beispielsweise das Remote-IP-Ventil verwenden. Ich würde davon ausgehen, dass die meisten Anwendungsserver eine ähnliche Funktionalität haben.
Der Container kann auch für das Verständnis sorgen, wenn Ihr Front-End-Lastausgleicher SSL-Verbindungen beendet und die Anforderung über HTTP an den App-Server weiterleitet. Dies ist wichtig, wenn Ihre Anwendung URLs für sich selbst erstellen muss.
Der Header "x-forwarded-for" enthält die ursprüngliche Client-IP, wenn ein Proxy oder ein Lastausgleich verwendet wird. Aber ich denke, nicht alle Proxies/lb fügen diesen Header hinzu.
Hier ein bisschen Java-Code, um den Header zu analysieren: http://www.codereye.com/2010/01/get-real-ip-from-request-in-Java.html
Wenn dieser Header nicht vorhanden ist, würde ich wie @Bozho vorgehen
Warum nicht eine elegantere Lösung wie diese verwenden?
private static final List<String> IP_HEADERS = Arrays.asList("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");
public static String getClientIpAddr(HttpServletRequest request) {
for (String ipHeader : IP_HEADERS) {
String ip = request.getHeader(ipHeader);
if (ip != null && !ip.isEmpty() && !ip.equalsIgnoreCase("unknown")) {
return ip;
}
}
return request.getRemoteAddr();
}
Deduplizieren Sie Ihren Code!
Warum sollten wir meiner Meinung nach zuerst versuchen, die IP-Adresse aus dem Header 'X-Forwarded-For
' abzurufen? Wenn Sie von request.getRemoteAddr()
erhalten, kann es sich um die echte IP des Clients oder die IP des letzten Proxys handeln, die die Anforderung weiterleitet . Wir können also nicht sagen, zu welchem Zustand es gehört. Wenn jedoch 'X-Forwarded-For
' in den Header gesetzt ist, ist die Client-IP der am weitesten links stehende Teil dessen, was Sie daraus erhalten.
/**
* Try to get real ip from request:
* <ul>
* <li>try X-Forwarded-For</li>
* <li>try remote address</li>
* </ul>
*
* @param request request
* @return real ip or ""
*/
private String tryGetRealIp(HttpServletRequest request) {
// X-Forwarded-For: <client>, <proxy1>, <proxy2>
// If a request goes through multiple proxies, the IP addresses of each successive proxy is listed.
// This means, the right-most IP address is the IP address of the most recent proxy and
// the left-most IP address is the IP address of the originating client.
String forwards = request.getHeader("X-Forwarded-For");
if (StringUtils.isNotBlank(forwards)) {
// The left-most IP must be client ip
String ip = StringUtils.substringBefore(forwards, ",");
return ip;
} else if (StringUtils.isNotBlank(request.getRemoteAddr())) {
// this could be real client ip or last proxy ip which forwards the request
return request.getRemoteAddr();
}
return "";
}
String ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null) {
ipAddress = request.getHeader("X_FORWARDED_FOR");
if (ipAddress == null){
ipAddress = request.getRemoteAddr();
}
}