Wie kann ich die Remote-IP-Adresse in NHttpRequestHandler mithilfe von Apache httpcomponents ermitteln?

StackOverflow https://stackoverflow.com/questions/6336060

  •  27-10-2019
  •  | 
  •  

Frage

Ich implementieren einen http-Server im Comet-Stil (verzögerte Antwort) mit Apache httpcomponents.Mein Code ist dem Beispiel „Einfacher nicht blockierender HTTP-Server“ unter sehr ähnlich http://hc.apache.org/httpcomponents-core-ga/examples.html

Ich verwende einen DefaultServerIOEventDispatch und einen DefaultListeningIOReactor, um Anfragen zu versenden, genau wie im Beispielcode.In meinem NHttpRequestHandler möchte ich die IP-Adresse jeder Anfrage protokollieren.

Innerhalb eines HttpRequestHandlers haben Sie Zugriff auf einen HttpRequest, einen HttpResponse und einen HttpContext.Mit einem NHttpRequestHandler haben Sie auch einen NHttpResponseTrigger.Wie erhalte ich die Remote-IP-Adresse, von der die Anfrage kam?Ich kann mir nicht vorstellen, wie ich das mit den verfügbaren Objekten machen soll.

Aktualisieren, hier ist der Scala-Code, den ich letztendlich verwendet habe:

def getIp(context: HttpContext): Option[String] = {
  val conn = context.getAttribute(ExecutionContext.HTTP_CONNECTION)

  conn match {
    case inet: HttpInetConnection =>
      inet.getRemoteAddress match {
        case sock: java.net.InetSocketAddress => // HttpComponents 4.1
          Some(sock.getAddress.getHostAddress)
        case adr: java.net.InetAddress => // HttpComponents 4.2
          Some(adr.getHostAddress)
        case unknown =>
          Some(unknown.toString)
      }
    case _ => None
  }
}

Wie Sie sehen, gibt es in HttpComponents 4.1 einen zusätzlichen Schritt.

War es hilfreich?

Lösung

Man kann werfen NHttpConnection Instanz zu HttpInetConnection eingeben und anrufen HttpInetConnection#getRemoteAddress Methode, um die IP des gegenüberliegenden Endpunkts zu erhalten.Das Verbindungsobjekt kann von erhalten werden HttpContext Instanz, die als Parameter an übergeben wird HttpRequestHandler.Alternativ möchten Sie vielleicht implementieren EventListener Schnittstelle, wenn Sie die Protokollierung von Verbindungslebenszyklusereignissen von Ihrer Protokollverarbeitungslogik entkoppeln möchten.

Es gibt auch eine Reihe von Protokollierungsklassen im Contrib-Paket von HttpCore, mit denen Standard-HttpCore-Klassen um Funktionen zur Protokollierung von Wire- und I/O-Ereignissen erweitert werden können:

http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/httpcore-contrib/src/main/java/org/apache/http/contrib/logging/

Andere Tipps

Ich hatte eine verdammt gute Zeit, um dies herauszufinden, also dachte ich, ich werde in Zukunft in diesem Beitrag über diesen Beitrag wandern.

Zuerst war ich an httpcore-nio 4.1 Und die Verbindung zu bekommen, schien unmöglich. Schließlich habe ich es mit einem Reflexions -Hack gemacht (das ist wahrscheinlich keineswegs der beste Weg, es zu tun). Nach dem Upgrade auf 4.2.1 war es erheblich einfacher. Ich werde beide Lösungen unten teilen. Der folgende Code wird zurückgegeben 403 Forbidden Wenn der Verbindungskunde nicht lokal ist.

Httpcore nio 4.2

@Override
public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) {
    HttpInetConnection connection = (HttpInetConnection) context.getAttribute(ExecutionContext.HTTP_CONNECTION);
    InetAddress ia = connection.getRemoteAddress();
    if("localhost".equals(ia.getHostName()) {
        response.setStatusCode(HttpStatus.SC_FORBIDDEN);
        return;
    }
    ...
}

Httpcore nio 4.1

Ein Wort an die Weisen: Tu das nicht. Es wird für 4.1 funktionieren, aber es wird beim Upgrade 4.2.x brechen. Wenn Sie können, aktualisieren Sie stattdessen.

Diese Lösung funktioniert für httpcore-nio 4.1 Aber Vorsicht, der Code ist ein schrecklicher, schrecklicher Reflexions -Hack, um ein privates Feld zu bekommen (iosession) aus einer endgültigen Variablen (HttpContext).

@Override
public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) {
    try {
        Field f = context.getClass().getDeclaredField("iosession");
        boolean accessible = f.isAccessible();
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        int modifiers = f.getModifiers();
        modifiersField.setAccessible(true);
        modifiersField.set(f, f.getModifiers() & ~Modifier.FINAL & ~Modifier.PRIVATE);
        f.setAccessible(true);
        IOSession io = (IOSession) f.get(context);
        f.setAccessible(accessible);
        modifiersField.set(f, modifiers);
        SocketAddress sa = io.getRemoteAddress();
        if("localhost".equals(((InetSocketAddress) sa).getHostName())) {
            response.setStatusCode(HttpStatus.SC_FORBIDDEN);
            return;
        }
    } catch (Exception e) {
        logger.error("No way! I can't believe this fantastic piece of code threw an exception!", e);
    } 
    ...
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top