Java Tip 96: Използвайте HTTPS в кода на вашия Java клиент

Ако някога сте опитвали да внедрите сигурна комуникация между клиент на Java и HTTPS (HyperText Transfer Protocol Secure) сървър, вероятно сте открили, че стандартният java.net.URLклас не поддържа протокола HTTPS. Изпълнението на това уравнение от страна на сървъра е доста лесно. Почти всеки уеб сървър, който се предлага днес, предлага механизъм за искане на данни, използвайки HTTPS. След като настроите вашия уеб сървър, всеки браузър може да поиска защитена информация от вашия сървър, просто като посочи HTTPS като протокол за URL адреса. Ако все още нямате настроен HTTPS сървър, можете да тествате вашия клиентски код с почти всяка HTTPS уеб страница в Интернет. Разделът Ресурси съдържа кратък списък с кандидати, които можете да използвате за тази цел.

От гледна точка на клиента обаче, простотата на S в края на познатия HTTP е измамна. Браузърът всъщност извършва значително количество задкулисна работа, за да гарантира, че никой не е подправял или наблюдавал информацията, която сте поискали. Както се оказва, алгоритъмът за извършване на криптирането за HTTPS е патентован от RSA Security (поне още няколко месеца). Използването на този алгоритъм е лицензирано от производителите на браузъри, но не е лицензирано от Sun Microsystems за включване в стандартното URLизпълнение на Java клас. В резултат на това, ако се опитате да конструирате URLобект с низ, посочващ HTTPS като протокол, MalformedURLExceptionще бъде хвърлено.

За щастие, за да отговори на това ограничение, спецификацията на Java предоставя възможност за избор на алтернативен манипулатор на потока за URLкласа. Техниката, необходима за внедряване, е различна, в зависимост от виртуалната машина (VM), която използвате. За съвместимата с JDK 1.1 VM на Microsoft, JView, Microsoft е лицензирал алгоритъма и е предоставил обработващ HTTPS поток като част от своя wininetпакет. Sun, от друга страна, наскоро пусна Java Secure Sockets Extension (JSSE) за JDK 1.2-съвместими виртуални машини, в които Sun също е лицензирал и предоставил HTTPS обработващ поток. Тази статия ще демонстрира как да приложите използването на HTTPS-активиран манипулатор на потока, използвайки JSSE и пакета на Microsoft wininet.

JDK 1.2-съвместими виртуални машини

Техниката за използване на JDK 1.2-съвместими виртуални машини разчита основно на разширението Java Secure Sockets (JSSE) 1.0.1. Преди тази техника да заработи, трябва да инсталирате JSSE и да го добавите към пътя на класа на въпросната клиентска виртуална машина.

След като инсталирате JSSE, трябва да зададете системно свойство и да добавите нов доставчик на защита към Securityобекта на класа. Има различни начини да направите и двете неща, но за целите на тази статия е показан програмният метод:

System.setProperty ("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol"); Security.addProvider (нов com.sun.net.ssl.internal.ssl.Provider ());

След извършване на предишните две извиквания на метода, MalformedURLExceptionвече няма да се изхвърля чрез извикване на следния код:

 URL адрес на URL = нов URL ("// [вашият сървър]"); 

Ако се свързвате със стандартния SSL порт, 443, имате възможност да добавите номера на порта към URL низ. Ако обаче вашият уеб сървър използва нестандартен порт за SSL трафик, ще трябва да добавите номера на порта към вашия URL адрес по следния начин:

 URL адрес на URL = нов URL ("// [вашият сървър]: 7002"); 

Една забележка на тази техника се отнася до URL, който се отнася до сървър, който има неподписан или невалиден SSL сертификат. В този случай опитът за извличане на входния или изходния поток от обекта на връзката на URL адреса ще изведе SSLExceptionсъобщение „верига за сертификат на ненадежден сървър“. Ако сървърът има валиден подписан сертификат, няма да се появи изключение.

URL адрес на URL = нов URL ("// [вашият сървър]"); URLConnection con = URL.openConnection (); // SSLException хвърлен тук, ако сертификатът на сървъра е невалиден con.getInputStream ();

Очевидното решение на този проблем е да получите подписани сертификати за вашия сървър. Въпреки това, един от следните URL адреси може също да предостави решение: „Разширение на Java Secure Socket 1.0.2 Промени“ (Sun Microsystems) или форум на Java за разработчици на Java.

Microsoft JView

Поради отчасти на продължаващия спор между Microsoft и Sun относно лицензирането на Java за използване на платформи на Windows, Microsoft JView VM понастоящем е съвместим само с JDK 1.1. Следователно техниката, описана по-горе, няма да работи за клиенти, работещи в JView, тъй като JSSE изисква поне 1.2.2-съвместима VM. Достатъчно удобно е обаче, че Microsoft предоставя обработващ поток с активиран HTTPS като част от com.ms.net.wininetпакета.

Можете да зададете манипулатора на потока в среда на JView, като извикате един статичен метод за URLкласа:

 URL.setURLStreamHandlerFactory (нов com.ms.net.wininet.WininetStreamHandlerFactory ()); 

След като извика предишния метод,

MalformedURLException

вече няма да се изхвърля чрез извикване на следния код:

 URL адрес на URL = нов URL ("// [вашият сървър]"); 

Има две предупреждения, свързани с тази техника. Първо, съгласно документацията на JDK, setURLStreamHandlerFactoryметодът може да бъде извикан най-много веднъж в дадена VM. Следващите опити за извикване на този метод ще хвърлят Error. Второ, както е в случая с решението 1.2 VM, трябва да внимавате, когато използвате URL адрес, който се отнася до сървър с неподписан или невалиден SSL сертификат. Както при предишния случай, възникват проблеми, когато се прави опит за извличане на входния или изходния поток от обекта на връзката на URL адреса. Въпреки това, вместо да изхвърля SSLException, обработващият поток на Microsoft изхвърля стандарт IOException.

URL адрес на URL = нов URL ("// [вашият сървър]"); URLConnection con = url.openConnection (); // IOException хвърлен тук, ако сертификатът на сървъра е невалиден con.getInputStream ();

Отново очевидното решение на този проблем е да се опита HTTPS комуникация само със сървъри, които имат подписан валиден сертификат. JView обаче предлага още една опция. Непосредствено преди извличането на входния или изходния поток от обекта на връзката на URL адреса, можете да се обадите setAllowUserInteraction(true)на обекта на връзката. Това ще накара JView да покаже съобщение, което предупреждава потребителя, че сертификатите на сървъра са невалидни, но му дава възможност все пак да продължи. Имайте предвид обаче, че подобни съобщения може да са разумни за приложение за настолни компютри, но наличието на диалогови прозорци на сървъра ви за нещо различно от целите за отстраняване на грешки вероятно е неприемливо.

Забележка: Можете също да извикате setAllowUserInteraction()метода в съвместими с JDK 1.2 виртуални машини. Въпреки това, при използване на 1.2 VM на Sun (с който е тестван този код), не се показват диалогови прозорци, дори когато това свойство е зададено на true.

URL адрес на URL = нов URL ("// [вашият сървър]"); URLConnection con = url.openConnection (); // кара VM да показва диалогов прозорец при свързване // към ненадеждни сървъри con.setAllowUserInteraction (вярно); con.getInputStream ();

Изглежда, че com.ms.net.wininetпакетът е инсталиран и поставен в системния път на класа по подразбиране в системите Windows NT 4.0, Windows 2000 и Windows 9x. Също така, според документацията на Microsoft JDK, WinInetStreamHandlerFactoryе "... същият манипулатор, който е инсталиран по подразбиране при изпълнение на аплети."

Независимост от платформата

Въпреки че и двете техники, които описах, обхващат повечето платформи, на които вашият Java клиент може да работи, вашият Java клиент може да се наложи да работи както на JDK 1.1-, така и на JDK 1.2-съвместими виртуални машини. „Пиши веднъж, тичай навсякъде“, помниш ли? Както се оказва, комбинирането на тези две техники, така че подходящият манипулатор да се зареди в зависимост от VM, е доста ясен. Следният код демонстрира един от начините да направите това:

Низ strVendor = System.getProperty ("java.vendor"); String strVersion = System.getProperty ("java.version"); // Приема низ на системна версия от формата: //[major].[minor].[release] (напр. 1.2.2) Double dVersion = new Double (strVersion.substring (0, 3)); // Ако работим в среда на MS, използвайте манипулатора на MS потока. if (-1 <strVendor.indexOf ("Microsoft")) {try {Class clsFactory = Class.forName ("com.ms.net.wininet.WininetStreamHandlerFactory"); if (null! = clsFactory) URL.setURLStreamHandlerFactory ((URLStreamHandlerFactory) clsFactory.newInstance ()); } catch (ClassNotFoundException cfe) {хвърли ново изключение ("Не може да се зареди манипулатора на потока на Microsoft SSL" + ". Проверете classpath." + cfe.toString ());} // Ако фабриката за обработчик на потоци // вече е зададена успешно // уверете се, че нашият флаг е настроен и изядете грешката (Error err) {m_bStreamHandlerSet = true;}} // Ако сме в нормална Java среда, // опитайте да използвате манипулатора на JSSE. // ЗАБЕЛЕЖКА: JSSE изисква 1.2 или по-добре иначе, ако (1.2 <= dVersion.doubleValue ()) {System.setProperty ("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol "); опитайте {// ако имаме на разположение доставчика на JSSE, // и той вече не е // зададен, добавете го като ново предоставяне към класа за сигурност. Клас clsFactory = Class.forName ("com.sun.net.ssl.internal.ssl.Provider"); if ((null! = clsFactory) && (null == Security.getProvider ("SunJSSE"))) Security.addProvider ((Provider) clsFactory.newInstance ());} catch (ClassNotFoundException cfe) {хвърля ново изключение ("Не може да се зареди обработващия поток JSSE SSL." + "Проверете classpath." + cfe.toString ()); }}

Ами аплетите?

Извършването на HTTPS-базирана комуникация от аплета изглежда като естествено продължение на описаните по-горе сценарии. В действителност в повечето случаи е дори по-лесно. В 4.0 и по-нови версии на Netscape Navigator и Internet Explorer, HTTPS е активиран по подразбиране за съответните им виртуални машини. Следователно, ако искате да създадете HTTPS връзка от кода на вашия аплет, просто посочете HTTPS като ваш протокол, когато създавате екземпляр на URLкласа:

 URL адрес на URL = нов URL ("// [вашият сървър]"); 

Ако клиентският браузър работи с приставката Java 2 на Sun, тогава има допълнителни ограничения за това как можете да използвате HTTPS. Пълна дискусия за използването на HTTPS с приставката Java 2 може да бъде намерена на уебсайта на Sun (вж. Ресурси).

Заключение

Използването на протокола HTTPS между приложенията може да бъде бърз и ефективен начин за постигане на разумно ниво на сигурност във вашата комуникация. За съжаление причините, поради които не се поддържа като част от стандартната спецификация на Java, изглежда са повече правни, отколкото технически. С появата на JSSE и използването на com.ms.net.winintпакета на Microsoft , защитената комуникация е възможна от повечето платформи само с няколко реда код.

Мат Тауърс, самоописан eBozo, наскоро напусна позицията си за развитие във Visio. Оттогава той се присъединява към интернет стартиране, PredictPoint.com, в Сиатъл, Вашингтон, където работи като редовен разработчик на Java.

Научете повече за тази тема

  • The source code zip file for this article contains the platform-independent code shown above implemented in a class called HttpsMessage. HttpsMessage is intended as a subclass to the HttpMessage class written by Jason Hunter, author of Java Servlet Programming (O'Reilly & Associates). Look for HttpsMessage in the upcoming second edition of his book. If you wish to use that class as intended, you'll need to download and install the com.oreilly.servlets package. The com.oreilly.servlets package and corresponding source code can be found on Hunter's Website

    //www.servlets.com

  • You can also download the source zip file

    //images.techhive.com/downloads/idge/imported/article/jvw/2000/06/httpsmessage.zip

  • Here are a few good Webpages for testing HTTPS communication:
  • //www.verisign.com/
  • //happiness.dhs.org/
  • //www.microsoft.com
  • //www.sun.com
  • //www.ftc.gov
  • More information on the JSSE as well as the downloadable bits and installation instructions can be found on Sun's Website

    //java.sun.com/products/jsse/.

  • A description of how to use some JSSE services, including the technique described above, can be found in "Secure Networking in Java" by Jonathan Knudsen on the O'Reilly Website

    //java.oreilly.com/bite-size/java_1099.html

  • More information on WininetStreamHandlerFactory class can be found in the Microsoft JSDK documentation

    //www.microsoft.com/java/sdk/. In addition, the Microsoft knowledge base also publishes "PRBAllowing the URL class to access HTTPS in Applications"

    //support.microsoft.com/support/kb/articles/Q191/1/20.ASP

  • For more information on using HTTPS with the Java 2 plug-in, see "How HTTPS Works in Java Plug-In" on Sun's Website

    //java.sun.com/products/plugin/1.2/docs/https.html

Тази история, „Java Tip 96: Използвайте HTTPS във вашия клиентски код на Java“, първоначално е публикувана от JavaWorld.