1. Hintergrund
HTTP ist ein öffentliches Protokoll, das die Lesbarkeit der Übertragung von Inhalten ermöglicht, und Daten vom Client und Server werden vollständig über Klartext übertragen. Unter diesem Hintergrund sind die gesamten Internetdaten, die auf dem HTTP -Protokoll beruhen, transparent, was großartige Risiken für die Datensicherheit mit sich bringt. Es gibt zwei Ideen, um dieses Problem zu lösen:
Der erste Typ hat in der Realität einen größeren Anwendungsbereich als imaginär. Die beiden Parteien tauschen Tasten offline aus, und der Client verwendet beim Senden von Daten, die über das transparente HTTP -Protokoll im Internet übertragen werden. Nach Erhalt der Anfrage entschlüsselt der Server den einfachen Text auf die vereinbarte Weise. Auch wenn diese Art von Inhalten entführt wird, spielt es keine Rolle, da Dritte ihre Verschlüsselungs- und Entschlüsselungsmethoden nicht kennen. Dieser Ansatz ist jedoch zu speziell, und sowohl der Client als auch der Server müssen sich um diese spezielle Verschlüsselungs- und Entschlüsselungslogik kümmern.
Die zweite Art der C/S -Seite kümmert sich möglicherweise nicht um die oben genannte spezielle Logik. Sie glauben, dass das Senden und Empfangen Klartext sind, weil das Protokoll selbst die Verschlüsselungs- und Entschlüsselungsteil verarbeitet wurde.
Nach den Ergebnissen scheint es keinen Unterschied zwischen den beiden Lösungen zu geben, aber aus der Sicht der Software -Ingenieure ist der Unterschied sehr groß. Da für den ersten Typ das Geschäftssystem erforderlich ist, um die Verschlüsselungs- und Entschlüsselungsfunktion der Antwort zu entwickeln und der offline -interaktive Schlüssel erforderlich ist, hat der zweite Typ nicht das Entwicklungsvolumen.
HTTPS ist die beliebteste Sicherheitsform für HTTP, die erstmals von Netscape erstellt wurde. In HTTPS beginnen URLs mit https: // anstelle von http: //. Wenn HTTPS verwendet wird, werden alle HTTP -Anforderungen und Antworten verschlüsselt, bevor sie an das Netzwerk gesendet werden, das in der SSL -Ebene implementiert wird.
2. Verschlüsselungsmethode
Die einfachen Textdaten werden über die SSL -Ebene verschlüsselt und dann an das Internet gesendet, um das ursprüngliche Datensicherheitsproblem des HTTP -Protokolls zu lösen. Im Allgemeinen werden die Methoden zur Verschlüsselung von Daten in symmetrische Verschlüsselung und asymmetrische Verschlüsselung unterteilt.
2.1 Symmetrische Verschlüsselung
Die symmetrische Verschlüsselung bezieht sich auf die Verwendung des gleichen Schlüssels wie Verschlüsselung und Entschlüsselung. Gemeinsame Algorithmen umfassen DES und AES usw., und die Algorithmuszeit hängt mit der Schlüssellänge zusammen.
Der größte Nachteil der symmetrischen Schlüssel besteht darin, dass sie eine große Anzahl symmetrischer Schlüssel beibehalten und Offline -Austausch benötigen. Um einem Netzwerk mit N-Entitäten beizutreten, sind N (N-1) -Keys erforderlich.
2.2 Asymmetrische Verschlüsselung
Die asymmetrische Verschlüsselung bezieht sich auf Verschlüsselungsmethoden, die auf öffentlichen/privaten Schlüssel basieren. Gemeinsame Algorithmen sind RSA, die im Allgemeinen eine langsamere Verschlüsselung als eine symmetrische Verschlüsselung.
Die symmetrische Verschlüsselung hat einen weiteren Schritt als eine asymmetrische Verschlüsselung, dh den öffentlichen Taste Server und nicht den von jeweils verwalteten Schlüssel.
Der gesamte Verschlüsselungsalgorithmus basiert auf einer bestimmten Zahlentheorie, und der Effekt ist, dass das Verschlüsselungsergebnis irreversibel ist. Das heißt, nur durch den privaten Schlüssel kann der Chiffretext vom öffentlichen Schlüssel verschlüsselt werden.
Unter diesem Algorithmus wird die Anzahl der Schlüssel im gesamten Netzwerk stark reduziert, und jede Person muss nur ein Paar Firmenschlüssel unterhalten. Das heißt, im Netzwerk von N -Entitäten beträgt die Anzahl der Schlüssel 2n.
Der Nachteil ist, dass es langsam läuft.
2.3 Hybridverschlüsselung
In Stephen Chows Film "God of Cookery" gibt es eine Szene, in der sich die Unterwelt an einem Hot Spot befindet und sich über das Thema Chassis zwischen Pee -Garnelen und Rindfleischbällen streiten. Der Gott des Essens sagte: "Es ist wirklich mühsam. Es ist zusammengemischt, um einen pinkelnden Rindfleischball zu machen, dumm!"
Der Vorteil der symmetrischen Verschlüsselung ist die schnelle Geschwindigkeit, und der Nachteil besteht darin, dass sie einen Schlüsselaustausch benötigt. Der Vorteil der asymmetrischen Verschlüsselung besteht darin, dass sie keinen interaktiven Schlüssel benötigt, und der Nachteil ist, dass es langsame Geschwindigkeit ist. Mischen Sie es einfach zusammen und verwenden Sie es gut.
Hybridverschlüsselung ist genau die Verschlüsselungsmethode, die vom HTTPS -Protokoll verwendet wird. Der symmetrische Schlüssel wird zuerst durch asymmetrische Verschlüsselung ausgetauscht, und dann wird die Daten über den symmetrischen Schlüssel übertragen.
Da die Menge der Datenübertragung viel größer ist als die Datenmenge, die zum Austausch von Schlüssel in der frühen Phase der Herstellung einer Verbindung verwendet wird, kann der Leistungseinfluss der asymmetrischen Verschlüsselung im Wesentlichen vernachlässigbar sein und gleichzeitig die Effizienz verbessert.
3. Https Handshake
Es ist ersichtlich, dass HTTPS basierend auf dem ursprünglichen HTTP -Protokoll die Verarbeitung von Sicherheitsschicht hinzugefügt hat:
4. HTTPCLIENT -Unterstützung für das HTTPS -Protokoll
4.1 SSL -Verbindungsfabrik und Domänenname -Überprüfungsvorrichtung erhalten
Als Software -Ingenieur kümmert uns das "HTTPS -Protokoll" in Code? Um das Geheimnis des HTTPClient -Quellcode zu untersuchen, beginnt alles mit httpclientbuilder.
public CloseableHttpclient Build () {// einen Code auslassen httpclientConnectionManager connManagerCopy = this.connmanager; // Wenn der Verbindungspool -Manager angegeben ist, verwenden Sie die angegebene, ansonsten eine neue Standardeinstellung if (connManagercopy == null) {LayeredConnectionsOCKETFACTORY SSLSOCKETFACTORTORYCOPY = this.sssLSocketFactory; if (sslsocketfactoryCopy == null) {// Wenn die Variable der Verwendung der Verwendung von Umgebern verwendet wird, wird die HTTPS -Version und die Kennwortsteuerung aus der Umgebungsvariablen endgültige Zeichenfolge [] SupportedProtocols = SystemProperties gelesen? split (System.getProperty ("https.Protocols"): null; Final String [] SupportedCiphersuites = Systemproperties? split (System.getProperty ("https.ciphersuites"): null; // Wenn nicht angegeben, verwenden Sie den Standard -Validator des Standarddomänennamens, und es wird überprüfen, ob der Domänenname mit dem vom Server zurückgegebenen Zertifikat in der SSL Session HostNameVier HostnameVerifierCopy = this.hostNameVerifier entspricht; if (hostNameVerifierCopy == null) {hostNameVierCopy = new DefaultHostNameVerifier (PublicsuffixMatcherCopy); } // Wenn SSLContext formuliert ist, wird eine benutzerdefinierte SSL -Verbindungsfabrik generiert, ansonsten wird die Standardverbindungsfabrik verwendet, wenn (SSLContext! } else {if (systemProperties) {sslsocketfactoryCopy = new sslConnectionsOCKETFACTORY ((SSLSOCKETFACTORY) SSLSOCKETFACTORY } else {SSLSOCKETFACTORTORYCOPY = new SSLConnectionsOCKETFACTORY (SSLCONTEXTS.CreateFault (), HostNameVerifierCopy); }}} // Registrieren Sie die SSL -Verbindungsfabrik im Verbindungspool -Manager. Wenn eine HTTPS -Verbindung benötigt wird, wird die SSL -Verbindung basierend auf der obigen SSL -Verbindungsfabrik @Suppresswarnings ("Ressourcen") erstellt, die endgültige PoolinghttpclientConnectionManager boolingmgr = new PoolinghttpclientConnectionManager (RegistryBuilder. PlainconnectionsOcketFactory.getSocketFactory ()) .register ("https", sslsocketfactoryCopy) .build (), null, null, dnsresolver, conntimetolive, conntimetolivetimitiNit! = Null? // einige Codes weglassen}}Der obige Code erstellt eine SSLConnectionsConetFactory SSLConnectionsOcketFactory und registriert ihn im Verbindungspool -Manager für die spätere Herstellung von SSL -Verbindungen. Referenz für Verbindungspooling: http://www.vevb.com/article/141015.htm
Hier werden mehrere Schlüsselkomponenten verwendet, um SSLConNectionsOCKETFACTORY, den HostnameVerifier des Domänennamens und den Kontext -SSLContext zu konfigurieren.
Unter ihnen wird HostNameVerifier verwendet, um zu überprüfen, ob das Serverzertifikat mit dem Domänennamen übereinstimmt. Es gibt mehrere Implementierungen. DeFaultHostNameVerifier verwendet die Standardverifizierungsregeln, wodurch der BrowsercomPathostNameVerifier und den StrikthostNameVerifier in der vorherigen Version ersetzt werden. NoophostNameVerifier ersetzt ZulassungAlhostNameVerifier unter Verwendung einer Strategie zur Nichtüberprüfung des Domain -Namens.
Beachten Sie, dass es hier einige Unterschiede gibt, BrowsercompatheStNameVerifier kann mit mehrstufigen Subdomain-Namen übereinstimmen, und "*.foo.com" kann mit "abfoo.com" übereinstimmen. StrictThostNameVerifier kann nicht mit mehrstufigen Subdomain-Namen übereinstimmen, sondern nur mit "A.foo.com".
Nach 4.4 verwendete Httpclient den neuen DefaultHostNameVerifier, um die beiden beiden Strategien zu ersetzen, und behielt nur eine strenge Strategie und StrikthostNameVerifier bei. Da strenge Strategien die Strategien von IE6 und JDK selbst sind, sind Nicht-Strategien die Strategien von Curl und Firefox. Das heißt, die Standard-HTTPClient-Implementierung unterstützt keine multi-Level-Subdomänennamen-Matching-Strategie.
SSLContext speichert Schlüsselinformationen im Zusammenhang mit dem Schlüssel, der in direktem Zusammenhang mit dem Unternehmen steht und sehr wichtig ist. Dies ist später separat zu analysieren.
4.2 So erhalten Sie eine SSL -Verbindung
Wie erhalte ich eine Verbindung aus einem Verbindungspool? Dieser Prozess wurde in früheren Artikeln analysiert. Ich werde es hier nicht analysieren. Weitere Informationen finden Sie in der Verbindung: //www.vevb.com/article/141015.htm.
Nachdem Sie eine Verbindung aus dem Verbindungspool erhalten haben, müssen Sie zuerst die Verbindung herstellen, wenn sich die Verbindung nicht im festgelegten Zustand befindet.
Der Code des DefaulthttpclientConnectionoperator -Teils ist:
public void connect (endgültig verwaltete CONT -Host, endgültiger InetSocketaddress localAddress, endgültiger Int ConnectTimeout, endgültiger SocketConfig -SocketConfig, endgültiger HTTPContext -Kontext) Throws IOException {// zuvor https 'Connection Pool -Implementierung wurde in HttpcLient registriert. Hier erhält Such die Implementierung von HTTPS, dh SSLConnectionsOCKETFACTORY Final Such <ConnectionsOcketFactory> Registry = GetocketFactoryRegistry (Kontext); endgültige connectionsOcketFactory sf = Registry.lookup (Host.getSchemename ()); if (sf == null) {neue nicht unterstützte Schemeexception werfen (Host.getschemename () + "Protokoll wird nicht unterstützt"); } // Wenn sich die Adresse in IP -Form befindet, kann sie direkt verwendet werden. Andernfalls verwenden Sie den DNS -Parser, um die IP zu analysieren, die dem Domänennamen entspricht, um die endgültige InetAddress [] adresses = host.getAddress ()! = NULL zu erhalten? new inetaddress [] {host.getAddress ()}: this.dnsresolver.resolve (Host.Gethostname ()); endgültig int port = this.schemeportresolver.resolve (Host); // Ein Domänenname kann mehreren IP entsprechen und versuchen, eine Verbindung herzustellen, um (int i = 0; i <adresses.length; i ++) {endgültige inetaddress address = adresses [i]; endgültig boolean last = i == adresses.length - 1; // Dies ist nur ein Socket, der generiert wurde, und es gibt keine Verbindung zu Socket Sock = Sf.CreateSocket (Kontext); // Setzen Sie einige TCP -Schichtparameter sock.setsotimeout (socketConfig.getSotimeout ()); Sock.SetReuseaddress (SocketConfig.ISSORESEADDRESS ()); SOCK.SETTCPNODELAY (SOCKKETCONFIG.ISTCPNODELAY ()); Sock.Setkeepalive (SocketConfig.Issokeepalive ()); if (socketConfig.getRCVBUfSIZE ()> 0) {sock.setReceivebufferSize (socketConfig.getRCVBUFSIZE ()); } if (socketConfig.getSndbufSize ()> 0) {sock.setsendBufferSize (socketConfig.getSndbufSize ()); } final int desser = socketConfig.getSolinger (); if (Desser> = 0) {Sock.SetSolinger (True, Dinger); } conn.bind (Sock); endgültig inetsocketaddress remoteaddress = new inetsocketaddress (Adresse, Port); if (this.log.isdebugenabled ()) {this.log.debug ("Anschluss an" + remoteaddress); } try {// eine Verbindung über SSLConNectionsOcketFactory herstellen und an conn socK = sf.connectSocket (ConnectTimeout, Sock, Host, Remoteaddress, LocalAddress, Kontext) binden; Conn.bind (Sock); if (this.log.isdebugenabled ()) {this.log.debug ("Verbindung hergestellt" + conn); } zurückkehren; } // einen Code weglassen}}}Im obigen Code sehen wir, dass die Vorbereitungsarbeiten vor dem Aufbau einer SSL -Verbindung erfolgt. Dies ist ein allgemeiner Prozess, und das Gleiche gilt für gewöhnliche HTTP -Verbindungen. Wo spiegelt der spezielle Prozess der SSL -Verbindung nach?
Der Quellcode von SSLConNectionsOcketFactory lautet wie folgt:
@Override Public Socket ConnectSocket (endgültige Int ConnectTimeout, endgültiger Socket -Socket, endgültiger Httphost -Host, endgültiger InetSocketaddress remoteaddress, endgültig inetSocketaddress localAddress, endgültiger HTTPContext -Kontext) wirft IoException {args.notnull (Host, "HTTPContext -Kontext); Args.notnull (remoteaddress, "Remoteadresse"); Finale Socket Sock = Socket! = NULL? Socket: createsocket (Kontext); if (localAddress! = null) {sock.bind (localAddress); } try {if (connectTimeout> 0 && sock.getSotimeout () == 0) {sock.setsotimeout (ConnectTimeOut); } if (this.log.isdebugenabled ()) {this.log.debug ("Anschluss von Socket mit" + remoteaddress + "mit Timeout" + ConnectTimeOut); } // Connection Sock.connect (remoteaddress, ConnectTimeOut) erstellen; } catch (endgültig ioException ex) {try {sock.close (); } catch (endgültige ioException ignorore) {} throw ex; } // Wenn es sich derzeit um SSLSocket handelt, führen Sie SSL Handshake- und Domänenname -Überprüfung durch, wenn (SSCK -Instanz von SSLSocket) {endgültige SSLSOCKET SSLSOCK = (SSLSOCKET) SOCK; this.log.debug ("Starthandshake"); sslsock.startHandshake (); VerifyHostName (SSLSOCK, HOST.GETHOSTNAME ()); Return Sock; } else {// Wenn es sich nicht um sslsocket handelt, wickeln Sie es als sslsocket return createlayeredSocket (sock, host.gethostname (), remoteaddress.getPort (), Kontext); }} @Override public Socket CreateLayeredSocket (endgültiger Socket -Socket, endgültiges Zeichenfolgenziel, endgültiger int -Port, endgültiger httpcontext -Kontext) löst ioException (// Wickeln Sie einen normalen Socket als sslsocket aus, und es enthält basierend auf SSLContext in httpclientbuilders, die die Schlüsselinformation in SSLSockTPClients enthält. (Sslsocket) this.SocketFactory.createSocket (Socket, Ziel, Port, wahr); // Wenn der SSL -Schicht -Protokollversion und der Verschlüsselungsalgorithmus formuliert sind, verwenden Sie den angegebenen, ansonsten die Standardeinstellung (unterstützteProtokolle! } else {// Wenn unterstützte Protokolle nicht explizit festgelegt sind, entfernen Sie alle SSL -Protokollversionen endgültig [] alleProtocols = sslsock.ggeabledProtocols (); endgültige Liste <string> enabledProtocols = new ArrayList <string> (AllProtocols.length); für (endgültiges String -Protokoll: AllProtocols) {if (! protocol.startswith ("SSL") {enabledProtocols.add (Protokoll); }} if (! enabledProtocols.isempty ()) {sslsock.setenabledProtocols (enabledProtocols.toArray (neue String [enabledProtocols.size ()]))); }} if (unterstützte kiphersuites! } if (this.log.isdebugenabled ()) {this.log.debug ("aktivierte Protokolle:" + arrays.aslist (sslsock.getenabledProtocols ())); this.log.debug ("aktivierte Cipher -Suites:" + arrays.aslist (sslsock.getenabledCiphersuites ())); } preparesocket (SSLSOCK); this.log.debug ("Starthandshake"); // SSL Connection Handshake SSLSOCK.StARTHandShake (); // Nach dem Erfolg des Handshake prüfen Sie, ob das zurückgegebene Zertifikat mit dem Domänennamen verifyHostname (SSLSOCK, Target) übereinstimmt. Return sslsock; }Wie zu sehen ist, für eine SSL -Kommunikation. Stellen Sie zuerst eine normale Socket -Verbindung her, führen Sie dann einen SSL -Handshake durch und überprüfen Sie dann die Konsistenz des Zertifikats und des Domänennamens. Die anschließende Operation besteht darin, über SSLSOCKETIMPL zu kommunizieren. Die Protokolldetails spiegeln sich in der SSLSOCKETIMPL -Klasse wider, aber dieser Teil des Code JDK ist keine Open Source. Diejenigen, die interessiert sind, können den entsprechenden OpenJDK -Quellcode herunterladen, um die Analyse fortzusetzen.
5. Zusammenfassung dieses Artikels
Okay, das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.