JavaRush /Java blogi /Random-UZ /HTTP dan HTTPS ga
Viacheslav
Daraja

HTTP dan HTTPS ga

Guruhda nashr etilgan
HTTP dan HTTPS ga - 1
Tarkib:

Kirish

Zamonaviy dunyoda siz veb-ilovalarsiz yashay olmaysiz. Va biz kichik tajriba bilan boshlaymiz. Bolaligimda barcha do'konlarda "Argumentlar va faktlar" gazetasi qanday sotilganini eslayman. Men ularni esladim, chunki bolaligimdan shaxsiy tasavvurimga ko'ra, bu gazetalar doimo g'alati ko'rinishga ega edi. Va men ularning veb-saytiga kirishga qaror qildim:
HTTP dan HTTPS ga - 2
Agar biz Google Chrome yordamiga kirsak, biz ushbu sayt xavfsiz ulanishdan foydalanmasligini va siz sayt bilan almashadigan ma'lumotlaringiz uchinchi shaxslar uchun ochiq bo'lishi mumkinligini o'qiymiz. Keling, boshqa yangiliklarni ko'rib chiqaylik, masalan, Fontanka, elektron ommaviy axborot vositalaridan Sankt-Peterburg yangiliklari:
HTTP dan HTTPS ga - 3
Ko'rib turganingizdek, Fontanka veb-saytida ushbu ma'lumotlarga asoslangan xavfsizlik muammosi yo'q. Ma'lum bo'lishicha, veb-resurslar xavfsiz yoki xavfsiz bo'lmasligi mumkin. Himoyalanmagan resurslarga kirish HTTP protokoli orqali sodir bo'lishini ham ko'ramiz. Va agar resurs himoyalangan bo'lsa, u holda ma'lumotlar almashinuvi HTTPS protokoli yordamida amalga oshiriladi, bu erda S oxirida "Xavfsiz" degan ma'noni anglatadi. HTTPS protokoli rfc2818 spetsifikatsiyasida tasvirlangan: " HTTP Over TLS ". Keling, o'z veb-ilovamizni yaratishga harakat qilaylik va uning qanday ishlashini o'zimiz ko'rib chiqaylik. Va yo'lda biz shartlarni tushunamiz.
HTTP dan HTTPS ga - 4

Java tilidagi veb-ilova

Shunday qilib, biz Java-da juda oddiy veb-ilovani yaratishimiz kerak. Birinchidan, bizga Java ilovasining o'zi kerak. Buning uchun biz Gradle loyihasining avtomatik qurish tizimidan foydalanamiz. Bu bizga kerakli katalog tuzilmasini qo'lda yaratmaslikka imkon beradi + Gradle biz uchun loyiha uchun zarur bo'lgan barcha kutubxonalarni boshqaradi va kodni bajarishda ularning mavjudligini ta'minlaydi. Siz Gradle haqida qisqacha sharhda o'qishingiz mumkin: " Gradle haqida qisqacha kirish ". Keling, Gradle Init plaginidan foydalanamiz va buyruqni bajaramiz:
gradle init --type java-application
build.gradleShundan so'ng, bizning loyihamiz qanday kutubxonalardan iboratligini va Gradle bizga taqdim etishini tavsiflovchi qurilish skriptini ochamiz . Keling, biz tajriba o'tkazadigan veb-serverga bog'liqlikni qo'shamiz:
dependencies {
    // Web server
    implementation 'io.undertow:undertow-core:2.0.20.Final'
     // Use JUnit test framework
     testImplementation 'junit:junit:4.12'
}
Veb-ilova ishlashi uchun bizga, albatta, ilovamiz joylashtiriladigan veb-server kerak. Veb-serverlarning xilma-xilligi juda katta, ammo asosiylari: Tomcat, Jetty, Undertow. Bu safar biz Undertow-ni tanlaymiz. Ushbu veb-serverimiz bilan qanday ishlashimiz mumkinligini tushunish uchun keling, Undertow rasmiy veb-saytiga o'tamiz va hujjatlar bo'limiga o'tamiz . Siz va men Undertow Core-ga qaramlikni bog'ladik, shuning uchun biz ushbu Core , ya'ni veb-serverning yadrosi, asosi haqidagi bo'limga qiziqamiz . Eng oson yo'li Undertow uchun Builder API-dan foydalanish:
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();
}
Agar biz kodni ishga tushirsak, quyidagi veb-resursga o'tishimiz mumkin:
HTTP dan HTTPS ga - 5
Bu oddiy ishlaydi. Undertow Builder API tufayli biz localhost va 8080 portiga HTTP tinglovchisini qo'shamiz. Ushbu tinglovchi veb-brauzerdan so'rovlarni oladi va javob sifatida "Salom Dunyo" qatorini qaytaradi. Ajoyib veb-ilova. Lekin biz ko'rib turganimizdek, biz HTTP protokolidan foydalanamiz, ya'ni. Ushbu turdagi ma'lumotlar almashinuvi xavfsiz emas. Keling, HTTPS protokoli yordamida almashinuv qanday amalga oshirilishini aniqlaylik.
HTTP dan HTTPS ga - 6

HTTPS uchun talablar

HTTPSni qanday yoqishni tushunish uchun HTTPS spetsifikatsiyasiga qaytaylik: " RFC-2818: HTTP Over TLS ". Spetsifikatsiyaga ko'ra, HTTPS protokolidagi ma'lumotlar SSL yoki TLS kriptografik protokollari orqali uzatiladi. Odamlar ko'pincha SSL va TLS tushunchasi bilan adashadilar. Aslida, SSL o'z versiyalarini o'zgartirdi va rivojlandi. Keyinchalik TLS SSL protokolini ishlab chiqishda navbatdagi qadam bo'ldi. Ya'ni, TLS shunchaki SSLning yangi versiyasidir. Spetsifikatsiyada shunday deyilgan: "SSL va uning vorisi TLS". Shunday qilib, biz SSL/TLS kriptografik protokollar mavjudligini bilib oldik. SSL - Secure Sockets Layer qisqartmasi bo'lib, "xavfsiz rozetka qatlami" deb tarjima qilinadi. Ingliz tilidan tarjima qilingan soket ulagichdir. Tarmoq orqali ma'lumotlarni uzatish ishtirokchilari tarmoq orqali bir-biri bilan muloqot qilish uchun dasturlash interfeysi (ya'ni API) sifatida rozetkalardan foydalanadilar. Brauzer mijoz vazifasini bajaradi va mijoz soketidan foydalanadi, so'rovni qabul qiluvchi va javob beruvchi server esa server soketidan foydalanadi. Va bu rozetkalar orasida ma'lumotlar almashinuvi sodir bo'ladi. Shuning uchun protokol dastlab SSL deb nomlangan. Ammo vaqt o'tdi va protokol rivojlandi. Va bir vaqtning o'zida SSL protokoli TLS protokoliga aylandi. TLS Transport Layer Security uchun qisqa. TLS protokoli, o'z navbatida, SSL protokoli spetsifikatsiyasining 3.0 versiyasiga asoslanadi. TLS protokoli alohida maqolalar va sharhlar mavzusidir, shuning uchun men o'zimni qiziqtirgan materiallarni ko'rsataman: Xulosa qilib aytganda, HTTPS asosi TLS bilan qoʻl siqish va raqamli sertifikat yordamida “Server identifikatori”ni tekshirish (yaʼni server identifikatsiyasi) hisoblanadi. Bu muhim. Keling, buni eslaylik, chunki ... Bu faktga keyinroq qaytamiz. Shunday qilib, avvalroq biz serverga HTTP protokoli orqali qanday ishlashni aytib berish uchun HttpListener-dan foydalanganmiz. Agar yuqoridagi misolda biz HTTP orqali ishlash uchun HttpListener qo'shgan bo'lsak, HTTPS orqali ishlash uchun HttpsListener qo'shishimiz kerak:
HTTP dan HTTPS ga - 7
Lekin uni qo'shish uchun bizga SSLContext kerak. Qizig'i shundaki, SSLContext bu Undertow'dan emas, balki javax.net.ssl.SSLContext. SSLContext klassi " Java Secure Socket Extension " (JSSE) deb ataladigan qismi - Internetga ulanish xavfsizligini ta'minlash uchun Java kengaytmasi. Ushbu kengaytma " Java Secure Socket Extension (JSSE) Reference Guide " da tasvirlangan . Hujjatlarning kirish qismidan ko'rinib turibdiki, JSSE SSL va TLS protokollarining asosini va Java dasturini taqdim etadi. SSLContext-ni qanday olamiz? JavaDoc SSLContext ni oching va getInstance usulini toping . Ko'rib turganingizdek, SSLContext-ni olish uchun biz "Secure Socket Protocol" nomini ko'rsatishimiz kerak. Parametrlarning tavsifi shuni ko'rsatadiki, bu nomlarni " Java kriptografiyasi arxitekturasi standart algoritm nomi hujjatlari " da topish mumkin. Shuning uchun, keling, ko'rsatmalarga amal qilib, hujjatlarga o'tamiz. Va biz SSL va TLS o'rtasida tanlov qilishimiz mumkinligini ko'ramiz:
HTTP dan HTTPS ga - 8
Endi biz SSLContext-ni quyidagicha yaratishimiz kerakligini tushunamiz:
public SSLContext getSSLContext() {
	// 1. Получаем контекст, в рамках которого будем работать по TLS протоколу
	SSLContext context = null;
	try {
		context = SSLContext.getInstance("TLS");
	} catch (NoSuchAlgorithmException e) {
		throw new IllegalStateException(e);
	}
	return context;
}
Yangi kontekst yaratgandan so'ng, SSLContext " Java Secure Socket Extension (JSSE) Reference Guide " da tasvirlanganini eslaymiz . Biz o'qiymiz va ko'ramiz "Yangi yaratilgan SSLContext init usulini chaqirish orqali ishga tushirilishi kerak". Ya'ni, kontekst yaratish etarli emas. Uni ishga tushirish kerak. Va bu mantiqiy, chunki xavfsizlik haqida biz sizga faqat TLS protokolidan foydalanmoqchi ekanligimizni aytdik. SSLContext-ni ishga tushirish uchun biz uchta narsani ta'minlashimiz kerak: KeyManager, TrustManager, SecureRandom.
HTTP dan HTTPS ga - 9

KeyManager

KeyManager - bu asosiy menejer. U biz bilan bog'langan kishiga qanday "autentifikatsiya ma'lumotlarini" taqdim etishi uchun javobgardir. Hisob ma'lumotlarini shaxs sifatida tarjima qilish mumkin. Identifikatsiya mijoz o'zi da'vo qilgan server ekanligiga va ishonchli bo'lishi mumkinligiga ishonch hosil qilishi uchun kerak. Identifikatsiya sifatida nima ishlatiladi? Esda tutganimizdek, Server identifikatori serverning raqamli sertifikati bilan tasdiqlangan. Bu jarayonni quyidagicha ifodalash mumkin:
HTTP dan HTTPS ga - 10
Bundan tashqari, " JSSE Reference Guide: SSL How to Works "da aytilishicha, SSL "assimetrik kriptografiya" dan foydalanadi, ya'ni bizga kalit juftligi kerak: ochiq kalit va shaxsiy kalit. Biz kriptografiya haqida gapirayotganimiz sababli, "Java Kriptografiya Arxitekturasi" (JCA) o'ynaydi. Oracle ushbu arxitektura bo'yicha ajoyib hujjatni taqdim etadi: " Java Kriptografiya Arxitekturasi (JCA) Yo'riqnomasi ". Bundan tashqari, JavaRush-da JCA haqida qisqacha ma'lumotni o'qishingiz mumkin: " Java kriptografiya arxitekturasi: Birinchi tanishuv ." Shunday qilib, KeyManager-ni ishga tushirish uchun bizga server sertifikatini saqlaydigan KeyStore kerak bo'ladi. Kalit va sertifikatlar do'konini yaratishning eng keng tarqalgan usuli bu JDK tarkibiga kiritilgan keytool yordam dasturidir. Misolni JSSE hujjatlarida ko'rish mumkin: " JSSE bilan foydalanish uchun kalit do'konini yaratish ". Shunday qilib, kalit do'konini yaratish va u erda sertifikat yozish uchun KeyTool yordam dasturidan foydalanishimiz kerak. Qizig'i shundaki, avval kalit avlodi -genkey yordamida ko'rsatilgan edi, ammo endi -genkeypair dan foydalanish tavsiya etiladi. Biz quyidagi narsalarni aniqlashimiz kerak bo'ladi:
  • taxallus : taxallus yoki oddiygina yozuv Keystore-da saqlanadigan nom
  • keyalg : Kalitni shifrlash algoritmi. Keling, RSA algoritmini tanlaylik, bu aslida bizning maqsadimiz uchun standart echimdir.
  • keysize : Kalit hajmi (bitlarda). Tavsiya etilgan minimal o'lcham - 2048, chunki... kichikroq o'lcham allaqachon yorilib ketgan. Batafsil bu yerda o'qishingiz mumkin: " 2048 bitli ssl sertifikati ".
  • dname : Taniqli ism, taniqli ism.
So'ralgan resurs (masalan, https://localhost) unga nisbatan solishtirilishini tushunish muhimdir. Bu "mavzuni moslashtirish" deb ataladi.
  • amal qilish muddati : Yaratilgan sertifikat amal qiladigan kunlardagi muddat, ya'ni. yaroqli.
  • ext : " Nomlangan kengaytmalar " da ko'rsatilgan sertifikat kengaytmasi.
O'z-o'zidan imzolangan sertifikatlar uchun (ya'ni, mustaqil ravishda yaratilgan sertifikatlar uchun) siz quyidagi kengaytmalarni ko'rsatishingiz kerak:
  • -ext san:critical=dns:localhost,ip:127.0.0.1 > SubjectAlternativeName tomonidan mavzuni moslashtirish uchun
  • -ext bc=ca:false > bu sertifikat boshqa sertifikatlarni imzolash uchun ishlatilmasligini bildiradi
Buyruqni bajaramiz (Windows OS uchun misol):
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
Chunki fayl yaratiladi, faylni yaratish uchun barcha huquqlarga ega ekanligingizga ishonch hosil qiling. Bundan tashqari, siz quyidagi maslahatlarni ko'rishingiz mumkin:
HTTP dan HTTPS ga - 11
Bu erda bizga JKS xususiy format ekanligi aytiladi. Xususiylik bu mualliflarning shaxsiy mulki ekanligini va faqat Java-da foydalanish uchun mo'ljallanganligini bildiradi. Uchinchi tomon yordam dasturlari bilan ishlashda nizo kelib chiqishi mumkin, shuning uchun biz ogohlantirilamiz. Bundan tashqari, biz xatoni olishimiz mumkin: The destination pkcs12 keystore has different storepass and keypass. Ushbu xato kalit do'konidagi kirish va kalit do'konining o'zi uchun parollar boshqacha bo'lganligi sababli yuzaga keladi. Keytool hujjatlarida aytilganidek , "Masalan, uchinchi tomon vositalarining ko'pchiligi PKCS #12 kalit do'konidagi do'kon o'tish va kalitlarni bir xil bo'lishini talab qiladi." Biz kalitni o'zimiz belgilashimiz mumkin (masalan, -destkeypass entrypassw). Lekin talablarni buzmaslik va bir xil parolni o'rnatish yaxshiroqdir. Shunday qilib, import quyidagicha ko'rinishi mumkin:
keytool -importkeystore -srckeystore C:/keystore.jks -destkeystore C:/keystore.jks -deststoretype pkcs12
Muvaffaqiyatga misol:
HTTP dan HTTPS ga - 12
Sertifikatni faylga eksport qilish uchun quyidagilarni bajarishingiz mumkin:
keytool -export -alias ssl -storepass passw0rd -file C:/server.cer -keystore C:/keystore.jks
Bundan tashqari, biz Keystore tarkibini quyidagicha olishimiz mumkin:
keytool -list -v -keystore C:/keystore.jks -storepass passw0rd
Ajoyib, endi bizda sertifikat mavjud kalit do'kon bor. Endi siz uni koddan olishingiz mumkin:
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);
	}
}
Agar KeyStore mavjud bo'lsa, biz KeyManagerni ishga tushirishimiz mumkin:
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);
	}
}
Birinchi maqsadimizga erishildi. TrustManager nima ekanligini aniqlash uchun qoladi. TrustManager JSSE hujjatlarida " TrustManager interfeysi " bo'limida tasvirlangan. U KeyManager-ga juda o'xshaydi, lekin uning maqsadi ulanishni so'ragan shaxsga ishonish mumkinligini tekshirishdir. Ochig'ini aytganda, bu KeyManager teskari =) Bizga TrustManager kerak emas, shuning uchun biz nullni o'tkazamiz. Shundan so'ng, serverimizga so'rov yuborayotgan oxirgi foydalanuvchini tasdiqlamaydigan standart TrustManager yaratiladi. Hujjatlarda shunday deyilgan: "standart dastur qo'llaniladi". SecureRandom bilan ham xuddi shunday. Agar null ni belgilasak, standart dastur ishlatiladi. SecureRandom JCA klassi ekanligini va JCA hujjatlarida " SecureRandom Class " bo'limida tasvirlanganligini eslaylik . Umuman olganda, yuqorida tavsiflangan barcha usullarni hisobga olgan holda tayyorgarlik quyidagicha ko'rinishi mumkin:
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);
	}
Faqat serverni ishga tushirish qoladi:
// 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();
}
Bu safar bizning serverimiz quyidagi manzilda ishlaydi. https://localhost:443 Ammo biz hali ham bu resursga ishonib bo‘lmaydi degan xatolikni olamiz:
HTTP dan HTTPS ga - 13
Keling, sertifikatda nima noto'g'ri ekanligini va u bilan nima qilish kerakligini aniqlaylik.
HTTP dan HTTPS ga - 14

Sertifikat boshqaruvi

Shunday qilib, bizning serverimiz allaqachon HTTPS orqali ishlashga tayyor, ammo mijoz bunga ishonmaydi. Nega? Keling, ko'rib chiqaylik:
HTTP dan HTTPS ga - 15
Sababi, bu sertifikat o'z-o'zidan imzolangan sertifikatdir. O'z-o'zidan imzolangan SSL sertifikati o'zi aniqlagan shaxs tomonidan chiqarilgan va imzolangan ochiq kalit sertifikatiga ishora qiladi. Ya'ni, u biron bir hurmatli sertifikatlash organi (CA, Sertifikat organi sifatida ham tanilgan) tomonidan berilmagan. Sertifikat organi ishonchli shaxs sifatida ishlaydi va kundalik hayotda notariusga o'xshaydi. U bergan sertifikatlar ishonchli ekanligiga ishonch hosil qiladi. Bunday CAlar tomonidan sertifikatlar berish xizmati pullik, shuning uchun hech kimga ishonchni yo'qotish va obro'-e'tibor xavfi kerak emas. Odatiy bo'lib, ishonchli bo'lgan bir nechta sertifikat organlari mavjud. Ushbu ro'yxatni tahrirlash mumkin. Va har bir operatsion tizim sertifikatlashtirish organlari ro'yxatini o'z boshqaruviga ega. Masalan, Windows-da ushbu ro'yxatni boshqarish bu erda o'qilishi mumkin: " Windows-da ishonchli ildiz sertifikatlarini boshqarish ". Xato xabarida ko'rsatilganidek, sertifikatni ishonchlilarga qo'shamiz. Buning uchun birinchi navbatda sertifikatni yuklab oling:
HTTP dan HTTPS ga - 16
Windows operatsion tizimida Win+R tugmalarini bosing va mmcboshqaruv konsoliga qo'ng'iroq qilish uchun bajaring. Keyinchalik, joriy konsolga "Sertifikatlar" bo'limini qo'shish uchun Ctrl + M tugmalarini bosing. Keyinchalik, "Ishonchli ildiz sertifikatlash organlari" kichik bo'limida biz bajaramiz Действия / Все задачи / Импорт. Oldin yuklangan faylni faylga import qilaylik. Brauzer sertifikatning o'tgan ishonch holatini eslab qolgan bo'lishi mumkin. Shuning uchun, sahifani ochishdan oldin brauzerni qayta ishga tushirishingiz kerak. Masalan, Google Chrome-da manzillar panelida siz ishga tushirishingiz kerak chrome://restart. Windows operatsion tizimida siz sertifikatlarni ko'rish uchun yordam dasturidan foydalanishingiz mumkin certmgr.msc:
HTTP dan HTTPS ga - 17
Agar biz hamma narsani to'g'ri bajargan bo'lsak, HTTPS orqali serverimizga muvaffaqiyatli qo'ng'iroqni ko'ramiz:
HTTP dan HTTPS ga - 18
Ko'rib turganingizdek, sertifikat endi haqiqiy deb hisoblanadi, resurs mavjud va hech qanday xatolik yo'q.
HTTP dan HTTPS ga - 19

Pastki chiziq

Shunday qilib, biz veb-serverda HTTPS protokolini yoqish sxemasi qanday ko'rinishini va buning uchun nima kerakligini aniqladik. Umid qilamanki, bu erda qo'llab-quvvatlash kriptografiya uchun mas'ul bo'lgan Java Kriptografiya Arxitekturasi (JCA) va Java tomonida TLS amalga oshirilishini ta'minlaydigan Java Secure Socket Extension (JSSE) o'zaro ta'siri orqali ta'minlanishi aniq. JDK-ga kiritilgan keytool yordam dasturi KeyStore kalitlari va sertifikatlar do'koni bilan ishlash uchun qanday ishlatilishini ko'rdik. Bundan tashqari, HTTPS xavfsizlik uchun SSL/TLS protokollaridan foydalanishini angladik. Buni kuchaytirish uchun sizga ushbu mavzu bo'yicha ajoyib maqolalarni o'qishni maslahat beraman: Umid qilamanki, ushbu kichik ko'rib chiqishdan keyin HTTPS biroz shaffofroq bo'ladi. Va agar siz HTTPS-ni yoqishingiz kerak bo'lsa, dastur serverlaringiz va ramkalaringiz hujjatlaridan shartlarni osongina tushunishingiz mumkin. #Viacheslav
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION