Məzmun:
Giriş
Müasir dünyada veb proqramlar olmadan yaşaya bilməzsiniz. Və kiçik bir təcrübə ilə başlayacağıq. Uşaq vaxtı bütün piştaxtaların “Arqumentlər və faktlar” kimi bir qəzeti necə satdığını xatırlayıram. Onları ona görə xatırladım ki, uşaqlıqdan şəxsi təsəvvürümə görə, bu qəzetlər həmişə qəribə görünürdü. Və onların veb saytına daxil olub-olmamağı qərara aldım:
Google Chrome yardımına getsək, bu saytın təhlükəsiz bağlantıdan istifadə etmədiyini və saytla mübadilə etdiyiniz məlumatın üçüncü tərəflər üçün əlçatan ola biləcəyini oxuyacağıq. Gəlin başqa bir xəbərə, məsələn, elektron media olan Fontankadan Sankt-Peterburq xəbərlərinə baxaq:
Gördüyünüz kimi, Fontanka veb saytında bu məlumatlara əsaslanaraq heç bir təhlükəsizlik problemi yoxdur. Məlum olub ki, veb-resurslar təhlükəsiz ola da bilər, olmaya da bilər. Biz həmçinin görürük ki, qorunmayan resurslara giriş HTTP protokolu vasitəsilə baş verir. Resurs qorunursa, məlumat mübadiləsi HTTPS protokolundan istifadə etməklə həyata keçirilir, burada S sonunda "Təhlükəsiz" deməkdir. HTTPS protokolu rfc2818 spesifikasiyasında təsvir edilmişdir: "
HTTP Over TLS ". Gəlin öz veb tətbiqimizi yaratmağa çalışaq və onun necə işlədiyini özümüz görək. Və yolda biz şərtləri anlayacağıq.
Java-da veb proqram
Beləliklə, biz Java-da çox sadə veb proqram yaratmalıyıq. Əvvəlcə Java proqramının özünə ehtiyacımız var. Bunun üçün biz Gradle layihəsinin avtomatik qurma sistemindən istifadə edəcəyik. Bu, bizə lazımi kataloq strukturunu əl ilə yaratmamağa imkan verəcək + Gradle bizim üçün layihə üçün lazım olan bütün kitabxanaları idarə edəcək və kodu icra edərkən onların mövcud olmasını təmin edəcək. Siz qısa icmalda Gradle haqqında ətraflı oxuya bilərsiniz: "
Gradle-a Qısa Giriş ".
Gradle Init Plugin-dən istifadə edək və əmri icra edək:
gradle init --type java-application
build.gradle
Bundan sonra, layihəmizin hansı kitabxanalardan ibarət olduğunu, Gradle-nin bizə təqdim edəcəyini təsvir edən build skriptini açaq . Orada təcrübə aparacağımız veb serverdən asılılıq əlavə edək:
dependencies {
implementation 'io.undertow:undertow-core:2.0.20.Final'
testImplementation 'junit:junit:4.12'
}
Veb tətbiqinin işləməsi üçün bizə mütləq proqramımızın yerləşəcəyi veb server lazımdır. Çox sayda veb server var, lakin əsas olanlar: Tomcat, Jetty, Undertow. Bu dəfə biz Undertow-u seçəcəyik. Bu veb serverimizlə necə işləyə biləcəyimizi başa düşmək üçün rəsmi
Undertow veb saytına keçək və sənədlər bölməsinə keçək .
Siz və mən Undertow Core-dan asılılığı birləşdirmişik, ona görə də bizi bu Core , yəni veb serverin əsası, əsası haqqında bölmə maraqlandırır . Ən asan yol Undertow üçün Builder API istifadə etməkdir:
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();
}
Kodu icra etsək, aşağıdakı veb resursa keçə bilərik:
Sadəcə işləyir. Undertow Builder API sayəsində biz localhost və port 8080-ə HTTP dinləyicisi əlavə edirik. Bu dinləyici veb brauzerdən sorğular alır və cavab olaraq "Salam Dünya" sətirini qaytarır. Əla veb tətbiqi. Ancaq gördüyümüz kimi, biz HTTP protokolundan istifadə edirik, yəni. Bu tip məlumat mübadiləsi təhlükəsiz deyil. HTTPS protokolundan istifadə edərək mübadilələrin necə aparıldığını anlayaq.
HTTPS üçün tələblər
HTTPS-i necə aktivləşdirəcəyini anlamaq üçün HTTPS spesifikasiyasına qayıdaq: "
RFC-2818: HTTP Over TLS ". Spesifikasiyaya görə, HTTPS protokolundakı məlumatlar SSL və ya TLS kriptoqrafik protokolları üzərindən ötürülür. İnsanlar tez-tez SSL və TLS anlayışı ilə aldadılır. Əslində, SSL inkişaf etdi və versiyalarını dəyişdirdi. Daha sonra TLS SSL protokolunun hazırlanmasında növbəti addım oldu. Yəni TLS sadəcə SSL-in yeni versiyasıdır. Spesifikasiya belə deyir: “SSL və onun varisi TLS”. Beləliklə, SSL/TLS kriptoqrafik protokolların olduğunu öyrəndik.
SSL Secure Sockets Layer üçün abreviaturadır və "təhlükəsiz yuva təbəqəsi" kimi tərcümə olunur. İngilis dilindən tərcümə edilmiş soket bir bağlayıcıdır. Şəbəkə üzərindən məlumat ötürülməsinin iştirakçıları şəbəkə üzərindən bir-biri ilə əlaqə saxlamaq üçün proqramlaşdırma interfeysi (yəni API) kimi rozetkalardan istifadə edirlər. Brauzer müştəri kimi çıxış edir və müştəri yuvasından, sorğu qəbul edən və cavab verən server isə server yuvasından istifadə edir. Və məlumat mübadiləsi məhz bu yuvalar arasında baş verir. Buna görə protokol əvvəlcə SSL adlanırdı. Ancaq vaxt keçdi və protokol inkişaf etdi. Və bir anda SSL protokolu TLS protokoluna çevrildi. TLS Nəqliyyat Layer Təhlükəsizliyi üçün qısadır. TLS protokolu, öz növbəsində, SSL protokolunun spesifikasiyasının 3.0 versiyasına əsaslanır. TLS protokolu ayrı-ayrı məqalələrin və rəylərin mövzusudur, ona görə də maraqlı hesab etdiyim materialları qeyd edəcəyəm:
Qısacası, HTTPS-in əsasını TLS-in əl sıxması və rəqəmsal sertifikatından istifadə edərək “Server İdentifikasiyası” yoxlaması (yəni server identifikasiyası) təşkil edir. Vacibdir. Bunu xatırlayaq, çünki... Bu fakta daha sonra qayıdacağıq. Beləliklə, əvvəllər serverə HTTP protokolu üzərindən necə işləməyi izah etmək üçün HttpListener istifadə etdik. Yuxarıdakı nümunədə HTTP üzərində işləmək üçün HttpListener əlavə etmişiksə, HTTPS üzərində işləmək üçün HttpsListener əlavə etməliyik:
Ancaq onu əlavə etmək üçün bizə SSLContext lazımdır. Maraqlıdır ki, SSLContext Undertow-dan bir sinif deyil, lakin
javax.net.ssl.SSLContext
.
SSLContext sinfi " Java Secure Socket Extension " (JSSE) adlanan bir hissəsidir - İnternet bağlantısı təhlükəsizliyini təmin etmək üçün Java genişləndirilməsi.
Bu genişləndirmə " Java Secure Socket Extension (JSSE) Reference Guide " də təsvir edilmişdir . Sənədlərin giriş hissəsindən göründüyü kimi, JSSE SSL və TLS protokollarının çərçivəsini və Java tətbiqini təmin edir. SSLContext-i necə əldə edə bilərik? JavaDoc SSLContext-i açın və
getInstance metodunu tapın . Gördüyünüz kimi, SSLContext əldə etmək üçün "Secure Socket Protocol" adını göstərməliyik. Parametrlərin təsviri göstərir ki, bu adlar "
Java Kriptoqrafiya Arxitekturasının Standart Alqoritm Adı Sənədlərində " tapıla bilər. Buna görə də, təlimatlara əməl edək və sənədlərə keçək. Və görürük ki, biz SSL və TLS arasında seçim edə bilərik:
İndi başa düşürük ki, SSLContext-i aşağıdakı kimi yaratmalıyıq:
public SSLContext getSSLContext() {
SSLContext context = null;
try {
context = SSLContext.getInstance("TLS");
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
}
return context;
}
Yeni kontekst yaratdıqdan sonra SSLContext-in " Java Secure Socket Extension (JSSE) Reference Guide " də təsvir edildiyini xatırlayırıq . Biz oxuyuruq və görürük ki, “Yeni yaradılmış SSLContext init metodunu çağırmaqla işə salınmalıdır”. Yəni kontekst yaratmaq kifayət deyil. Onu işə salmaq lazımdır. Və bu məntiqlidir, çünki təhlükəsizlik haqqında sizə yalnız TLS protokolundan istifadə etmək istədiyimizi söylədik. SSLContext-i işə salmaq üçün üç şeyi təmin etməliyik: KeyManager, TrustManager, SecureRandom.
Açar Meneceri
KeyManager əsas menecerdir. O, bizimlə əlaqə saxlayan birinə hansı “identifikasiya etimadnaməsini” təqdim etməsinə cavabdehdir. Etibarnamə şəxsiyyət kimi tərcümə edilə bilər. Şəxsiyyət ona görə lazımdır ki, müştəri serverin özünün iddia etdiyi şəxs olduğuna və etibar edilə bildiyinə əmin olsun. İdentifikasiya kimi nə istifadə olunacaq? Xatırladığımız kimi, Server Şəxsiyyəti serverin rəqəmsal sertifikatı ilə təsdiqlənir. Bu prosesi aşağıdakı kimi təqdim etmək olar:
Əlavə olaraq, "
JSSE Referans Bələdçisi: SSL Necə İşləyir " deyir ki, SSL "asimmetrik kriptoqrafiya" istifadə edir, bu o deməkdir ki, bizə açar cütü lazımdır: açıq açar və şəxsi açar. Söhbət kriptoqrafiyadan getdiyi üçün “Java Kriptoqrafiya Arxitekturası” (JCA) işə düşür. Oracle bu arxitektura üzrə əla sənəd təqdim edir: "
Java Kriptoqrafiya Arxitekturası (JCA) Referans Bələdçisi ". Bundan əlavə, siz JavaRush-da JCA-nın qısa icmalı ilə tanış ola bilərsiniz: "
Java Kriptoqrafiya Arxitekturası: İlk tanışlıq ." Beləliklə, KeyManager-i işə salmaq üçün bizə serverimizin sertifikatını saxlayacaq KeyStore lazımdır. Açar və sertifikat mağazası yaratmağın ən ümumi yolu JDK-ya daxil olan keytool yardım proqramıdır. Məsələni JSSE sənədlərində görmək olar: "
JSSE ilə istifadə etmək üçün açar anbarının yaradılması ". Beləliklə, açar mağazası yaratmaq və orada sertifikat yazmaq üçün KeyTool yardım proqramından istifadə etməliyik. Maraqlıdır ki, əvvəllər açar generasiyası -genkey istifadə edilməklə müəyyən edilirdi, lakin indi -genkeypair istifadə etmək tövsiyə olunur. Aşağıdakıları müəyyənləşdirməliyik:
- ləqəb : ləqəb və ya sadəcə girişin Açar Mağazada saxlanacağı ad
keyalg : Açar şifrələmə alqoritmi. Gəlin məqsədimiz üçün mahiyyətcə standart həll olan RSA alqoritmini seçək.
- keysize : Açar ölçüsü (bit ilə). Tövsiyə olunan minimum ölçü 2048-dir, çünki... daha kiçik ölçüsü artıq çatlamışdır. Ətraflı burada oxuya bilərsiniz: " 2048 bitlik ssl sertifikatı ".
- dname : Hörmətli ad, görkəmli ad.
Tələb olunan resursun (məsələn, https://localhost) onunla müqayisə ediləcəyini başa düşmək vacibdir. Buna "mövzu cn uyğunluğu" deyilir.
- etibarlılıq : Yaradılmış sertifikatın etibarlı olduğu günlərdəki müddət, yəni. etibarlıdır.
- ext : " Adlandırılmış Genişləndirmələr "də göstərilən Sertifikat Genişləndirilməsi.
Öz-özünə imzalanan Sertifikatlar üçün (yəni, müstəqil yaradılmış sertifikatlar üçün) aşağıdakı genişləndirmələri göstərməlisiniz:
- -ext san:critical=dns:localhost,ip:127.0.0.1 > SubjectAlternativeName ilə mövzu uyğunluğunu yerinə yetirmək üçün
- -ext bc=ca:false > bu sertifikatın digər sertifikatları imzalamaq üçün istifadə edilmədiyini göstərmək üçün
Gəlin əmri yerinə yetirək (Windows OS üçün nümunə):
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
Çünki fayl yaradılacaq, faylı yaratmaq üçün bütün hüquqlara malik olduğunuzdan əmin olun. Bundan əlavə, çox güman ki, belə məsləhət görəcəksiniz:
Burada bizə JKS-nin mülkiyyət formatı olduğu bildirilir. Mülkiyyət o deməkdir ki, o, müəlliflərin şəxsi mülkiyyətidir və yalnız Java-da istifadə üçün nəzərdə tutulub. Üçüncü tərəfin kommunal xidmətləri ilə işləyərkən münaqişə yarana bilər, buna görə də bizə xəbərdarlıq edilir. Bundan əlavə, biz xəta ala bilərik:
The destination pkcs12 keystore has different storepass and keypass
. Bu xəta, Açar anbarındakı giriş və açar anbarının özü üçün parolların fərqli olması səbəbindən baş verir.
Keytool sənədlərində deyildiyi kimi , "Məsələn, üçüncü tərəf alətlərinin çoxu PKCS #12 açar anbarında mağaza keçidi və açar keçidinin eyni olmasını tələb edir." Açarı özümüz təyin edə bilərik (məsələn, -destkeypass entrypassw). Ancaq tələbləri pozmamaq və eyni parol təyin etmək daha yaxşıdır. Beləliklə, idxal bu kimi görünə bilər:
keytool -importkeystore -srckeystore C:/keystore.jks -destkeystore C:/keystore.jks -deststoretype pkcs12
Uğur nümunəsi:
Sertifikatı fayla ixrac etmək üçün aşağıdakıları yerinə yetirə bilərsiniz:
keytool -export -alias ssl -storepass passw0rd -file C:/server.cer -keystore C:/keystore.jks
Əlavə olaraq, Keystore məzmununu belə əldə edə bilərik:
keytool -list -v -keystore C:/keystore.jks -storepass passw0rd
Əla, indi sertifikatı ehtiva edən açar anbarımız var. İndi onu koddan əldə edə bilərsiniz:
public KeyStore getKeyStore() {
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 varsa, biz KeyManager-i işə sala bilərik:
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);
}
}
İlk hədəfimizə nail olduq. TrustManager-in nə olduğunu anlamaq qalır. TrustManager JSSE sənədlərində "
TrustManager İnterfeysi " bölməsində təsvir edilmişdir. O, KeyManager-ə çox bənzəyir, lakin onun məqsədi əlaqə tələb edən şəxsin etibarlı olub olmadığını yoxlamaqdır. Açıqcasına desək, bu, əksinə olan KeyManager-dir =) Bizə TrustManager lazım deyil, ona görə də null keçirəcəyik. Daha sonra serverimizə sorğu göndərən son istifadəçini təsdiq etməyən defolt TrustManager yaradılacaq. Sənədlərdə belə deyilir: "defolt tətbiqdən istifadə ediləcək". SecureRandom ilə eyni. Əgər null təyin etsək, defolt tətbiqdən istifadə olunacaq.
Sadəcə xatırlayaq ki, SecureRandom bir JCA sinfidir və JCA sənədlərində " SecureRandom Class " bölməsində təsvir edilmişdir . Ümumilikdə, yuxarıda təsvir olunan bütün üsulları nəzərə alaraq hazırlıq bu kimi görünə bilər:
public static void main(String[] args) {
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);
}
Yalnız serveri işə salmaq qalır:
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();
}
Bu dəfə serverimiz aşağıdakı ünvanda əlçatan olacaq.
https://localhost:443
Bununla belə, bu resursa etibar edilə bilməyəcəyinə dair xəta alacağıq:
Sertifikatda nəyin səhv olduğunu və bununla bağlı nə edəcəyimizi anlayaq.
Sertifikat idarəçiliyi
Beləliklə, serverimiz artıq HTTPS vasitəsilə işləməyə hazırdır, lakin müştəri ona etibar etmir. Niyə? Gəlin nəzər salaq:
Səbəb bu sertifikatın Öz-özünə imzalanan Sertifikat olmasıdır. Öz-özünə imzalanan SSL sertifikatı, müəyyən etdiyi eyni şəxs tərəfindən verilmiş və imzalanmış açıq açar sertifikatına istinad edir. Yəni, heç bir hörmətli sertifikatlaşdırma orqanı (CA, Sertifikat Təşkilatı kimi də tanınır) tərəfindən verilməmişdir. Sertifikat Orqanı qəyyum kimi çıxış edir və gündəlik həyatda notariusa bənzəyir. Verdiyi sertifikatların etibarlı olduğuna əmin edir. Belə CA-lar tərəfindən sertifikatların verilməsi xidməti ödənişlidir, ona görə də heç kimə etibarın itirilməsi və reputasiya riskləri lazım deyil. Varsayılan olaraq, etibar edilən bir neçə sertifikat orqanı var. Bu siyahı redaktə edilə bilər. Və hər bir əməliyyat sistemi sertifikatlaşdırma orqanlarının siyahısının öz idarəçiliyinə malikdir. Məsələn, Windows-da bu siyahını idarə etmək üçün burada oxuya bilərsiniz: "
Windows-da Etibarlı Kök Sertifikatlarını İdarə et ". Səhv mesajında göstərildiyi kimi sertifikatı etibarlı olanlara əlavə edək. Bunu etmək üçün əvvəlcə sertifikatı yükləyin:
OS Windows-da Win+R düymələrini basın və
mmc
idarəetmə konsoluna zəng etmək üçün icra edin. Sonra, cari konsola "Sertifikatlar" bölməsini əlavə etmək üçün Ctrl+M düymələrini basın. Sonra, "Etibarlı Kök Sertifikatlaşdırma Orqanları" alt bölməsində biz icra edəcəyik
Действия / Все задачи / Импорт
. Gəlin daha əvvəl yüklənmiş faylı fayla idxal edək. Brauzer sertifikatın keçmiş etibar vəziyyətini xatırlamış ola bilər. Buna görə səhifəni açmadan əvvəl brauzeri yenidən başlatmalısınız. Məsələn, ünvan çubuğunda Google Chrome-da işə salmaq lazımdır
chrome://restart
. Windows OS-də sertifikatlara baxmaq üçün yardım proqramından da istifadə edə bilərsiniz
certmgr.msc
:
Hər şeyi düzgün etdiksə, HTTPS vasitəsilə serverimizə uğurlu bir zəng görəcəyik:
Gördüyünüz kimi, sertifikat artıq etibarlı sayılır, resurs mövcuddur və heç bir səhv yoxdur.
Alt xətt
Beləliklə, bir veb serverdə HTTPS protokolunu işə salmaq üçün sxemin nəyə bənzədiyini və bunun üçün nə lazım olduğunu anladıq. Ümid edirəm ki, bu nöqtədə dəstəyin kriptoqrafiyaya cavabdeh olan Java Kriptoqrafiya Arxitekturasının (JCA) və Java tərəfində TLS tətbiqini təmin edən Java Secure Socket Extension (JSSE) qarşılıqlı əlaqəsi ilə təmin edildiyi aydındır. JDK-ya daxil olan keytool yardım proqramının KeyStore açarı və sertifikat mağazası ilə işləmək üçün necə istifadə edildiyini gördük. Bundan əlavə, HTTPS-nin təhlükəsizlik üçün SSL/TLS protokollarından istifadə etdiyini başa düşdük. Bunu gücləndirmək üçün sizə bu mövzuda əla məqalələr oxumağı məsləhət görürəm:
Ümid edirik ki, bu kiçik baxışdan sonra HTTPS bir az daha şəffaf olacaq. Və HTTPS-i aktivləşdirməlisinizsə, tətbiq serverlərinizin və çərçivələrinizin sənədlərindən şərtləri asanlıqla başa düşə bilərsiniz. #Viaçeslav
GO TO FULL VERSION