JavaRush /Java Blog /Random-TL /Mula sa HTTP hanggang HTTPS

Mula sa HTTP hanggang HTTPS

Nai-publish sa grupo
Mula sa HTTP hanggang HTTPS - 1
Nilalaman:

Panimula

Sa modernong mundo, hindi ka mabubuhay nang walang mga web application. At magsisimula tayo sa isang maliit na eksperimento. Bilang isang bata, naaalala ko kung paano nagbebenta ang lahat ng mga stall ng naturang pahayagan bilang "Mga Argumento at Katotohanan". Naalala ko sila dahil, ayon sa aking personal na persepsyon mula pagkabata, ang mga pahayagang ito ay laging kakaiba. At nagpasya ako kung dapat tayong pumunta sa kanilang website:
Mula sa HTTP hanggang HTTPS - 2
Kung pupunta kami sa tulong ng Google Chrome, mababasa namin na ang site na ito ay hindi gumagamit ng secure na koneksyon at ang impormasyong ipinagpapalit mo sa site ay maaaring ma-access ng mga third party. Suriin natin ang ilang iba pang mga balita, halimbawa St. Petersburg balita mula sa Fontanka, isang electronic media:
Mula sa HTTP hanggang HTTPS - 3
Tulad ng nakikita mo, ang website ng Fontanka ay walang mga problema sa seguridad batay sa mga data na ito. Lumalabas na ang mga mapagkukunan sa web ay maaaring ligtas o hindi. Nakikita rin namin na ang pag-access sa mga hindi protektadong mapagkukunan ay nangyayari sa pamamagitan ng HTTP protocol. At kung protektado ang mapagkukunan, ang pagpapalitan ng data ay isinasagawa gamit ang HTTPS protocol, kung saan ang S sa dulo ay nangangahulugang "Secure". Ang HTTPS protocol ay inilarawan sa rfc2818 na detalye: " HTTP Over TLS ". Subukan nating lumikha ng sarili nating web application at tingnan natin kung paano ito gumagana. At sa daan ay mauunawaan natin ang mga tuntunin.
Mula sa HTTP hanggang HTTPS - 4

Web application sa Java

Kaya, kailangan nating lumikha ng napakasimpleng web application sa Java. Una, kailangan natin ang Java application mismo. Para magawa ito, gagamitin namin ang awtomatikong build system ng Gradle project. Ito ay magbibigay-daan sa amin na huwag manu-manong gumawa ng kinakailangang istraktura ng direktoryo + Pamamahalaan ng Gradle ang lahat ng mga aklatan na kinakailangan para sa proyekto para sa amin at matiyak na available ang mga ito kapag ipinapatupad ang code. Maaari kang magbasa nang higit pa tungkol sa Gradle sa isang maikling pagsusuri: " Isang Maikling Panimula sa Gradle ". Gamitin natin ang Gradle Init Plugin at patakbuhin ang command:
gradle init --type java-application
Pagkatapos nito, buksan natin ang build script build.gradle, na naglalarawan kung anong mga library ang binubuo ng aming proyekto, na ibibigay sa amin ng Gradle. Magdagdag tayo doon ng dependency sa web server kung saan tayo mag-eeksperimento:
dependencies {
    // Web server
    implementation 'io.undertow:undertow-core:2.0.20.Final'
     // Use JUnit test framework
     testImplementation 'junit:junit:4.12'
}
Para gumana ang isang web application, tiyak na kailangan namin ng web server kung saan iho-host ang aming application. Mayroong isang malaking iba't ibang mga web server, ngunit ang mga pangunahing ay: Tomcat, Jetty, Undertow. Sa pagkakataong ito, pipiliin natin ang Undertow. Upang maunawaan kung paano tayo makakapagtrabaho sa web server natin na ito, pumunta tayo sa opisyal na website ng Undertow at pumunta sa seksyon ng dokumentasyon . Ikaw at ako ay nagkonekta ng isang dependency sa Undertow Core, kaya interesado kami sa seksyon tungkol sa mismong Core na ito , iyon ay, ang core, ang batayan ng web server. Ang pinakamadaling paraan ay ang paggamit ng Builder API para sa Undertow:
public static void main(String[] args) {
	Undertow server = Undertow.builder()
            .addHttpListener(8080, "localhost")
            .setHandler(new HttpHandler() {
                @Override
                public void handleRequest(final HttpServerExchange exchange) throws Exception {
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
                    exchange.getResponseSender().send("Hello World");
                }
            }).build();
    server.start();
}
Kung ipapatupad namin ang code, maaari kaming mag-navigate sa sumusunod na mapagkukunan ng web:
Mula sa HTTP hanggang HTTPS - 5
Ito ay gumagana nang simple. Salamat sa Undertow Builder API, nagdaragdag kami ng HTTP listener sa localhost at port 8080. Ang listener na ito ay tumatanggap ng mga kahilingan mula sa web browser at nagbabalik ng string na "Hello World" bilang tugon. Mahusay na web application. Ngunit tulad ng nakikita namin, ginagamit namin ang HTTP protocol, i.e. Ang ganitong uri ng pagpapalitan ng data ay hindi secure. Alamin natin kung paano isinasagawa ang mga palitan gamit ang HTTPS protocol.
Mula sa HTTP hanggang HTTPS - 6

Mga kinakailangan para sa HTTPS

Upang maunawaan kung paano paganahin ang HTTPS, bumalik tayo sa detalye ng HTTPS: " RFC-2818: HTTP Over TLS ". Ayon sa detalye, ang data sa HTTPS protocol ay ipinapadala sa mga cryptographic protocol na SSL o TLS. Ang mga tao ay madalas na naliligaw ng konsepto ng SSL at TLS. Sa katunayan, ang SSL ay nagbago at binago ang mga bersyon nito. Nang maglaon, ang TLS ang naging susunod na hakbang sa pagbuo ng SSL protocol. Ibig sabihin, ang TLS ay simpleng bagong bersyon ng SSL. Ganito ang sabi ng detalye: “SSL, at ang kapalit nitong TLS”. Kaya, nalaman namin na mayroong SSL/TLS cryptographic protocol. Ang SSL ay isang abbreviation para sa Secure Sockets Layer at isinasalin bilang "secure socket layer". Ang socket na isinalin mula sa English ay isang connector. Ang mga kalahok sa paghahatid ng data sa isang network ay gumagamit ng mga socket bilang interface ng programming (iyon ay, isang API) upang makipag-ugnayan sa isa't isa sa network. Ang browser ay gumaganap bilang isang kliyente at gumagamit ng isang client socket, at ang server na tumatanggap ng isang kahilingan at naglalabas ng isang tugon ay gumagamit ng isang server socket. At sa pagitan ng mga socket na ito nangyayari ang pagpapalitan ng data. Iyon ang dahilan kung bakit orihinal na tinawag ang protocol na SSL. Ngunit lumipas ang oras at umunlad ang protocol. At sa isang punto, ang SSL protocol ay naging TLS protocol. Ang TLS ay maikli para sa Transport Layer Security. Ang TLS protocol, naman, ay batay sa bersyon 3.0 ng detalye ng SSL protocol. Ang TLS protocol ay ang paksa ng magkahiwalay na mga artikulo at mga pagsusuri, kaya't ipapahiwatig ko lang ang mga materyal na sa tingin ko ay kawili-wili: Sa madaling salita, ang batayan ng HTTPS ay ang TLS handshake at ang “Server Identity” check (i.e., server identification) gamit ang digital certificate nito. Ito ay mahalaga. Tandaan natin ito, dahil... Babalik tayo sa katotohanang ito mamaya. Kaya, mas maaga ay ginamit namin ang HttpListener upang sabihin sa server kung paano gumana sa HTTP protocol. Kung sa halimbawa sa itaas ay nagdagdag kami ng HttpListener upang gumana sa HTTP, pagkatapos ay upang gumana sa HTTPS kailangan naming magdagdag ng HttpsListener:
Mula sa HTTP hanggang HTTPS - 7
Ngunit upang idagdag ito kailangan namin ng SSLContext. Kapansin-pansin, ang SSLContext ay hindi isang klase mula sa Undertow, ngunit javax.net.ssl.SSLContext. Ang klase ng SSLContext ay bahagi ng tinatawag na " Java Secure Socket Extension " (JSSE) - isang Java extension para sa pagtiyak ng seguridad ng koneksyon sa Internet. Ang extension na ito ay inilalarawan sa " Java Secure Socket Extension (JSSE) Reference Guide ". Gaya ng nakikita mo mula sa panimulang bahagi ng dokumentasyon, ang JSSE ay nagbibigay ng balangkas at pagpapatupad ng Java ng mga protocol ng SSL at TLS. Paano natin makukuha ang SSLContext? Buksan ang JavaDoc SSLContext at hanapin ang getInstance method . Tulad ng nakikita mo, upang makuha ang SSLContext kailangan naming tukuyin ang pangalan na "Secure Socket Protocol". Ang paglalarawan ng mga parameter ay nagpapahiwatig na ang mga pangalang ito ay matatagpuan sa " Java Cryptography Architecture Standard Algorithm Name Documentation ". Samakatuwid, sundin natin ang mga tagubilin at pumunta sa dokumentasyon. At nakita namin na maaari kaming pumili sa pagitan ng SSL at TLS:
Mula sa HTTP hanggang HTTPS - 8
Ngayon naiintindihan namin na kailangan naming lumikha ng SSLContext tulad ng sumusunod:
public SSLContext getSSLContext() {
	// 1. Получаем контекст, в рамках которого будем работать по TLS протоколу
	SSLContext context = null;
	try {
		context = SSLContext.getInstance("TLS");
	} catch (NoSuchAlgorithmException e) {
		throw new IllegalStateException(e);
	}
	return context;
}
Sa paggawa ng bagong konteksto, natatandaan namin na ang SSLContext ay inilarawan sa " Java Secure Socket Extension (JSSE) Reference Guide ". Nabasa at nakikita namin na "Ang isang bagong likhang SSLContext ay dapat masimulan sa pamamagitan ng pagtawag sa init na paraan". Ibig sabihin, hindi sapat ang paglikha ng konteksto. Kailangan itong masimulan. At ito ay lohikal, dahil tungkol sa seguridad, sinabi lang namin sa iyo na gusto naming gamitin ang TLS protocol. Upang masimulan ang SSLContext kailangan naming magbigay ng tatlong bagay: KeyManager, TrustManager, SecureRandom.
Mula sa HTTP hanggang HTTPS - 9

KeyManager

Ang KeyManager ay isang pangunahing tagapamahala. Siya ang may pananagutan para sa kung anong “authentication credential” ang ibibigay sa isang taong nakikipag-ugnayan sa amin. Maaaring isalin ang kredensyal bilang pagkakakilanlan. Ang pagkakakilanlan ay kailangan upang ang kliyente ay sigurado na ang server ay kung sino ang kanyang inaangkin at mapagkakatiwalaan. Ano ang gagamitin bilang pagkakakilanlan? Tulad ng natatandaan namin, ang Server Identity ay na-verify ng digital certificate ng server. Ang prosesong ito ay maaaring ilarawan bilang mga sumusunod:
Mula sa HTTP hanggang HTTPS - 10
Bukod pa rito, sinasabi ng " JSSE Reference Guide: How SSL Works " na gumagamit ang SSL ng "asymmetric cryptography", na nangangahulugang kailangan namin ng key pair: isang pampublikong key at isang pribadong key. Dahil pinag-uusapan natin ang tungkol sa cryptography, ang "Java Cryptography Architecture" (JCA) ay pumapasok. Ang Oracle ay nagbibigay ng mahusay na dokumento sa arkitektura na ito: " Java Cryptography Architecture (JCA) Reference Guide ". Bilang karagdagan, maaari mong basahin ang isang maikling pangkalahatang-ideya ng JCA sa JavaRush: " Java Cryptography Architecture: First acquaintance ." Kaya, para masimulan ang KeyManager, kailangan namin ng KeyStore, na mag-iimbak ng certificate ng aming server. Ang pinakakaraniwang paraan para gumawa ng key at certificate store ay ang keytool utility, na kasama sa JDK. Ang isang halimbawa ay makikita sa dokumentasyon ng JSSE: " Paggawa ng Keystore na Gagamitin sa JSSE ". Kaya, kailangan nating gamitin ang KeyTool utility para gumawa ng key store at isulat ang certificate doon. Kapansin-pansin, ang pagbuo ng susi ay dating tinukoy gamit ang -genkey, ngunit ngayon ay inirerekomendang gamitin ang -genkeypair. Kakailanganin nating tukuyin ang mga sumusunod na bagay:
  • alias : Alias ​​​​o simpleng pangalan kung saan ise-save ang entry sa Keystore
  • keyalg : Key encryption algorithm. Piliin natin ang RSA algorithm, na mahalagang karaniwang solusyon para sa ating layunin.
  • keysize : Sukat ng key (sa bits). Ang pinakamababang inirerekumendang laki ay 2048, dahil... ang isang mas maliit na sukat ay nabasag na. Maaari kang magbasa ng higit pa dito: " isang ssl certificate sa 2048 bit ".
  • dname : Distinguished Name, distinguished name.
Mahalagang maunawaan na ang hiniling na mapagkukunan (halimbawa, https://localhost) ay ihahambing laban dito. Ito ay tinatawag na "subject cn matching".
  • validity : Tagal sa mga araw kung kailan valid ang nabuong certificate, i.e. wasto.
  • ext : Extension ng Certificate na tinukoy sa " Named Extension ".
Para sa Self-signed Certificates (ibig sabihin, para sa mga certificate na ginawa nang hiwalay), dapat mong tukuyin ang mga sumusunod na extension:
  • -ext san:critical=dns:localhost,ip:127.0.0.1 > para magsagawa ng pagtutugma ng paksa ayon sa SubjectAlternativeName
  • -ext bc=ca:false > upang ipahiwatig na ang sertipiko na ito ay hindi ginagamit upang pumirma sa ibang mga sertipiko
Patakbuhin natin ang command (halimbawa para sa Windows OS):
keytool -genkeypair -alias ssl -keyalg RSA -keysize 2048 -dname "CN=localhost,OU=IT,O=Javarush,L=SaintPetersburg,C=RU,email=contact@email.com" -validity 90 -keystore C:/keystore.jks -storepass passw0rd -keypass passw0rd -ext san:critical=dns:localhost,ip:127.0.0.1 -ext bc=ca:false
kasi malilikha ang file, siguraduhing mayroon kang lahat ng karapatan upang likhain ang file. Malamang na makakita ka rin ng payo tulad nito:
Mula sa HTTP hanggang HTTPS - 11
Dito sinabi sa amin na ang JKS ay isang proprietary format. Ang pagmamay-ari ay nangangahulugan na ito ay pribadong pag-aari ng mga may-akda at nilayon para sa paggamit lamang sa Java. Kapag nagtatrabaho sa mga third-party na utility, maaaring magkaroon ng salungatan, kaya naman kami ay binabalaan. Bilang karagdagan, maaari naming matanggap ang error: The destination pkcs12 keystore has different storepass and keypass. Ang error na ito ay nangyayari dahil ang mga password para sa entry sa Keystore at para sa keystore mismo ay magkaiba. Gaya ng sinasabi ng dokumentasyon ng keytool , "Halimbawa, ang karamihan sa mga tool ng third-party ay nangangailangan ng storepass at keypass sa isang PKCS #12 keystore upang maging pareho." Maaari naming tukuyin ang susi mismo (halimbawa, -destkeypass entrypassw). Ngunit mas mahusay na huwag lumabag sa mga kinakailangan at itakda ang parehong password. Kaya maaaring ganito ang hitsura ng pag-import:
keytool -importkeystore -srckeystore C:/keystore.jks -destkeystore C:/keystore.jks -deststoretype pkcs12
Halimbawa ng tagumpay:
Mula sa HTTP hanggang HTTPS - 12
Upang i-export ang certificate sa isang file, maaari mong patakbuhin ang:
keytool -export -alias ssl -storepass passw0rd -file C:/server.cer -keystore C:/keystore.jks
Bilang karagdagan, maaari naming makuha ang mga nilalaman ng Keystore tulad nito:
keytool -list -v -keystore C:/keystore.jks -storepass passw0rd
Mahusay, mayroon na kaming keystore na naglalaman ng certificate. Ngayon ay maaari mo itong makuha mula sa code:
public KeyStore getKeyStore() {
	// Согласно https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#KeyStore
	try(FileInputStream fis = new FileInputStream("C:/keystore.jks")){
		KeyStore keyStore = KeyStore.getInstance("pkcs12");
		keyStore.load(fis, "passw0rd".toCharArray());
		return keyStore;
	} catch (IOException ioe) {
		throw new IllegalStateException(ioe);
	} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException e) {
		throw new IllegalStateException(e);
	}
}
Kung mayroong KeyStore, maaari nating simulan ang KeyManager:
public KeyManager[] getKeyManagers(KeyStore keyStore) {
	String keyManagerAlgo = KeyManagerFactory.getDefaultAlgorithm();
	KeyManagerFactory keyManagerFactory = null;
	try {
		keyManagerFactory = KeyManagerFactory.getInstance(keyManagerAlgo);
		keyManagerFactory.init(keyStore, "passw0rd".toCharArray());
		return keyManagerFactory.getKeyManagers();
	} catch (NoSuchAlgorithmException e) {
		throw new IllegalStateException(e);
	} catch (UnrecoverableKeyException | KeyStoreException e) {
		throw new IllegalStateException(e);
	}
}
Ang aming unang layunin ay nakamit. Ito ay nananatiling malaman kung ano ang TrustManager. Inilalarawan ang TrustManager sa dokumentasyon ng JSSE sa seksyong " The TrustManager Interface ". Ito ay halos kapareho sa KeyManager, ngunit ang layunin nito ay suriin kung ang taong humihiling ng koneksyon ay mapagkakatiwalaan. To put it bluntly, this is the KeyManager in reverse =) We don't need TrustManager, so we'll pass null. Gagawa ang isang default na TrustManager na hindi nagbe-verify sa end user na gumagawa ng mga kahilingan sa aming server. Ganito ang sabi ng dokumentasyon: "gagamitin ang default na pagpapatupad". Pareho sa SecureRandom. Kung tutukuyin namin ang null, gagamitin ang default na pagpapatupad. Tandaan lang natin na ang SecureRandom ay isang klase ng JCA at inilarawan sa dokumentasyon ng JCA sa seksyong " The SecureRandom Class ". Sa kabuuan, ang paghahanda na isinasaalang-alang ang lahat ng mga pamamaraan na inilarawan sa itaas ay maaaring magmukhang ganito:
public static void main(String[] args) {
	// 1. Подготавливаем приложение к работе по HTTPS
	App app = new App();
	SSLContext sslContext = app.getSSLContext();
	KeyStore keyStore = app.getKeyStore();
	KeyManager[] keyManagers = app.getKeyManagers(keyStore);
	try {
		sslContext.init(keyManagers, null, null);
	} catch (KeyManagementException e) {
		throw new IllegalStateException(e);
	}
Ang natitira na lang ay upang simulan ang server:
// 2. Поднимаем server
 	int httpsPort = 443;
	Undertow server = Undertow.builder()
            .addHttpsListener(httpsPort, "localhost", sslContext)
            .setHandler(new HttpHandler() {
                @Override
                public void handleRequest(final HttpServerExchange exchange) throws Exception {
                    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
                    exchange.getResponseSender().send("Hello World");
                }
            }).build();
	server.start();
}
Sa pagkakataong ito ay magiging available ang aming server sa address https://localhost:443 Gayunpaman, makakatanggap pa rin kami ng error na hindi mapagkakatiwalaan ang mapagkukunang ito:
Mula sa HTTP hanggang HTTPS - 13
Alamin natin kung ano ang mali sa sertipiko at kung ano ang gagawin tungkol dito.
Mula sa HTTP hanggang HTTPS - 14

Pamamahala ng sertipiko

Kaya, handa na ang aming server na gumana sa pamamagitan ng HTTPS, ngunit hindi ito pinagkakatiwalaan ng kliyente. Bakit? Tingnan natin:
Mula sa HTTP hanggang HTTPS - 15
Ang dahilan ay ang certificate na ito ay Self-signed Certificate. Ang isang self-sign na SSL certificate ay tumutukoy sa isang public key certificate na inisyu at nilagdaan ng parehong taong kinikilala nito. Ibig sabihin, hindi ito inisyu ng anumang respetadong awtoridad sa sertipikasyon (CA, kilala rin bilang Awtoridad ng Sertipiko). Ang Awtoridad ng Sertipiko ay kumikilos bilang isang tagapangasiwa at katulad ng isang notaryo sa pang-araw-araw na buhay. Tinitiyak niya na maaasahan ang mga inilabas niyang sertipiko. Ang serbisyo ng pagbibigay ng mga sertipiko ng naturang mga CA ay binabayaran, kaya walang nangangailangan ng pagkawala ng tiwala at mga panganib sa reputasyon. Bilang default, mayroong ilang mga awtoridad sa certificate na pinagkakatiwalaan. Mae-edit ang listahang ito. At ang bawat operating system ay may sariling pamamahala ng listahan ng mga awtoridad sa sertipikasyon. Halimbawa, ang pamamahala sa listahang ito sa Windows ay mababasa dito: " Manage Trusted Root Certificates in Windows ". Idagdag natin ang certificate sa mga pinagkakatiwalaan gaya ng ipinahiwatig sa mensahe ng error. Upang gawin ito, i-download muna ang sertipiko:
Mula sa HTTP hanggang HTTPS - 16
Sa OS Windows, pindutin ang Win+R at i-execute mmcpara tawagan ang control console. Susunod, pindutin ang Ctrl+M upang idagdag ang seksyong "Mga Sertipiko" sa kasalukuyang console. Susunod, sa subsection na "Trusted Root Certification Authority" ay isasagawa namin ang Действия / Все задачи / Импорт. I-import natin ang file na na-download kanina sa file. Maaaring naalala ng browser ang nakaraang trust state ng certificate. Samakatuwid, bago buksan ang pahina kailangan mong i-restart ang browser. Halimbawa, sa Google Chrome sa address bar kailangan mong patakbuhin ang chrome://restart. Sa OS Windows, maaari mo ring gamitin ang utility para tingnan ang mga certificate certmgr.msc:
Mula sa HTTP hanggang HTTPS - 17
Kung ginawa namin nang tama ang lahat, makakakita kami ng matagumpay na tawag sa aming server sa pamamagitan ng HTTPS:
Mula sa HTTP hanggang HTTPS - 18
Tulad ng nakikita mo, ang sertipiko ay itinuturing na ngayon na wasto, ang mapagkukunan ay magagamit, at walang mga error.
Mula sa HTTP hanggang HTTPS - 19

Bottom line

Kaya nalaman namin kung ano ang hitsura ng scheme para sa pagpapagana ng HTTPS protocol sa isang web server at kung ano ang kailangan para dito. Umaasa ako na sa puntong ito ay malinaw na ang suporta ay ibinibigay ng pakikipag-ugnayan ng Java Cryptography Architecture (JCA), na responsable para sa cryptography, at ng Java Secure Socket Extension (JSSE), na nagbibigay ng pagpapatupad ng TLS sa bahagi ng Java. Nakita namin kung paano ginagamit ang keytool utility na kasama sa JDK para gumana sa KeyStore key at certificate store. Bukod pa rito, napagtanto namin na gumagamit ang HTTPS ng mga protocol ng SSL/TLS para sa seguridad. Upang mapalakas ito, ipinapayo ko sa iyo na basahin ang mahusay na mga artikulo sa paksang ito: Sana, pagkatapos ng maliit na pagsusuri na ito, ang HTTPS ay magiging mas transparent. At kung kailangan mong paganahin ang HTTPS, madali mong mauunawaan ang mga tuntunin mula sa dokumentasyon ng iyong mga server at framework ng application. #Viacheslav
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION