JavaRush /Java блогу /Random-KY /HTTPден HTTPSге
Viacheslav
Деңгээл

HTTPден HTTPSге

Группада жарыяланган
HTTPден HTTPSге - 1
Мазмуну:

Киришүү

Заманбап дүйнөдө сиз веб тиркемелерсиз жашай албайсыз. Ал эми биз кичинекей эксперимент менен баштайбыз. Бала кезимде «Аргументы и факты» гезитин бардык күркөлөр кантип сатканы эсимде. Мен аларды эстедим, анткени, менин бала кезимдеги жеке түшүнүгүм боюнча, бул гезиттер дайыма кызыктай көрүнчү. Мен алардын веб-сайтына киребизби деп чечтим:
HTTPден HTTPSге - 2
Эгер Google Chrome жардам бөлүмүнө барсак, бул сайт коопсуз туташууну колдонбой турганын жана сайт менен алмашкан маалыматыңыз үчүнчү жактарга жеткorктүү болушу мүмкүн экенин окуйбуз. Келгиле, башка жаңылыктарды карап көрөлү, мисалы, Фонтанка электрондук маалымат каражаттарынын Санкт-Петербургдагы жаңылыктары:
HTTPден HTTPSге - 3
Көрүнүп тургандай, Fontanka веб-сайтында бул маалыматтардын негизинде коопсуздук көйгөйлөрү жок. Көрсө, веб-ресурстар коопсуз болушу мүмкүн же коопсуз эмес. Биз ошондой эле корголбогон ресурстарга жетүү HTTP протоколу аркылуу ишке ашарын көрөбүз. Ал эми ресурс корголгон болсо, анда маалымат алмашуу HTTPS протоколунун жардамы менен ишке ашырылат, мында S аягында "Коопсуз" дегенди билдирет. HTTPS протоколу rfc2818 спецификациясында сүрөттөлгөн: " HTTP Over TLS ". Келгиле, өзүбүздүн веб-тиркемебизди түзүүгө аракет кылалы жана анын кантип иштээрин өз көзүбүз менен көрөлү. Жана жолдо биз терминдерди түшүнөбүз.
HTTPден HTTPSге - 4

Java тorндеги веб-тиркеме

Ошентип, биз Java абдан жөнөкөй веб-тиркеме түзүү керек. Биринчиден, бизге Java тиркемесинин өзү керек. Бул үчүн, биз Gradle долбоорунун автоматтык куруу системасын колдонобуз. Бул бизге керектүү каталог түзүмүн кол менен түзбөөгө мүмкүндүк берет + Gradle биз үчүн долбоор үчүн зарыл болгон бардык китепканаларды башкарып, codeду аткарууда алардын жеткorктүү болушун камсыздайт. Градл жөнүндө кененирээк кыскача баяндамадан окуй аласыз: " Градлга кыскача киришүү ". Келгиле, Gradle Init Plugin колдонуп , буйрукту иштетели:
gradle init --type java-application
Андан кийин, келгиле, куруу скриптин ачалы build.gradle, анда биздин долбоор кандай китепканалардан турганы жана Gradle бизге бере турганы сүрөттөлөт. Биз эксперимент жасай турган веб-serverге көз карандылыкты кошолу:
dependencies {
    // Web server
    implementation 'io.undertow:undertow-core:2.0.20.Final'
     // Use JUnit test framework
     testImplementation 'junit:junit:4.12'
}
Веб тиркеме иштеши үчүн бизге сөзсүз түрдө биздин тиркеме жайгаша турган веб-server керек. Веб-serverлердин көп түрдүүлүгү бар, бирок негизгилери: Tomcat, Jetty, Undertow. Бул жолу биз Undertow тандайбыз. Бул веб-serverибиз менен кантип иштей аларыбызды түшүнүү үчүн, келгиле, Undertow расмий веб-сайтына жана documentация бөлүмүнө баралы . Сиз экөөбүз Undertow Coreге көз карандылыкты туташтырдык, ошондуктан бизди ушул Core , башкача айтканда, веб-serverдин өзөгү, негизи жөнүндө бөлүм кызыктырды . Эң оңой жолу - Undertow үчүн Builder API колдонуу:
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();
}
Эгерде биз codeду аткарсак, биз төмөнкү веб-ресурска кайрыла алабыз:
HTTPден HTTPSге - 5
Бул жөнөкөй иштейт. Undertow Builder API'нин аркасында биз localhost жана 8080 портуна HTTP угуучусун кошобуз. Бул угуучу веб-браузерден суроо-талаптарды кабыл алып, жооп катары "Hello World" сабын кайтарат. Улуу веб-тиркеме. Бирок биз көрүп тургандай, биз HTTP протоколун колдонобуз, б.а. Маалымат алмашуунун бул түрү коопсуз эмес. Келгиле, алмашуу HTTPS протоколунун жардамы менен кантип ишке ашырыларын карап көрөлү.
HTTPден HTTPSге - 6

HTTPS үчүн талаптар

HTTPSти кантип иштетүүнү түшүнүү үчүн HTTPS спецификациясына кайрылып көрөлү: " RFC-2818: HTTP Over TLS ". Спецификацияга ылайык, HTTPS протоколундагы маалыматтар SSL же TLS криптографиялык протоколдору аркылуу берилет. Адамдарды көбүнчө SSL жана TLS түшүнүгү адаштырышат. Чынында, SSL өнүккөн жана анын versionларын өзгөрткөн. Кийинчерээк TLS SSL протоколун иштеп чыгуудагы кийинки кадам болуп калды. Башкача айтканда, TLS жөн гана SSLдин жаңы versionсы. Спецификацияда мындай деп айтылат: "SSL жана анын мураскери TLS". Ошентип, биз SSL/TLS криптографиялык протоколдор бар экенин билдик. SSL - Secure Sockets Layer дегендин аббревиатурасы жана "коопсуз розетка катмары" деп которулат. Англис тorнен которулган розетка туташтыргыч болуп саналат. Тармак аркылуу маалыматтарды берүүнүн катышуучулары тармак аркылуу бири-бири менен байланышуу үчүн программалоо интерфейси (башкача айтканда API) катары розеткаларды колдонушат. Браузер кардар катары иштейт жана кардар розеткасын колдонот, ал эми суроо-талапты кабыл алып, жооп берген server server розеткасын колдонот. Жана дал ушул розеткалардын ортосунда маалымат алмашуу болот. Ошол себептен протокол алгач SSL деп аталган. Бирок убакыт өтүп, протокол түзүлдү. Ал эми бир учурда, SSL протоколу TLS протоколу болуп калды. TLS транспорт катмарынын коопсуздугу үчүн кыска. TLS протоколу, өз кезегинде, SSL протоколунун спецификациясынын 3.0 versionсына негизделген. TLS протоколу өзүнчө макалалардын жана сын-пикирлердин темасы, ошондуктан мен жөн гана кызыктуу материалдарды көрсөтөм: Кыскача айтканда, HTTPS негизи TLS кол алышуу жана анын санарип сертификатын колдонуу менен "Сервердин идентификациясын" текшерүү (б.а. serverдин идентификациясы) болуп саналат. Бул маанилүү. Муну эстейли, анткени... Бул фактыга кийинчерээк кайрылабыз. Ошентип, мурун биз serverге HTTP протоколу аркылуу кантип иштөө керектигин айтуу үчүн HttpListener колдондук. Эгерде жогорудагы мисалда биз HTTP аркылуу иштөө үчүн HttpListener кошсок, анда HTTPS аркылуу иштөө үчүн HttpsListener кошушубуз керек:
HTTPден HTTPSге чейин - 7
Бирок аны кошуу үчүн бизге SSLContext керек. Кызыктуусу, SSLContext бул Undertow классы эмес, бирок javax.net.ssl.SSLContext. SSLContext классы " Java Secure Socket Extension " (JSSE) деп аталган бир бөлүгү болуп саналат - Интернетке туташуу коопсуздугун камсыз кылуу үчүн Java кеңейтүүсү. Бул кеңейтүү " Java Secure Socket Extension (JSSE) Reference Guide " сүрөттөлгөн . Документтин кириш бөлүгүнөн көрүнүп тургандай, JSSE SSL жана TLS протоколдорунун негизин жана Java ишке ашырууну камсыз кылат. SSLContext'ти кантип алабыз? JavaDoc SSLContext ачып, getInstance ыкмасын табыңыз . Көрүнүп тургандай, SSLContext алуу үчүн биз "Secure Socket Protocol" аталышын көрсөтүшүбүз керек. Параметрлердин сүрөттөлүшү бул аталыштарды " Java Cryptography Architecture Standard Algorithm Name Documentation "дан тапса болорун көрсөтүп турат. Ошондуктан, келгиле, көрсөтмөлөрдү аткарып, documentацияга баралы. Жана биз SSL жана TLS ортосунда тандай аларыбызды көрүп жатабыз:
HTTPден HTTPSге - 8
Эми биз төмөнкүдөй SSLContext түзүү керек экенин түшүнөбүз:
public SSLContext getSSLContext() {
	// 1. Получаем контекст, в рамках которого будем работать по TLS протоколу
	SSLContext context = null;
	try {
		context = SSLContext.getInstance("TLS");
	} catch (NoSuchAlgorithmException e) {
		throw new IllegalStateException(e);
	}
	return context;
}
Жаңы контекстти түзгөндөн кийин, SSLContext " Java Secure Socket Extension (JSSE) Reference Guide " сүрөттөлгөндүгүн эстейбиз . "Жаңыдан түзүлгөн SSLContext init ыкмасын чакыруу менен инициализацияланышы керек" деп окуп, көрүп жатабыз. Башкача айтканда, контекстти түзүү жетишсиз. Аны инициализациялоо керек. Жана бул логикалуу, анткени коопсуздук жөнүндө, биз сизге TLS протоколун колдонгубуз келет деп гана айттык. SSLContextди инициализациялоо үчүн биз үч нерсени камсыз кылышыбыз керек: KeyManager, TrustManager, SecureRandom.
HTTPден HTTPSге чейин - 9

KeyManager

KeyManager негизги менеджер болуп саналат. Ал биз менен байланышкан адамга кандай "аныктыгын тастыктоочу маалымат" үчүн жооптуу. Ишеним грамотасын инсандык катары которууга болот. Кардар serverдин ким экенине жана ага ишенүүгө боло турганына ынанышы үчүн идентификация керек. Идентификация катары эмне колдонулат? Эсибизде болгондой, Server Identity serverдин санарип сертификаты менен тастыкталат. Бул процесс төмөнкүчө чагылдырууга болот:
HTTPден HTTPSге чейин - 10
Кошумча, " JSSE маалымдама колдонмосу: SSL кантип иштейт " SSL "ассиметриялык криптографияны" колдонот, демек, бизге ачкыч жуптары керек: ачык ачкыч жана купуя ачкыч. Биз криптография жөнүндө сөз болуп жаткандыктан, "Java Cryptography Architecture" (JCA) ишке кирет. Oracle бул архитектура боюнча эң сонун documentти камсыз кылат: " Java Cryptography Architecture (JCA) Reference Guide ". Кошумчалай кетсек, сиз JavaRush боюнча JCAнын кыскача баяндамасын окуй аласыз: " Java Cryptography Architecture: Биринчи таанышуу ." Ошентип, KeyManagerди инициализациялоо үчүн бизге serverдин сертификатын сактай турган KeyStore керек. Ачкыч жана сертификаттар дүкөнүн түзүүнүн эң кеңири таралган жолу бул JDK менен камтылган keytool утorтасы. Мисалды JSSE documentтеринен көрүүгө болот: " JSSE менен колдонуу үчүн ачкыч дүкөнүн түзүү ". Ошентип, биз ачкыч дүкөнүн түзүү үчүн KeyTool утorтасын колдонушубуз керек жана ал жерге сертификат жазышыбыз керек. Кызыгы, буга чейин ачкыч генерациясы -genkey аркылуу көрсөтүлгөн, бирок азыр -genkeypair колдонуу сунушталат. Биз төмөнкү нерселерди аныктоо керек болот:
  • лакап ат : Кайсыл ат же жөн эле жазуу ачкыч дүкөнүндө сактала турган ат
  • keyalg : Ачкычты шифрлөө алгоритми. Келгиле, RSA алгоритмин тандап алалы, ал негизи биздин максат үчүн стандарттуу чечим болуп саналат.
  • keysize : Ачкычтын өлчөмү (бит менен). Сунушталган минималдуу өлчөмү 2048, анткени... кичинекей өлчөмү мурунтан эле жарака кеткен. Кененирээк бул жерден окуй аласыз: " ssl сертификаты 2048 бит ".
  • dname : Атактуу ысым, өзгөчө ысым.
Суралган ресурс (мисалы, https://localhost) ага каршы салыштырыларын түшүнүү маанилүү. Бул "предметтин дал келиши" деп аталат.
  • жарактуулугу : Түзүлгөн сертификат жарактуу болгон күндөрдөгү узактыгы, б.а. жарактуу.
  • ext : " Аты аталган кеңейтүүлөрдө " көрсөтүлгөн Сертификат кеңейтүүсү .
Өз алдынча кол коюлган сертификаттар үчүн (б.а., өз алдынча түзүлгөн сертификаттар үчүн) төмөнкү кеңейтүүлөрдү көрсөтүшүңүз керек:
  • -ext san:critical=dns:localhost,ip:127.0.0.1 > SubjectAlternativeName боюнча предмет дал келүү үчүн
  • -ext bc=ca:false > бул сертификат башка сертификаттарга кол коюу үчүн колдонулбагандыгын көрсөтүү үчүн
Келгиле, команданы иштетели (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
Анткени файл түзүлөт, файлды түзүүгө бардык укуктарыңыз бар экенине ынаныңыз. Мындан тышкары, сиз төмөнкүдөй кеңештерди көрө аласыз:
HTTPден HTTPSге - 11
Бул жерде биз JKS менчик формат экенин айтышты. Проприетардык бул авторлордун жеке менчиги жана Javaда гана колдонууга арналган дегенди билдирет. Үчүнчү тараптын коммуналдык кызматтары менен иштөөдө конфликт пайда болушу мүмкүн, ошондуктан бизге эскертүү берилет. Мындан тышкары, биз ката алышыбыз мүмкүн: The destination pkcs12 keystore has different storepass and keypass. Бул ката Ачкычтар сактагычындагы жана ачкычтар сактагычынын сырсөздөрү башка болгондуктан келип чыгат. Keytool documentациясында айтылгандай , "Мисалы, үчүнчү тараптын куралдарынын көбү PKCS №12 ачкыч дүкөнүндөгү дүкөнгө өтүү жана баскычтар бирдей болушу үчүн талап кылынат." Биз ачкычты өзүбүз аныктай алабыз (мисалы, -destkeypass entrypassw). Бирок талаптарды бузбоо жана ошол эле сырсөздү коюу жакшы. Ошентип, импорт төмөнкүдөй болушу мүмкүн:
keytool -importkeystore -srckeystore C:/keystore.jks -destkeystore C:/keystore.jks -deststoretype pkcs12
Ийгorктин мисалы:
HTTPден HTTPSге - 12
Сертификатты файлга экспорттоо үчүн, сиз:
keytool -export -alias ssl -storepass passw0rd -file C:/server.cer -keystore C:/keystore.jks
Мындан тышкары, биз Keystore мазмунун төмөнкүдөй ала алабыз:
keytool -list -v -keystore C:/keystore.jks -storepass passw0rd
Жакшы, азыр бизде сертификат камтылган ачкыч дүкөнү бар. Эми сиз аны 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);
	}
}
Эгерде KeyStore бар болсо, анда биз 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);
	}
}
Биздин биринчи максатыбыз ишке ашты. TrustManager деген эмне экенин аныктоо үчүн калды. TrustManager JSSE documentтеринде " TrustManager Interface " бөлүмүндө сүрөттөлгөн. Бул KeyManagerге абдан окшош, бирок анын максаты - туташууну сураган адамга ишенүүгө болорун текшерүү. Ачык айтканда, бул KeyManager тескери =) Бизге TrustManager керек эмес, ошондуктан биз нөлгө өтөбүз. Андан кийин демейки TrustManager түзүлөт, ал акыркы колдонуучунун биздин serverге суроо-талаптарын текшербейт. Документте мындай деп айтылат: "демейки ишке ашыруу колдонулат". SecureRandom менен бирдей. Эгерде биз null деп белгилесек, демейки ишке ашыруу колдонулат. SecureRandom бул JCA классы жана JCA documentтеринде " SecureRandom Class " бөлүмүндө сүрөттөлгөндүгүн эстейли . Жалпысынан, жогоруда сүрөттөлгөн бардык ыкмаларды эске алуу менен даярдоо төмөнкүдөй болушу мүмкүн:
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);
	}
Серверди баштоо гана калды:
// 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();
}
Бул жолу биздин server төмөнкү дарек боюнча жеткorктүү болот. https://localhost:443 Бирок, биз дагы эле бул ресурска ишенүүгө болбойт деген катаны алабыз:
HTTPден HTTPSге - 13
Келгиле, күбөлүктүн эмнеси туура эмес экенин жана ал боюнча эмне кылуу керек экенин карап көрөлү.
HTTPден HTTPSге - 14

Сертификатты башкаруу

Ошентип, биздин server HTTPS аркылуу иштөөгө даяр, бирок кардар ага ишенбейт. Неге? Келгиле, карап көрөлү:
HTTPден HTTPSге чейин - 15
Себеби, бул күбөлүк өзүнөн өзү кол коюлган күбөлүк болуп саналат. Өзүн-өзү кол койгон SSL сертификаты ошол эле адам тарабынан чыгарылган жана кол коюлган ачык ачкычтын сертификатын билдирет. Башкача айтканда, ал эч кандай кадыр-барктуу тастыктоочу орган тарабынан берилген эмес (CA, ошондой эле Тастыктоо органы катары белгилүү). Күбөлүк борбору ишенимдүү адам катары иштейт жана күнүмдүк турмушта нотариуска окшош. Ал берген сертификаттар ишенимдүү деп ишендирүүдө. Мындай САлар тарабынан сертификаттарды берүү кызматы акы төлөнөт, ошондуктан эч кимге ишенимди жоготуунун жана репутация тобокелдигинин кереги жок. Демейки боюнча, ишенимдүү бир нече тастыктама органдары бар. Бул тизме түзөтүүгө болот. Ал эми ар бир иштөө тутумунун сертификаттоо органдарынын тизмесинин өзүнүн башкаруусу бар. Мисалы, Windows'до бул тизмени башкаруу бул жерден окуса болот: " Windows'тун ишенимдүү тамыр сертификаттарын башкаруу ". Ката кабарында көрсөтүлгөндөй сертификатты ишенимдүүлөргө кошолу. Бул үчүн, адегенде күбөлүктү жүктөп алыңыз:
HTTPден HTTPSге чейин - 16
Windows OS ичинде, mmcбашкаруу консолуна чакыруу үчүн Win+R баскычтарын басып, аткарыңыз. Андан кийин, учурдагы консолго "Сертификаттар" бөлүмүн кошуу үчүн Ctrl+M басыңыз. Андан кийин, "Ишенимдүү тамыр сертификаттоо органдары" бөлүмүндө биз аткарабыз Действия / Все задачи / Импорт. Мурда жүктөлгөн файлды файлга импорттойлу. Браузер сертификаттын мурунку ишеним абалын эстеп калган болушу мүмкүн. Ошондуктан, баракты ачардан мурун, браузерди өчүрүп күйгүзүшүңүз керек. Мисалы, дарек тилкесинде Google Chrome'до сиз иштетишиңиз керек chrome://restart. OS Windows'та сиз утorтаны сертификаттарды көрүү үчүн да колдоно аласыз certmgr.msc:
HTTPден HTTPSге чейин - 17
Эгерде биз бардыгын туура кылган болсок, HTTPS аркылуу serverибизге ийгorктүү чалууну көрөбүз:
HTTPден HTTPSге - 18
Көрүнүп тургандай, сертификат азыр жарактуу деп эсептелет, ресурс жеткorктүү жана эч кандай каталар жок.
HTTPден HTTPSге - 19

Төмөнкү сызык

Ошентип, биз веб-serverде HTTPS протоколун иштетүү схемасы кандай экенин жана бул үчүн эмне керек экенин түшүндүк. Бул учурда колдоо криптография үчүн жооптуу Java криптографиялык архитектурасынын (JCA) жана Java тарабында TLS ишке ашырууну камсыз кылган Java Secure Socket Extension (JSSE) өз ара аракеттенүүсү менен камсыз кылынат деп үмүттөнөм. JDK камтылган keytool утorтасы KeyStore ачкычы жана сертификаттар дүкөнү менен иштөө үчүн кандайча колдонуларын көрдүк. Андан тышкары, биз HTTPS коопсуздук үчүн SSL/TLS протоколдорун колдоноорун түшүндүк. Муну бекемдөө үчүн, мен сизге бул тема боюнча мыкты макалаларды окууну сунуштайм: Бул кичинекей карап чыгуудан кийин HTTPS бир аз ачык болуп калат деп үмүттөнөбүз. Эгер сиз HTTPSти иштетүү керек болсо, анда сиз колдонмо serverлериңиздин жана алHowтарыңыздын documentтеринен шарттарды оңой түшүнө аласыз. #Вячеслав
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION