1. Фон
HTTP - это публичный протокол, который обеспечивает читабельность передачи контента, а данные с клиента и сервера полностью передаются через открытый текст. На этом фоне все данные в Интернете, которые полагаются на протокол HTTP, являются прозрачными, что приносит большие риски безопасности данных. Есть две идеи, чтобы решить эту проблему:
Первый тип имеет более широкий диапазон приложений в реальности, чем воображение. Две стороны обмениваются ключами в автономном режиме, а клиент использует зашифрованный текст при отправке данных, который передается в Интернете через прозрачный протокол HTTP. После получения запроса сервер расшифровывает и получает простой текст согласованным образом. Даже если этот вид контента угнает, это не имеет значения, потому что третьи стороны не знают их методов шифрования и дешифрования. Тем не менее, этот подход слишком особенный, и клиент и сервер должны заботиться об этой специальной логике шифрования и дешифрования.
Второй тип C/S может не заботиться о специальной логике выше. Они считают, что отправка и получение являются открытым текстом, потому что часть шифрования и дешифрования была обработана самим протоколом.
Судя по результатам, между этими двумя решениями нет разницы, но с точки зрения инженеров -программистов разница очень огромна. Поскольку первый тип требует, чтобы бизнес -система разработала функцию шифрования и дешифрования для ответа, и требуется автономный интерактивный ключ, второй тип не имеет объема разработки.
HTTPS является самой популярной формой безопасности для HTTP, впервые созданной Netscape. В https URL начинаются с https: // вместо http: //. Когда используется HTTPS, все HTTP -запросы и ответы зашифрованы перед отправкой в сеть, которая реализована на уровне SSL.
2. Метод шифрования
Простые текстовые данные зашифруются через уровень SSL, а затем отправляются в Интернет для передачи, что решает исходную задачу безопасности данных протокола HTTP. Вообще говоря, методы данных шифрования делятся на симметричное шифрование и асимметричное шифрование.
2.1 Симметричное шифрование
Симметричное шифрование относится к использованию того же ключа, что и шифрование и дешифрование. Общие алгоритмы включают DES и AES и т. Д., А время алгоритма связано с длиной ключей.
Самым большим недостатком симметричных ключей является то, что им необходимо поддерживать большое количество симметричных клавиш и требовать автономного обмена. Чтобы присоединиться к сети с N Entinits, требуются клавиши N (N-1).
2.2 Асимметричное шифрование
Асимметричное шифрование относится к методам шифрования на основе общественных/частных ключей. Общие алгоритмы включают RSA, который, как правило, более медленное шифрование, чем симметричное шифрование.
Симметричное шифрование имеет больше шага, чем асимметричное шифрование, то есть для получения общедоступного ключа сервера, а не ключа, поддерживаемого каждым.
Весь алгоритм шифрования основан на определенной теории чисел, и эффект заключается в том, что результат шифрования необратимый. То есть только через закрытый ключ может быть расшифрована зашифрованный текст, зашифрованный открытым ключом.
В соответствии с этим алгоритмом количество ключей во всей сети значительно сокращается, и каждый человек должен только поддерживать пару ключей компании. То есть в сети n сущностей количество ключей составляет 2n.
Недостатком является то, что он работает медленно.
2.3 Гибридное шифрование
В фильме Стивена Чоу есть сцена «Бог кулинарного бога», где подземный мир находится в горячей точке, спорящих о проблеме разделения шасси между мочами креветками и говяжьими мячами. Бог еды сказал: «Это действительно трудно.
Преимущество симметричного шифрования заключается в его быстрой скорости, и недостатком является то, что он требует обмена ключом. Преимущество асимметричного шифрования состоит в том, что оно не требует интерактивного ключа, и недостаток в том, что это медленная скорость. Просто смешайте его вместе и используйте хорошо.
Гибридное шифрование - это именно метод шифрования, используемый протоколом HTTPS. Симметричный ключ обменивается сначала через асимметричное шифрование, а затем данные передаются через симметричный ключ.
Поскольку объем передачи данных намного больше, чем объем данных, используемых для обмена ключами на ранней стадии установления соединения, влияние асимметричного шифрования на производительность может быть в основном незначительным и в то же время повышает эффективность.
3. Https Handshake
Можно видеть, что на основе исходного протокола HTTP, HTTPS добавила обработку уровня безопасности:
4. Поддержка HttpClient протокола HTTPS
4.1 Получить заводскую завод SSL -соединения и устройство проверки доменного имени
Как инженер -программист, мы заботимся о том, как «протокол HTTPS» реализуется в коде? Чтобы исследовать загадку исходного кода httpclient, все начинается с httpclientbuilder.
public closablehttpclient build () {// Опустить какой -то код httpclientconnectionmanager connmanagercopy = this.connmanager; // Если указан менеджер пула соединений, используйте указанный, в противном случае создайте новый по умолчанию if (connmanagercopy == null) {LayeredConcectionCosteCfactory sslSocketCactoryCopy = this.sslSocketFactory; if (sslsocketFactoryCopy == null) {// Если переменная использования среды включена, версия HTTPS и контроль пароля. Окончательная строка [] Поддержка Split (System.getProperty ("https.protocols")): null; Final String [] Поддержание CipherSuites = SystemProperties? Split (System.getProperty ("https.ciphersuites")): null; // Если не указано, используйте валидатор доменного домена по умолчанию, и он будет подтвержден, соответствует ли доменное имя сертификат, возвращаемый сервером в сеансе SSL HostnameVerifier hostnameVerifierCopy = this.hostNameVerifier; if (hostnameverifiercopy == null) {hostnameverifiercopy = new DefaulthostNameVerifier (publicsUffixMatcherCopy); } // Если сформулирован SSLContext, создается настройка SSL -подключения, в противном случае используется фабрика подключения по умолчанию, если (sslContext! = Null) {sslSocketFactoryCopy = new sslConnectionsocketCosteCactory (sslContext, поддерживающий процесс, поддерживающий энципсут, hostnameverifiercopy); } else {if (SystemProperties) {sslSocketFactoryCopy = new sslConnectionsockeCtectory ((sslSocketFactory) sslsocketFactory.getDefault (), поддерживающий протокол, поддерживающие экипировки, hostnameverifiercopy); } else {sslsocketFactoryCopy = new sslConnectionsockectectory (sslcontexts.createdefault (), hostnameverifiercopy); }}} // Зарегистрировать заводскую завод SSL в диспетчере пула соединений. Когда необходимо подключение к HTTPS, соединение SSL будет создано на основе вышеуказанной фабрики SSL Connection Factory @SuppressWarnings («Ресурс») Final PoolingHttpClientConnectionManager PoolingMgr = New BoolingHttpClientConnectionManager (RegistryBuilder. Plainconnectionsockectory.getsocketfactory ()) .register ("https", sslsocketfactorycopy) .build (), Null, Null, Dnsresolver, Conntimetolive, ConntimetoliveMeanit! = NULL? // Опустите некоторые коды}}Приведенный выше код создает sslConnectionsockeCockeCfactory sslConnectionsockeCocketCactory и регистрирует его в менеджере пула соединений для последующего производства соединений SSL. Ссылка на объединение соединений: http://www.vevb.com/article/141015.htm
Здесь несколько компонентов ключа используются при настройке sslConnectionsocketCactory, доменного имени Validator HostNAmeVerifier и контекста SSLContext.
Среди них hostnameverifier используется для проверки того, соответствует ли сертификат сервера доменное имя. Есть много реализаций. DefaulthostNameVerifier использует правила проверки по умолчанию, заменяя BrowserCompathostNameVerifier и StricthostNameVerifier в предыдущей версии. NOOPHOSTNAMEVERIFIER заменяет AllugalHostNameVerifier, используя стратегию не проверки доменного имени.
Обратите внимание, что здесь есть некоторые различия, BrowserCompathostNameVerifier может соответствовать многоуровневым именам субдомена, и «*.foo.com» может соответствовать «abfoo.com». StricthostNameVerifier не может соответствовать многоуровневым именам поддоменов, только с «a.foo.com».
После 4.4 HttpClient использовал новый DefaulthostNameVerifier, чтобы заменить две вышеупомянутые стратегии, и сохранила только одну строгую стратегию и строгомуседженно. Поскольку строгие стратегии являются стратегиями IE6 и самого JDK, нетронутые стратегии являются стратегиями Curl и Firefox. То есть реализация HTTPClient по умолчанию не поддерживает многоуровневую стратегию сопоставления имен субдона.
SSLContext хранит ключевую информацию, связанную с ключом, которая напрямую связана с бизнесом и очень важна. Это должно быть проанализировано отдельно позже.
4.2 Как получить соединение SSL
Как получить соединение из пула соединений? Этот процесс был проанализирован в предыдущих статьях. Я не буду анализировать это здесь. Пожалуйста, обратитесь к Connection: //www.vevb.com/article/141015.htm.
После получения соединения из пула соединений, если соединение не находится в установленном состоянии, вам нужно сначала установить соединение.
Кодекс части DefaulthttpclientConnectionoperator:
Public void Connect (Final ManagedHttpClientConnection conn, окончательный хост Httphost, Final InetSocketAddress LocalDdress, Final Int ConnectTimeout, Final SocketConfig SocketConfig, окончательный контекст httpContext) Throws IoException {// Ранее, реализация пула HTTPS была зарегистрирована в httpclientBuilder. Здесь поиск получает реализацию HTTPS, то есть SSLConnectionsockeCtectory Final Lookup <neplysectionCosteCfactory> registry = getSocketCactoryRegistry (контекст); final ConnectionSocketCactory sf = registry.lookup (host.getschemename ()); if (sf == null) {бросить новый UnsupportedSchemeexception (host.getSchemename () + "Протокол не поддерживается"); } // Если адрес находится в форме IP, его можно использовать напрямую, в противном случае используйте анализатор DNS для анализа IP, соответствующего доменному имени, чтобы получить окончательный inetAddress [] address = host.getAddress ()! = NULL? новая inetaddress [] {host.getaddress ()}: this.dnsresolver.resolve (host.gethostname ()); окончательный int port = this.schemeportesolver.resolve (host); // Имя домена может соответствовать нескольким IP и попытаться подключиться в порядке (int i = 0; i <address.length; i ++) {final inetAddress address = address [i]; final Boolean Last = i == Addreses.length - 1; // Это просто сгенерированный розетка, и нет никакого соединения с сокетом sock = sf.createSocket (контекст); // Установить некоторые параметры слоя TCP sock.setsotimeout (socketConfig.getSotimeout ()); sock.setreuseaddress (socketconfig.issoreuseaddress ()); sock.settcpnodelay (socketconfig.istcpnodelay ()); Sock.SeteckePalive (socketConfig.issokeePalive ()); if (socketConfig.getRcvbufsize ()> 0) {sock.setReceiveBuffersize (socketConfig.getRcvbufsize ()); } if (socketConfig.getSndbufsize ()> 0) {sock.setsendBuffersize (socketConfig.getSndbufsize ()); } final int linger = socketConfig.getSolinger (); if (linger> = 0) {sock.setsolinger (true, linger); } conn.bind (sock); final inetSocketAddress remoteAddress = new InetSocketAddress (адрес, порт); if (this.log.isdebugenabled ()) {this.log.debug («подключение к» + remoteaddress); } try {// установить соединение через sslConnectionsockeCtectory и связывать с conn sock = sf.connectsocket (connecttimeout, sock, host, remoteaddress, localaddress, context); Conn.Bind (носок); if (this.log.isdebugenabled ()) {this.log.debug ("соединение установлено" + conn); } возвращаться; } // Опустить какой -то код}}В приведенном выше коде мы видим, что подготовительная работа представляет собой перед установлением соединения SSL. Это общий процесс, и то же самое относится и к обычным HTTP -соединениям. Где отражается специальный процесс соединения SSL?
Исходный код sslConnectionsocketCactory выглядит следующим образом:
@Override Public Socket ConnectSocket (Final Int ConnectTimeout, Final Socket Socket, Final Httphost Host, Final inetSocketDdesress RemoteAddress, Final InetSocketCocketAddress LocalDdress, окончательный контекст HTTPContext) Throws IoException {args.notnull (host, http host »); Args.notnull (remoteaddress, "удаленный адрес"); Окончательный сокет носок = сокет! = NULL? сокет: CreateSocket (контекст); if (localaddress! = null) {sock.bind (localaddress); } try {if (connectTimeOut> 0 && sock.getSotimeout () == 0) {sock.setSotimeout (connectTimeOut); } if (this.log.isdebugenabled ()) {this.log.debug ("Подключение сокета с" + remoteaddress + "с таймаутом" + connecttimeout); } // Создать соединение sock.connect (remoteaddress, connecttimeout); } catch (final ioException ex) {try {sock.close (); } catch (окончательное ioException игнорировать) {} thress ex; } // Если это в настоящее время sslsocket, выполните проверку рукопожатия SSL и доменного имени IF (SOCK ENTAMSOF SSLSOCKET) {FINAL SSLSOCKE SSLSOCK = (SSLSOCKE) SOCK; this.log.debug («стартовое рукопожатие»); sslsock.starthandshake (); VerifyHostName (sslsock, host.gethostname ()); вернуть носок; } else {// Если это не sslSocket, оберните его как sslsocket return createLayeredSocket (sock, host.gethostname (), remoteaddress.getport (), context); } } @Override public Socket createLayeredSocket( final Socket socket, final String target, final int port, final HttpContext context) throws IOException { //Wrap a normal socket as SslSocket, socketfactory is generated based on SSLContext in HttpClientBuilder, which contains the key information final SSLSocket sslsock = (SSLSocket) this.socketfactory.createSocket (сокет, цель, порт, true); // Если сформулированы версия протокола уровня SSL и алгоритм шифрования, используйте указанный, в противном случае по умолчанию if (protectedProtocols! = Null) {sslsock.setEnabledProtocols (Поддержка -протоколы); } else {// Если поддерживаемые протоколы не установлены явно, удалите все версии SSL -протокола Окончательная строка [] allProtocols = sslsock.getEnabledProtocols (); Окончательный список <string> enabletprotocols = new ArrayList <string> (allprotocols.length); for (final String Protocol: AllProtocols) {if (! protocol.StartSwith ("ssl")) {enabletprotocols.add (protocol); }} if (! enabledprotocols.isempty ()) {sslsock.setenabledprotocols (enabletprotocols.toarray (new String [enabledprotocols.size ()])); }} if (anceredciphersuites! = null) {sslsock.setEnabledCipherSuites (anceredCipherSuites); } if (this.log.isdebugenabled ()) {this.log.debug ("Enabled Protocols:" + Arrays.aslist (sslsock.getenabledprotocols ())); this.log.debug ("Enabled Cipher Suites:" + Arrays.aslist (sslsock.getEnabledCipherSuites ())); } prepareSocket (sslsock); this.log.debug («стартовое рукопожатие»); // SSL Connection Handshake sslsock.starthandshake (); // После успешного рукопожатия проверьте, соответствует ли возвращенное сертификат с доменным именем verifyhostname (sslsock, target); вернуть sslsock; }Как видно, для общения SSL. Сначала установите обычное соединение сокета, затем выполните рукопожатие SSL, а затем проверьте согласованность сертификата и доменного имени. Последующая операция заключается в связи через SSLSocketImpl. Детали протокола отражены в классе SSLSocketImpl, но эта часть кода JDK не является открытым исходным кодом. Те, кто заинтересован, могут скачать соответствующий исходный код OpenJDK, чтобы продолжить анализ.
5. Резюме этой статьи
Хорошо, вышеупомянутое содержимое этой статьи. Я надеюсь, что содержание этой статьи имеет определенную справочную ценность для каждого обучения или работы. Если у вас есть какие -либо вопросы, вы можете оставить сообщение для общения. Спасибо за поддержку Wulin.com.