Terkadang menjadi penting untuk mentransfer data antara aplikasi yang berjalan di browser dan program yang berjalan di sistem yang sama di mana browser sedang berjalan. Ini mungkin perlu, misalnya, jika kita perlu bekerja dengan peralatan yang terhubung secara lokal. Pembaca kartu pintar, kunci enkripsi perangkat keras dan sebagainya.

Gambar dari sini
Yang pertama terlintas dalam pikiran adalah tiga cara untuk mengatasi masalah ini:
- Lakukan dengan alat peramban, atau tulis plugin untuknya
- Atur pertukaran data melalui backend, bertindak sebagai perantara
- Tambahkan layanan HTTP ke program, dan akses langsung dari browser
Item ketiga terlihat bagus, memungkinkan Anda untuk menghapus otorisasi dalam program ini, tidak memerlukan antarmuka pengguna sama sekali. Mari kita coba untuk mengimplementasikannya dengan menulis program dalam C # di bawah .NET Framework 4. Karena kita berbicara tentang .NET, solusinya hanya untuk Windows (XP dan yang lebih baru). Kami akan membuat aplikasi web pada sudut.
Kenapa tidak 1 dan 2?
Item pertama pasti akan membawa banyak rasa sakit, Anda harus mendukung browser secara terpisah, Anda dapat melakukan jauh dari segalanya di plug-in browser. Namun demikian, secara teori, dimungkinkan untuk bekerja dengan kartu pintar melalui plugin. Tetapi Anda membutuhkan cara yang lebih sederhana.
Poin kedua mudah diterapkan, tetapi untuk skema ini Anda harus melakukan otorisasi tidak hanya di situs, tetapi juga di aplikasi lokal. Ini berarti bahwa beberapa jenis antarmuka akan diperlukan, tetapi ketika mengubah kata sandi, otorisasi ulang dalam program juga akan diperlukan. Plus, di jaringan perusahaan akan ada masalah tambahan dengan jaringan, mereka sering memiliki akses Internet melalui proxy dengan penyaringan dan otorisasi yang parah, Anda juga harus membuat antarmuka untuk mengonfigurasi proxy, dan Anda tidak selalu dapat menyingkirkan pengaturan otomatis. Akan lebih sulit bagi pengguna yang jauh dari IT untuk bekerja dengan ini, kami akan membuat lebih banyak pekerjaan dukungan teknis. Tentu saja, Anda dapat membuat paket instalasi secara individual untuk setiap pengguna untuk menghapus kebutuhan otorisasi utama, tetapi ini hanya akan menambah masalah.
Apa hubungannya HTTPS dengan itu?
Ketika sebuah situs menjalankan HTTPS, browser memblokir pengunduhan konten aktif menggunakan HTTP. Namun, menurut logika beberapa hal, browser harus mempertimbangkan permintaan ke mesin lokal melalui HTTP agar aman , dan tidak boleh memblokirnya. Ini ternyata tidak begitu.
Tabel menunjukkan hasil studi kecil tentang perilaku browser pada platform Windows:
Tabel tersebut menunjukkan perilaku browser ketika mencoba membuat permintaan di alamat yang sesuai. Browser pada mesin Chromium berperilaku mirip dengan Chrome, dan perilaku Edge 44 mirip dengan perilaku IE 11. Sertifikat yang valid dikeluarkan untuk HTTPS, ditandatangani dengan sertifikat root yang ditandatangani sendiri. Perilaku untuk https://127.0.0.1 dan https: // localhost adalah sama, hanya untuk 127.0.0.1 maka Anda perlu mengeluarkan sertifikat juga, dan sertifikat untuk alamat IP jarang ditemukan, jadi kami mengabaikan hal ini.
Semuanya berfungsi di Chrome. Chrome dan IE menggunakan penyimpanan sertifikat sistem, jadi HTTPS juga berfungsi di dalamnya. Firefox menggunakan toko sertifikatnya sendiri, sehingga tidak mempercayai sertifikat yang ditandatangani sendiri oleh kami. Firefox dan IE tidak mempercayai nama host lokal, dan itu benar, karena tidak ada yang menjamin bahwa itu menyelesaikan ke 127.0.0.1 (walaupun mereka hanya bisa memeriksanya seperti yang dilakukan Chrome).
Masalah utama: IE tidak memungkinkan untuk mengakses program melalui HTTP. Jadi ribut-ribut dengan sertifikat yang tidak bisa kita hindari.
Untuk bekerja dengan browser, Anda juga perlu menentukan header Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Header ( CORS ) dalam program.
Sertifikat SSL
Anda dapat membuat data DNS untuk domain Anda, misalnya local.example.com, yang akan diselesaikan menjadi 127.0.0.1. Terbitkan sertifikat SSL untuk domain ini, sebarkan dengan program. Anda harus mendistribusikan kunci pribadi sertifikat ini dengan program. Ini sama sekali tidak cocok. Dan sertifikat dalam program ini juga perlu diperbarui.
IE tidak akan mempercayai sertifikat SSL yang ditandatangani sendiri, itu harus ditandatangani dengan sertifikat root tepercaya (dan itu bisa ditandatangani sendiri).
Anda dapat membuat sertifikat root dan sertifikat SSL dan mendistribusikannya dengan program, menambahkan ke toko sertifikat lokal. Itu terlihat tidak aman. Dan mungkin juga perlu untuk mencabut atau memperbarui sertifikat. Oleh karena itu, kami akan membuat sertifikat dengan kunci langsung di komputer pengguna pada awal program.
Membuat Sertifikat dalam C #
Untuk .NET, ada perpustakaan BouncyCastle yang dapat melakukan semua yang kita butuhkan. Satu-satunya masalah adalah bahwa untuk menambahkan sertifikat ke toko, Anda harus meminta peningkatan hak istimewa. Anda juga akan memerlukan hak tinggi untuk menggunakan netsh untuk mengamankan sertifikat ke port tertentu dalam sistem.
netsh http add sslcert ipport=0.0.0.0:{PORT} certhash={certThumbprint}
Dalam contoh ini, metode RegisterSslOnPort di kelas SslHelper melakukan pekerjaan ini.
Layanan HTTP dalam program C #
Untuk membuat server HTTP (S) yang ringan, kami menggunakan pustaka Nancy . Nancy adalah kerangka kerja web yang ringan untuk .NET, sederhana dan mudah digunakan. Banyak yang telah ditulis tentang dia, termasuk tentang HabrΓ© . Berkat modul Nancy.SelfHosting, kita dapat meng-host aplikasi kita tanpa menggunakan IIS.
Misalnya, mari kita buat titik akhir yang berhubungan dengan penambahan dua angka. Penting di sini untuk mengatur tajuk CORS yang benar, jika tidak browser tidak akan menjalankan permintaan ke API kami.
Nancymodule public class CalcNancyModule : NancyModule { public CalcNancyModule() {
Tambahkan inisialisasi Nancy ke aplikasi kita, dan kami siap bertempur.
Inisialisasi Nancy var hostConfigs = new HostConfiguration(); hostConfigs.UrlReservations.CreateAutomatically = true; hostConfigs.RewriteLocalhost = false; var uris = new Uri[] { new Uri($"http://localhost:{HTTPPORT}"), new Uri($"http://127.0.0.1:{HTTPPORT}"), new Uri($"https://localhost:{HTTPSPORT}") }; using (var host = new NancyHost(hostConfigs, uris)) { host.Start(); }
Pada awal pertama, Anda perlu membuat sertifikat dan menempatkannya di toko, meminta hak yang sesuai. Kelas SslHelper digunakan untuk manipulasi ini, di mana satu-satunya metode CheckOrCreateCertificates publik melakukan pekerjaan. Sebagai parameter, sertifikat SubjectName diberikan padanya. Metode ini memeriksa apakah sertifikat yang diperlukan tersedia dan sistem, jika tidak, membuatnya.
Untuk mensimulasikan kerja keras dan penundaan lama dalam contoh, tambahkan Thread.Sleep (1000) ke panggilan API kami.
Pada aplikasi ini siap dijalankan, masuk ke web.
Aplikasi web
Seperti yang dapat Anda lihat dari tabel perilaku browser, satu titik akhir tidak dapat disingkirkan, setidaknya dua harus digunakan:
Dalam aplikasi web, kita perlu menentukan apakah kita berada di IE (atau Edge) - gunakan HTTPS, jika tidak - HTTP. Anda dapat membuatnya lebih andal dan tidak mencari tahu di peramban mana kita berada, tetapi coba saja jalankan permintaan ke metode GET / Calc API kami, jika permintaan berhasil, kami bekerja, jika tidak, kami coba protokol lain.
Semua ini diperlukan hanya jika aplikasi web itu sendiri menggunakan HTTPS, karena ketika menggunakan protokol HTTP, browser tidak memaksakan pembatasan pada permintaan, hanya header CORS yang benar yang diperlukan.
Dalam aplikasi bersudut, buat layanan InteractionService yang akan memeriksa ketersediaan titik akhir lokal terlebih dahulu melalui HTTP, kemudian oleh HTTPS. Pemeriksaan dilakukan dengan metode checkAvailabilitas, dan hasil tes tersedia ketika Anda berlangganan variabel $ tersedia dari tipe BehaviorSubject dengan nilai awal false.
Kami menambahkan pekerjaan menambahkan angka ke komponen AppComponent. Ketika Anda mengklik tombol "Hitung", aplikasi web membuat permintaan untuk GET / Calc / Tambah? Num1 = {num1} & num2 = {num2}. Jawaban atau kesalahan ditampilkan di bidang Hasil.
Saat debugging, bahkan melalui HTTPS, Anda mungkin tidak melihat masalah, karena domain untuk permintaan akan sama - localhost. Karena itu, Anda perlu menguji aplikasi dengan nama domain yang berbeda.
Untuk menyederhanakan pekerjaan menyebarkan aplikasi web sebanyak mungkin, kami menggunakan layanan https://stackblitz.com , ini adalah IDE web untuk sudut dan tidak hanya dengan rasa VSCode. Aplikasi yang sudah selesai tersedia di tautan .
Dan Anda dapat menggali kodenya di sini .
Aplikasi tidak akan bekerja secara interaktif di stackblitz, Anda harus membukanya di tab pribadi yang terpisah, atau di browser lain di https://angular-pfwfrm.stackblitz.io .
Bagaimana cara mencoba?
Aplikasi web dengan mudah diluncurkan menggunakan stackblitz, cukup dengan mengklik tautan https://angular-pfwfrm.stackblitz.io .
Anda dapat menjalankan aplikasi web secara lokal.
Untuk ini Anda perluUntuk melakukan ini, Anda harus mengkloning repositori:
git clone https://github.com/jdtcn/InteractionExample.git cd InteractionExample
di folder AngularWebApp Anda perlu menjalankan perintah:
npm install ng serve --ssl true
Aplikasi web akan tersedia di https: // localhost: 4200 /
Aplikasi lokal dapat dikompilasi dari contoh (buka CsClientApp.sln dari folder CsClientApp) menggunakan Visual Studio dan jalankan, atau gunakan skrip untuk program LINQPad .
Jika Anda adalah pengembang .NET dan tidak menggunakan LINQPad , pastikan untuk membacanya, hal yang sangat diperlukan dalam pengembangan. Untuk menjalankan contoh, Anda perlu membuka skrip di LINQPad'e (pertama kali Anda perlu menjalankan LINQPad dengan hak administrator agar sertifikat diinstal), dan instal paket nouget BouncyCastle, Nancy, Nancy.Hosting.Self, kemudian jalankan skrip. Setelah itu, Anda dapat mengklik tombol "Hitung" di aplikasi web, dan dapatkan hasil operasinya.
Keamanan
Penting untuk dengan benar membentuk header CORS dalam aplikasi nyata sehingga penjahat dari situs lain tidak dapat mengakses program kami. Jika penjahat memiliki kesempatan untuk bekerja dengan hak istimewa pengguna di komputernya dan mem-bypass cek CORS, maka ia akan dapat melakukan semua yang dapat dilakukan oleh program kami.
Bagaimanapun, program harus bekerja dengan hak minimal, dan jika itu melakukan sesuatu yang sensitif dengan dokumen, Anda perlu menambahkan permintaan untuk konfirmasi operasi ke sana.
Kesimpulan
Tugas yang tampaknya sederhana ternyata sangat banyak, dan bahkan membutuhkan kruk tambahan untuk bekerja dengan sertifikat.
Pendekatan ini dilakukan dengan baik dalam aplikasi nyata. Tentu saja, untuk menggunakan kode dari contoh, Anda perlu menambahkan penanganan kesalahan normal.
Lebih mudah untuk meminta peningkatan hak istimewa ketika menginstal program, menggunakan InnoSetup mudah untuk melakukan ini, dan melewatkan atribut yang diperlukan pada menjalankan pertama program. Juga, sebelum menginstal, akan lebih mudah untuk memeriksa keberadaan .NET 4, dan menginstalnya jika tidak diinstal.
Tidak seorang pun di Virustotal bereaksi terhadap program ini, tetapi saya ingin! Tetapi jika Anda merakit paket instalasi di InnoSetup, beberapa antivirus kelas tiga mulai bekerja di sana. Ini membantu menyingkirkan penandatangan pemasang dengan sertifikat penandatanganan kode.
Pembaruan otomatis dari program di sini ada di belakang layar, tetapi tentu saja tidak akan berlebihan dalam aplikasi nyata. Squirrel sangat cocok untuk mengelola pembaruan otomatis. Lebih mudah menggunakan tupai untuk menghapus sertifikat kami dari sistem saat Anda menghapus program.
Kode contoh diposting di GitHub .
Terima kasih atas perhatian anda!