2016-01-22 7 views
5

Ich erstelle einen Login-Server für meine Client-Server-Anwendung.Server-Server-Authentifizierung für Client - Single-Thread

Grundsätzlich gibt es 5 Server, und alle diese Server sind mit einem Login-Server verbunden.

Der Client kann sich mit einem dieser 5 Server verbinden, muss sich jedoch mit Benutzernamen und einem Passwort authentifizieren. Die Authentifizierung sollte auf dem Anmeldeserver erfolgen, und der Anmeldeserver sollte eine Antwort an den tatsächlichen Server zurückgeben, der die Antwort an den Client zurückgeben soll.

So sein wie folgt aus:

Client -> Server -> Login-Server -> Server -> Client (Antwortcode)

Nun, ich Netty verwende und es ist NIO, es ist nicht thread- pro Kunde. Um nun mit NIO zu authentifizieren, müssen wir auf eine Antwort warten, die vom Login-Server kommt, und das kann eine Weile dauern und andere Clients, die sich anmelden wollen, verzögern. Tatsächlich kann man nicht einfach mit NIO auf eine Antwort warten . Also dachte ich über eine Idee nach, wie ich es zum Laufen bringen kann. Meine Idee wurde die Anfrage auf einem anderen Thread ausgeführt und ein Ereignis mit onResponse(String key, int responseCode) Methode und dann den Client-Kanal in einer Karte mit einem generierten Schlüssel, so dass wir wissen, wem die Antwort gehört. Wenn wir uns authentifizieren, senden wir den Schlüssel und die Benutzerdaten.

Aber ich fühle, dass dies ein schlechter Weg ist und es gibt eine effizientere Methode, dies zu tun. Irgendwelche Ideen?

+0

AFAIK Netty unterstützt die Blockierung von NIO mit einem Thread pro Verbindung. Beachten Sie, dass das * Standard * -Verhalten von NIO blockierende Operationen ist und bis vor kurzem nur Sockets nicht-blockierende Operationen als Option unterstützt hat. –

+0

In einer Multi-Server-Umgebung wird es unterbrochen, wenn die Karte verwendet wird, um Kanäle zu behalten. – eg04lt3r

+0

Nur ein Vorschlag, da Sie nach besseren Möglichkeiten gefragt haben, dies zu tun - wenn Sie Java verwenden, können Sie in Websockets suchen, z. B. HTML 5 + http (s). Dann erhalten Sie einen Thread pro Client-Modell, mit dem Sie arbeiten können. Die Authentifizierung mit Verschlüsselung ist für Ihre Anwendung transparent und Sie erhalten alle Funktionen von NIO, ohne dass ein End-Client bereitgestellt werden muss. – MuffinMan

Antwort

2

Unter der Annahme, dass Sie die volle Kontrolle über alle Systeme haben:

eine ID für jede Client-Verbindung im Server zuweisen. Wenn Sie den Benutzer dann authentifizieren müssen, fügen Sie diese Verbindungs-ID in die Anfrage vom Server zum Login-Server ein und kehren Sie zurück, ohne auf die Antwort vom Login-Server zu warten.

Einige Zeit in der Zukunft wird Ihr Server Login-Antwort vom Login-Server erhalten. Wenn die Anmeldeantwort die Clientverbindungs-ID enthält, verwenden Sie diese ID, um eine Verbindung von einem Server zu einem Client zu finden und diese Antwort an den Client weiterzuleiten.

1

Hier ist, wie ich es gemacht habe.

Setup-

eine Kanal-Wrapper-Klasse erstellen, so dass Sie erkennen können, welcher Kanal auf dem Client gehört.

public class CustomChannel implements Channel { 

    private final Channel channel; 
    private final String clientId; 

    ... 
} 

Erstellen eines benutzerdefinierten ChannelMatcher zum Abgleichen Kunden Kanal:

public class CustomChannelMatcher implements ChannelMatcher { 
    private final String clientId; 

    public CustomChannelMatcher(String clientId) { 
     this.clientId = clientId; 
    } 

    @Override 
    public boolean matches(Channel channel) { 
     if (channel instanceof CustomChannel) { 
      return clientId.equals(((CustomChannel) channel).getClientId()); 
     } 
     return false; 
    } 

    ... 
} 

Handhabung Anfrage

In Ihrem Client-Handler verwenden Channel Kanäle den Überblick über Ihre Kunden zu halten.

ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); 

... 

channelGroup.add(new CustomChannel(ctx.channel(), clientId)); 

// send request to another server without blocking 

Handhabung Antwort

In Ihrem Server-Handler, verwenden Sie Ihre CustomChannelMatcher des Kunden Kanal anzupassen.

// when the server responds sometimes later 

channelGroup.writeAndFlush(responseMessage, 
    new CustomChannelMatcher(clientId)); 

Der obige Code wird einen passenden Client-Kanal finden und die Nachricht darauf schreiben.

1

Sie sind besorgt, einen NIO-Arbeitsthread zu blockieren, aber Sie spinnen einen anderen Thread, um die Anmeldung durchzuführen. Du hast nur noch einen Thread benutzt. Definieren Sie also mehr Threads in Ihrem Server für http (s) und machen Sie damit fertig. Sofern Sie nicht mehr als 100 gleichzeitige Anmeldungen erwarten, gibt es hier kein Problem.

NIO ist weit überschätzt; Das OS ist sehr gut darin, Threads und Kontextwechsel zu planen, viel besser als in Java, wenn Backflips mit asyn apis ausgeführt werden. Waiting Threads verbrauchen keine CPU.

0

Ich weiß, du hast gesagt, du wärst auf Netty. Ich muss nur etwas über Servlet API sagen (

)

FYI, das ist das Problem mit dem Servlet API 3.0 behandelt, das Sie genau das in einem AsynContext ausführen können. Kein Scherz, lesen Sie auf dem Servlet 3.0, vorzugsweise Java Youtube Präsentationen und Tutorials, sogar die PDF-Spezifikation ist besser als die Javadoc.

Und wenn Sie sogar NIO auf dem Servletinputstream/Servletoutputstream ausführen möchten, können Sie dies (obwohl ein bisschen beteiligt) mit Servlet API 3.1. Die Java-Präsentation (2014 denke ich) ist großartig.