Pembelajaran Mendalam dan Keamanan Berbasis Web Praktis dengan Contoh

DaisyFoto profil

Oleh Daisy

Pembelajaran dan Keamanan Deep Berdasarkan Web Praktis Edisi ketiga Charlotte Harper 3 Juli 2024 Kata pengantar: Pertimbangan keamanan dalam membangun perangkat lunak untuk web adalah bagian penting dari rencana pengembang web dan eksekusi setiap saat merekayasa prototipe yang dapat diandalkan, stabil, dan berguna untuk tujuan praktis. DOM (Markup Objek Dokumen), dengan implementasi HTML, JavaScript, dan CSS serta perangkat lunak backend yang mengimplementasikan Python, C/C ++, Java dan Bash, memberi pengembang web kebebasan dan kekuatan untuk membuat berbagai proyek yang mengekspresikan kreativitas, memberikan kemudahan penggunaan dan fungsionalitas, menggambarkan kerendahan hati dan karakter, dan memberikan kemudahan penggunaan serta kenyamanan dan layanan penting yang semuanya menarik bagi rata -rata Joe, pengguna akhir yang ingin Bunuh waktu atau selesaikan sesuatu di internet, biasanya di perangkat smartphone layar sentuh. Kebanyakan orang bahkan tidak tahu harus mulai dari mana ketika mereka ingin membangun situs web dari awal,Mereka akan cenderung memulai di situs web orang lain dan membangun sesuatu yang terbatas dalam fungsionalitas, ketergantungan, kemudahan penggunaan dan terutama kreativitas ketika mereka dapat memiliki semua alat kuat terbaru yang mereka miliki untuk membangun sesuatu yang berguna tanpa membuang -buang waktu menekan tombol, dan Terutama membuang -buang uang untuk membayar langganan mahal untuk perangkat lunak yang beberapa orang ingin gunakan tetap mengingat keterbatasannya dalam kemudahan penggunaan dan fleksibilitas. Jika Anda memiliki beberapa menit untuk membaca buku ini dan mempelajari apa yang ingin saya ajarkan kepada Anda, atau bahkan berbicara dengan saya secara pribadi tentang tujuan Anda dan mendapatkan beberapa panduan ke arah yang benar, dan termotivasi untuk belajar kode dan menulis perangkat lunak Anda sendiri , bawa pulang buku ini dan sisihkan waktu untuk belajar membangun aplikasi web yang berpengaruh, kuat, ramping, dan penting berikutnya, sebuah situs web yang semuanya ada pada Anda dan melakukan persis seperti yang Anda inginkan dan memenuhi kebutuhan audiens Anda. Tentang saya: Saya seorang pengembang perangkat lunak dengan lebarAnge of Experience dalam C/C ++, Java, Python, HTML, CSS dan JavaScript. Saya membangun situs web yang ingin digunakan orang, ingin berkunjung, dan bahkan kecanduan hanya menggunakan hanya untuk belajar, menciptakan kembali dan menghabiskan waktu, dan yang paling penting, saya menjual perangkat lunak. Jika Anda memiliki ide tentang bagaimana Anda ingin situs web terlihat dan berfungsi, Anda bersedia mendukung saya sehingga saya dapat memenuhi kebutuhan saya sendiri saat saya bertemu dengan milik Anda, dan Anda bersedia menutupi biaya menjalankan situs web sendiri, Saya akan membangun Anda di YouTube berikutnya, Tiktok, Twitter, Google, atau bahkan aplikasi keamanan berteknologi tinggi yang hanya dapat Anda akses. Alih -alih mencoba menjual waktu saya, saya mencoba membeli milik Anda: Saya ingin membujuk Anda untuk membangun aplikasi (situs web) sendiri dengan informasi yang sudah ada, dan mengajari Anda apa yang Anda butuhkan untuk menjadi pengembang perangkat lunak independen, Pengusaha, memimpin karier yang sukses di bidang apa pun yang Anda inginkan. Dan biarkan saya jelas, pendidikan yang saya berikan kepada Anda akan informal. Anda bisa pergi ke sekolah dan mempelajari semua ini dengan aPendidikan rmal, atau bahkan membaca buku ini di sekolah, menyelesaikan tugas Anda, dan mengambil banyak dari pendidikan Anda, tetapi saya tidak akan secara resmi menempatkan Anda di kursi panas dan meminta Anda untuk menyelesaikan tugas. Saya bukan profesor Anda, Anda dapat menganggap saya seperti teman yang ingin membimbing Anda menuju karier yang didorong oleh kesuksesan pribadi Anda. Dan saya juga tidak menjual kesuksesan Anda, Anda perlu membelinya dengan waktu Anda. Belajar kode memiliki kurva belajar yang curam dan tidak pernah mudah, atau bahkan seharusnya. Anda perlu bekerja sekeras mungkin dan terus mencoba dan gagal dan mencoba lagi bahkan ketika Anda frustrasi untuk belajar dan membangun aplikasi sendiri. Itu adalah sifat kode itu sendiri. Kode dijalankan oleh kompiler yang dirancang untuk memberikan pesan kesalahan programmer, dan ini akan mengajarkan Anda cara membuat kode, bahkan jika Anda hanya menyalin kesalahan ke mesin pencari Anda dan membaca contoh orang lain. Dan saya harus mengatakan, Anda tidak perlu menjadi sangat kaya, pintar, sukses,Berorientasi detail atau terorganisir untuk membangun aplikasi. Komputer mengurus organisasi itu untuk Anda. Anda hanya perlu bertahan melalui coba -coba, mempertahankan fokus dan bekerja keras pada apa yang Anda lakukan, dan Anda akan memiliki karier yang sangat sukses secara keseluruhan dari apa yang Anda lakukan. Siapa saya: Saya menyadari bahwa bagian terakhir lebih banyak tentang belajar dan Anda mengambil jalan dari buku ini. Siapa sebenarnya saya? Itu pertanyaan yang rumit. Saya tidak jelas pada diri saya sendiri, karena saya menderita kondisi medis yang dapat menyulitkan saya untuk bahkan membuat kode atau menulis buku ini pada waktu -waktu tertentu, sambil menghadirkan tantangan dengan sosialisasi dan masalah identitas yang membuat hidup saya lebih sulit dalam hal memperkenalkan diri saya . Singkatnya, jika Anda membaca buku ini, Anda membawanya pulang karena Anda membalikkannya dan berpikir itu berguna, atau bahkan jika Anda baru saja membaca sejauh ini, untuk Anda, saya adalah orang yang berpikiran seperti yang ingin melihat Anda berhasil masuk Segala sesuatu yang Anda lakukan. Saya sendiri seorang insinyur, perangkat lunakpengembang, dan seorang siswa, dan saya menulis buku ini untuk siswa lain yang ingin membuat hidup mereka lebih mudah dengan memiliki buku pegangan perangkat lunak yang mereka butuhkan membuat hidup mereka lebih mudah dengan memberikan contoh untuk disalin yang cocok bersama seperti teka -teki besar ke dalam pekerjaan yang berfungsi , aplikasi yang bermanfaat, besar, fungsional, kohesif, dan menarik yang dapat mendorong kesuksesan tidak peduli lini bisnis. Sebagian besar, inilah yang saya lakukan: Saya membangun aplikasi untuk membantu diri saya dan orang lain berhasil. Saya juga seorang penulis, meskipun ini adalah publikasi pertama saya yang ingin saya selesaikan untuk menggabungkan portofolio saya menjadi dokumen yang berguna, dan saya juga seorang seniman. Saya akan mengakui ini untuk Anda, saya semacam orang yang aneh. Saya tidak sempurna, saya telah menjalankan Ins dengan hukum bahkan membuat saya meninggalkan perguruan tinggi dan universitas dan meninggalkan negara bagian untuk mencoba membuat nama untuk diri saya sendiri dengan lebih sukses. Saya seorang wanita sejak lahir, saya memakai riasan, mengambil foto diri saya, memakai gaun dan pakaian wanita lainnya, dan saya tetap sadar akan diri saya sebagai apria secara alami. Saya memiliki masalah dengan orang lain di masa lalu yang mengarah pada perjuangan dengan menulis dan membangun aplikasi web, dan saya minta maaf bahwa saya belum bisa mendapatkan buku ini di tangan Anda lebih cepat: Anda membutuhkan ini. Anda akan ingin membaca dan menulis kode yang terlihat seperti milik saya dan bekerja seperti milik saya dan melakukan hal yang sama tetapi bahkan lebih baik, karena jika Anda mampu membeli buku ini alih -alih menumbuk keyboard Anda seperti yang saya lakukan hanya untuk membuat buku sendiri meminta uang Untuk itu, Anda memiliki sumber daya yang Anda butuhkan untuk sukses dalam hidup Anda. Saya memiliki segala macam masalah dengan keluarga yang tumbuh, kondisi kesehatan, dokter, media, dan hukum, dan kode saya sangat mencerminkan perjuangan yaitu feminisme dan sifat perempuan di dunia yang terpecah dan frustrasi. Namun, buku ini adalah sesuatu yang sangat saya pedulikan, bayi saya, portofolio saya, dan mata pencaharian saya, jadi saya menghargai pertimbangan Anda ketika Anda membawa pulang teks dan dengan hati -hati meneliti untuk belajar dari saya. Harap diingat bahwa saya tidak sempurna,Buku akan memiliki kesalahan, revisi, dan edisi baru, dan Anda perlu berpikir dengan otak logis Anda sebaik mungkin untuk memiliki pengalaman yang sukses dengan tulisan saya. Juga, pahami bahwa saya bermaksud baik untuk Anda bahkan ketika Anda menghadapi tantangan saat menulis. Pikirkan seperti ini: Ketika Anda hanya dapat menyewa sistem komputer untuk melakukan apa pun yang dapat Anda bayangkan di ruang digital, menyimpan semua informasi yang Anda temui, #$%! Yze dan mengaturnya, dan mulai memahaminya, Anda akan melakukannya Tak pelak menghadapi kesulitan dengan informasi yang Anda konsumsi dan bahkan menerbitkan. Saya memberi tahu Anda ini karena saya mengalami kesulitan yang sama. Gunakan buku ini dengan risiko Anda sendiri, bekerja dengan komunitas dan komunitas Anda yang tersedia untuk Anda membangun perangkat lunak dalam pengaturan yang aman, dan jangan mengambil sesuatu untuk secara pribadi ketika Anda gagal atau bahkan berhasil dengan cara yang salah: Begitulah cara saya sampai sejauh ini , dan mengapa saya bisa membawakan Anda teks ini dan membantu Anda berhasil tanpa menyimpang di jalan kegilaan yang meninggalkanSaya hancur, robek, dan keributan sementara saya menemukan masalah biasa yang dilakukan semua orang dalam skala global berkat skala global paralellistic dari jaringan tempat kami akan bekerja, Internet. Anda mungkin tidak terlalu akrab dengan siapa saya hanya dengan beberapa kata, tetapi saya mendorong Anda untuk membaca, Anda akan mengenal saya ketika Anda terus membaca dan memahami saya sambil membangun proyek Anda sendiri untuk menyelesaikan pekerjaan Anda. Tidak akan ada pekerjaan rumah dengan buku ini, selama profesor atau guru Anda tidak memberikan Anda apa pun, tetapi saya sangat mendorong Anda untuk membangun portofolio proyek sendiri saat Anda membaca, serta proyek batu penjuru yang menampilkan bagaimana Anda bisa Terapkan apa yang telah Anda pelajari. Proyek Capstone saya ...
Pembelajaran Mendalam dan Keamanan Berbasis Web Praktis dengan Contoh

Pembelajaran dan Keamanan Deep Berdasarkan Web Praktis Edisi ketiga Charlotte Harper 3 Juli 2024 Kata pengantar: Pertimbangan keamanan dalam membangun perangkat lunak untuk web adalah bagian penting dari rencana pengembang web dan eksekusi setiap saat merekayasa prototipe yang dapat diandalkan, stabil, dan berguna untuk tujuan praktis. DOM (Markup Objek Dokumen), dengan implementasi HTML, JavaScript, dan CSS serta perangkat lunak backend yang mengimplementasikan Python, C/C ++, Java dan Bash, memberi pengembang web kebebasan dan kekuatan untuk membuat berbagai proyek yang mengekspresikan kreativitas, memberikan kemudahan penggunaan dan fungsionalitas, menggambarkan kerendahan hati dan karakter, dan memberikan kemudahan penggunaan serta kenyamanan dan layanan penting yang semuanya menarik bagi rata -rata Joe, pengguna akhir yang ingin Bunuh waktu atau selesaikan sesuatu di internet, biasanya di perangkat smartphone layar sentuh. Kebanyakan orang bahkan tidak akan tahu harus mulai dari mana ketika mereka ingin membangun situs webgoresan, mereka akan cenderung memulai di situs web orang lain dan membangun sesuatu yang terbatas dalam fungsionalitas, ketergantungan, kemudahan penggunaan dan terutama kreativitas ketika mereka dapat memiliki semua alat kuat terbaru yang mereka miliki untuk membangun sesuatu yang berguna tanpa membuang -buang waktu menekan tombol menekan waktu , dan terutama membuang -buang uang untuk membayar langganan mahal untuk perangkat lunak yang beberapa orang ingin gunakan tetap mengingat keterbatasannya dalam kemudahan penggunaan dan fleksibilitas. Jika Anda memiliki beberapa menit untuk membaca buku ini dan mempelajari apa yang ingin saya ajarkan kepada Anda, atau bahkan berbicara dengan saya secara pribadi tentang tujuan Anda dan mendapatkan beberapa panduan ke arah yang benar, dan termotivasi untuk belajar kode dan menulis perangkat lunak Anda sendiri , bawa pulang buku ini dan sisihkan waktu untuk belajar membangun aplikasi web yang berpengaruh, kuat, ramping, dan penting berikutnya, sebuah situs web yang semuanya ada pada Anda dan melakukan persis seperti yang Anda inginkan dan memenuhi kebutuhan audiens Anda. Tentang saya: Saya seorang pengembang perangkat lunak denganRentang pengalaman dalam C/C ++, Java, Python, HTML, CSS dan JavaScript. Saya membangun situs web yang ingin digunakan orang, ingin berkunjung, dan bahkan kecanduan hanya menggunakan hanya untuk belajar, menciptakan kembali dan menghabiskan waktu, dan yang paling penting, saya menjual perangkat lunak. Jika Anda memiliki ide tentang bagaimana Anda ingin situs web terlihat dan berfungsi, Anda bersedia mendukung saya sehingga saya dapat memenuhi kebutuhan saya sendiri saat saya bertemu dengan milik Anda, dan Anda bersedia menutupi biaya menjalankan situs web sendiri, Saya akan membangun Anda di YouTube berikutnya, Tiktok, Twitter, Google, atau bahkan aplikasi keamanan berteknologi tinggi yang hanya dapat Anda akses. Alih -alih mencoba menjual waktu saya, saya mencoba membeli milik Anda: Saya ingin membujuk Anda untuk membangun aplikasi (situs web) sendiri dengan informasi yang sudah ada, dan mengajari Anda apa yang Anda butuhkan untuk menjadi pengembang perangkat lunak independen, Pengusaha, memimpin karier yang sukses di bidang apa pun yang Anda inginkan. Dan biarkan saya jelas, pendidikan yang saya berikan kepada Anda akan informal. Anda bisa pergi ke sekolah dan mempelajari semua ini dengan aPendidikan formal, atau bahkan membaca buku ini di sekolah, menyelesaikan tugas Anda, dan mengambil banyak dari pendidikan Anda, tetapi saya tidak akan secara resmi menempatkan Anda di kursi panas dan meminta Anda untuk menyelesaikan tugas. Saya bukan profesor Anda, Anda dapat menganggap saya seperti teman yang ingin membimbing Anda menuju karier yang didorong oleh kesuksesan pribadi Anda. Dan saya juga tidak menjual kesuksesan Anda, Anda perlu membelinya dengan waktu Anda. Belajar kode memiliki kurva belajar yang curam dan tidak pernah mudah, atau bahkan seharusnya. Anda perlu bekerja sekeras mungkin dan terus mencoba dan gagal dan mencoba lagi bahkan ketika Anda frustrasi untuk belajar dan membangun aplikasi sendiri. Itu adalah sifat kode itu sendiri. Kode dijalankan oleh kompiler yang dirancang untuk memberikan pesan kesalahan programmer, dan ini akan mengajarkan Anda cara membuat kode, bahkan jika Anda hanya menyalin kesalahan ke mesin pencari Anda dan membaca contoh orang lain. Dan saya harus mengatakan, Anda tidak perlu terlalu kaya, pintar,Ester, atau bahkan berorientasi pada detail atau terorganisir untuk membangun aplikasi. Komputer mengurus organisasi itu untuk Anda. Anda hanya perlu bertahan melalui coba -coba, mempertahankan fokus dan bekerja keras pada apa yang Anda lakukan, dan Anda akan memiliki karier yang sangat sukses secara keseluruhan dari apa yang Anda lakukan. Siapa saya: Saya menyadari bahwa bagian terakhir lebih banyak tentang belajar dan Anda mengambil jalan dari buku ini. Siapa sebenarnya saya? Itu pertanyaan yang rumit. Saya tidak jelas pada diri saya sendiri, karena saya menderita kondisi medis yang dapat menyulitkan saya untuk bahkan membuat kode atau menulis buku ini pada waktu -waktu tertentu, sambil menghadirkan tantangan dengan sosialisasi dan masalah identitas yang membuat hidup saya lebih sulit dalam hal memperkenalkan diri saya . Singkatnya, jika Anda membaca buku ini, Anda membawanya pulang karena Anda membalikkannya dan berpikir itu berguna, atau bahkan jika Anda baru saja membaca sejauh ini, untuk Anda, saya adalah orang yang berpikiran seperti yang ingin melihat Anda berhasil masuk Segala sesuatu yang Anda lakukan. Saya sendiri seorang insinyur,pengembang, dan seorang siswa, dan saya menulis buku ini untuk siswa lain yang ingin membuat hidup mereka lebih mudah dengan memiliki buku pegangan perangkat lunak yang mereka butuhkan membuat hidup mereka lebih mudah dengan memberikan contoh untuk disalin yang cocok bersama seperti teka -teki besar ke dalam pekerjaan yang berfungsi , aplikasi yang bermanfaat, besar, fungsional, kohesif, dan menarik yang dapat mendorong kesuksesan tidak peduli lini bisnis. Sebagian besar, inilah yang saya lakukan: Saya membangun aplikasi untuk membantu diri saya dan orang lain berhasil. Saya juga seorang penulis, meskipun ini adalah publikasi pertama saya yang ingin saya selesaikan untuk menggabungkan portofolio saya menjadi dokumen yang berguna, dan saya juga seorang seniman. Saya akan mengakui ini untuk Anda, saya semacam orang yang aneh. Saya tidak sempurna, saya telah menjalankan Ins dengan hukum bahkan membuat saya meninggalkan perguruan tinggi dan universitas dan meninggalkan negara bagian untuk mencoba membuat nama untuk diri saya sendiri dengan lebih sukses. Saya seorang wanita sejak lahir, saya memakai riasan, mengambil foto diri saya, memakai gaun dan pakaian wanita lainnya, dan saya tetap sadar akan diri saya sebagai aperempuan secara alami. Saya memiliki masalah dengan orang lain di masa lalu yang mengarah pada perjuangan dengan menulis dan membangun aplikasi web, dan saya minta maaf bahwa saya belum bisa mendapatkan buku ini di tangan Anda lebih cepat: Anda membutuhkan ini. Anda akan ingin membaca dan menulis kode yang terlihat seperti milik saya dan bekerja seperti milik saya dan melakukan hal yang sama tetapi bahkan lebih baik, karena jika Anda mampu membeli buku ini alih -alih menumbuk keyboard Anda seperti yang saya lakukan hanya untuk membuat buku sendiri meminta uang Untuk itu, Anda memiliki sumber daya yang Anda butuhkan untuk sukses dalam hidup Anda. Saya memiliki segala macam masalah dengan keluarga yang tumbuh, kondisi kesehatan, dokter, media, dan hukum, dan kode saya sangat mencerminkan perjuangan yaitu feminisme dan sifat perempuan di dunia yang terpecah dan frustrasi. Namun, buku ini adalah sesuatu yang sangat saya pedulikan, bayi saya, portofolio saya, dan mata pencaharian saya, jadi saya menghargai pertimbangan Anda ketika Anda membawa pulang teks dan dengan hati -hati meneliti untuk belajar dari saya. Harap diingat bahwa saya tidakdll, buku ini akan memiliki kesalahan, revisi, dan edisi baru, dan Anda perlu berpikir dengan otak logis Anda sebaik mungkin untuk memiliki pengalaman yang sukses dengan tulisan saya. Juga, pahami bahwa saya bermaksud baik untuk Anda bahkan ketika Anda menghadapi tantangan saat menulis. Pikirkan seperti ini: Ketika Anda hanya dapat menyewa sistem komputer untuk melakukan apa pun yang dapat Anda bayangkan di ruang digital, menyimpan semua informasi yang Anda temui, #$%! Yze dan mengaturnya, dan mulai memahaminya, Anda akan melakukannya Tak pelak menghadapi kesulitan dengan informasi yang Anda konsumsi dan bahkan menerbitkan. Saya memberi tahu Anda ini karena saya mengalami kesulitan yang sama. Gunakan buku ini dengan risiko Anda sendiri, bekerja dengan komunitas dan komunitas Anda yang tersedia untuk Anda membangun perangkat lunak dalam pengaturan yang aman, dan jangan mengambil sesuatu untuk secara pribadi ketika Anda gagal atau bahkan berhasil dengan cara yang salah: Begitulah cara saya sampai sejauh ini , dan mengapa saya bisa membawakan Anda teks ini dan membantu Anda berhasil tanpa menyimpang di jalur kegilaanAves saya hancur, robek dan keributan sementara saya menemukan masalah biasa yang dilakukan semua orang dalam skala global berkat skala global paralellistic dari jaringan tempat kami akan bekerja, internet. Anda mungkin tidak terlalu akrab dengan siapa saya hanya dengan beberapa kata, tetapi saya mendorong Anda untuk membaca, Anda akan mengenal saya ketika Anda terus membaca dan memahami saya sambil membangun proyek Anda sendiri untuk menyelesaikan pekerjaan Anda. Tidak akan ada pekerjaan rumah dengan buku ini, selama profesor atau guru Anda tidak memberikan Anda apa pun, tetapi saya sangat mendorong Anda untuk membangun portofolio proyek sendiri saat Anda membaca, serta proyek batu penjuru yang menampilkan bagaimana Anda bisa Terapkan apa yang telah Anda pelajari. Proyek Capstone saya adalah dasar untuk sebagian besar dari apa yang akan Anda baca dalam buku ini, karena menggabungkan kode dari proyek saya sebelumnya, kode yang telah saya buat dan pelajari untuk menulis secara metodis dengan tangan, dan berbagai ide dan tips yang telah membantu saya berhasil ke titik di mana saya dapat memutar aplikasi sederhana itusepenuhnya ditampilkan dan terlihat dan berperilaku seperti aplikasi populer yang mungkin Anda lihat menggunakan teman atau keluarga Anda, di internet, diiklankan kepada Anda, atau dalam berita. Apa buku ini: Buku ini adalah tutorial dengan contoh. Anda dapat menemukan kode di sini, instruksi untuk cara belajar kode, informasi tentang kode debugging dan memperbaiki kesalahan, pemecahan masalah, instruksi tentang cara mencadangkan dan menyimpan kode Anda, menggunakan kembali jika ada yang merusak kode Anda, mengamankan kode Anda, menggunakan Kode Anda, membangun situs web interaktif yang menghibur, menarik, dan membuat ketagihan, dan Anda akan merasakan siapa saya, mengapa ini penting, dan bagaimana memerankan diri Anda, aplikasi dan citra perusahaan Anda, serta citra perusahaan, serta citra perusahaan Anda, serta citra perusahaan Anda, serta perusahaan Perangkat lunak yang Anda bangun dengan cahaya terbaik mutlak untuk menjadi yang paling menarik bagi pengguna akhir Anda, pengunjung situs web Anda. Dalam buku ini, saya akan mendemonstrasikan sejumlah contoh desain perangkat lunak dengan fokus pada web sebagai platform serta keamanan. Kami akan memulai pengalaman belajar dengan membangun dasarOjop Menggunakan shell unix, dengan fitur cadangan dan skrip. Kemudian, kami akan memeriksa situs web blog dasar, meningkatkan blog kami dengan fitur foto dan video serta menggunakan fitur ini untuk menggunakan solusi keamanan menggunakan perangkat lunak gratis, dan mengamankan server kami menggunakan Modul Otentikasi Pluggable (PAM). Kami kemudian akan meninjau penanganan dan pemrosesan file, mengeksplorasi pengeditan video, donasi suara, pemindaian barcode dan pengenalan karakter optik, di antara konsep -konsep lainnya. Sepanjang jalan kami akan memeriksa API yang akan membantu kami membuat perangkat lunak kami lebih berguna dan aman, dengan opsi gratis dan berbayar. Sepanjang jalan, kami akan mengeksplorasi keamanan fisik dan alat militan seperti senjata api dan desain amunisi dan manufaktur termasuk desain barel dan repeater, desain menara dan drone, dan kepala sekolah lainnya yang akan kami integrasikan dengan perangkat lunak kami di jaringan yang ada untuk melindungi perangkat lunak kami dan menunjukkan pertahanan diri dan resillience. Kami akan beristirahat di sepanjang jalan untuk membangun game, 2D dan 3DEngine yang membawakan, dan bekerja dengan perangkat keras tertanam dalam contoh studi kasus perangkat lunak rendering dimensi dasar dan masing -masing pemijat yang bergetar elektronik di karet silikon. Sepanjang jalan, kami juga akan menggunakan solusi pembelajaran mesin yang sudah tersedia untuk lebih mengamankan perangkat lunak kami. Kami juga akan menggunakan alat stok yang tersedia untuk Web untuk merampingkan dan mengamankan proses. Buku ini adalah panduan untuk kesuksesan Anda dalam membangun aplikasi web dan mengintegrasikannya dengan jaringan komputer profesional dan sistem mekanik tertanam, dan secara keseluruhan panduan untuk membangun perangkat lunak dan perangkat keras tertanam tanpa pengetahuan latar belakang atau pengalaman sebelumnya. Buku ini bukan: Jika Anda benar -benar ingin memiliki situs web, Anda bisa membuat toko sederhana dan menjual apa yang Anda butuhkan, memposting blog, memposting foto atau video, atau tanpa pernah menulis satu baris kode. Buku ini bukan itu. Buku ini akan mengajari Anda cara membangun perangkat lunak yang lebih berguna, sepenuhnyaDitampilkan, fungsional dan aman daripada perangkat lunak apa pun yang sudah Anda temukan, karena menggunakan perangkat lunak terbaru yang masih prototipe, mungkin mahal untuk dijalankan pada skala perusahaan yang lebih tua yang beroperasi di, dan tidak menarik untuk mundur, perusahaan berbelit -belit diatur ke menghasilkan uang untuk orang yang tidak benar -benar melakukan apapun. Jika Anda mengikuti buku ini dengan cermat, Anda akan ingin menulis kode, kode penelitian, membangun aplikasi Anda sendiri, dan Anda akan menghasilkan uang dari apa yang Anda lakukan. Saya akan menghasilkan uang dari buku ini, bahkan pada tahap awal, karena berisi informasi yang dibutuhkan orang dan ingin membaca, dan sudah membeli ketika mereka membeli atau menggunakan aplikasi saya. Buku ini tidak akan membangun aplikasi untuk Anda, tetapi itu akan mengarahkan Anda ke arah yang benar dan mempersenjatai Anda dengan alat yang Anda butuhkan dan keterampilan dan tips yang akan memfasilitasi kesuksesan Anda sendiri dalam membangun perangkat lunak untuk web, dengan setiap baris Kode yang perlu Anda tulis sebagai contoh, siap untuk disatukan menjadi perangkat lunak yang Anda dan pendukung, tamu, klien, AndaRiends, keluarga, pengunjung, kontraktor, dan orang -orang di internet ingin menggunakan dan mendukung. Apa yang akan Anda pelajari: Buku ini akan mengajari Anda cara membangun dan menjual perangkat lunak, sangat fungsional, perangkat lunak yang berguna, perekaman media, fitur keamanan seperti pengenalan wajah, pemindaian kode batang zona yang dapat dibaca mesin, API web untuk mengautentikasi, merekam dan membuat video dan foto, dan bertukar pesan seperti Bluetooth dan komunikasi Field Near (NFC). Buku ini akan mengajari Anda cara menggunakan komputer jaringan, dengan fokus pada Debian Linux, cara membangun kode bash untuk membuat pemasangan dan mencadangkan perangkat lunak Anda menjadi angin yang mulus dan otomatis, cara membangun kode python sebagai backend untuk melayani pesan dinamis, gaya Hal -hal dengan baik menggunakan gaya CSS dengan bootstrap, memungkinkan login pengguna dan interaktivitas melalui perangkat jaringan, membangun media interaktif dan jaringan dengan situs web lain untuk menawarkan fitur keamanan seperti pesan teks untuk verifikasi atau lainnya tujuan, pemindaian ID, moderasi gambar dan video, dataRansaksi untuk menjaga perangkat lunak Anda aman, pemrosesan pembayaran, perdagangan cryptocurrency, tugas asinkron, dan banyak lagi. Anda akan belajar cara membangun perangkat Bluetooth Anda sendiri, dengan baterai, pengisi daya, mikrokontroler, sirkuit, motor dan sensor, menggunakan solder, kawat, dan dicetak 3D serta bahan cor. Saya akan mendemonstrasikan prinsip -prinsip desain 3D yang diterapkan pada manufaktur dan alat aditif dan pembuatan die, sehingga Anda dapat memproduksi perangkat perangkat keras tertanam Anda sendiri dengan baterai terintegrasi, pengisi daya, sirkuit elektronik, dan output fungsional. dan jaringan mereka dengan Bluetooth dan Web. Secara khusus, kami akan memeriksa dua studi kasus, pemijat yang bergetar dan senjata api buatan sendiri, keduanya diprogram dalam OpenScad, yang tersedia sebagai antarmuka grafis atau utilitas baris perintah dan dapat diintegrasikan ke dalam web untuk hasil yang lebih cepat. Anda akan belajar cara membangun dan menggunakan situs web dari bawah ke atas tanpa pengalaman sebelumnya, membuatnya fungsional, aman, indah, bermanfaat dan palingpraktis secara mortasi. Anda akan belajar cara menggunakan pembelajaran mesin dan visi komputer untuk membuat situs aman dan lebih praktis, merekam video dan audio dari situs web Anda, menyumbangkan suara Anda, membuat musik dan memodulasi audio untuk membuat sampel yang berguna, dan cara memecahkan kebisingan dengan Memanfaatkan situs web lain untuk membangun jaringan situs web terbaik yang dapat Anda tautkan langsung ke Anda untuk berbagi semua informasi berguna yang Anda tawarkan, dan yang lebih penting membawa orang ke perangkat lunak dan bisnis Anda. Buku ini akan sangat terfokus pada media, keamanan dan pembelajaran mesin, yang merupakan tiga komponen utama yang akan membantu Anda membangun perangkat lunak yang berguna untuk web dengan melibatkan pengguna yang tepat dan melepaskan yang salah dengan cara yang realistis, praktis, Tangan dan menarik sementara juga otomatis, dan kokoh. Buku ini mengajarkan UNIX, khususnya Debian (Ubuntu), Bash Shell, Python, HTML, CSS, JavaScript, dan sejumlah paket perangkat lunak yang berguna untukn Suka permintaan, serta perangkat lunak bash yang berguna seperti Git dan FFMPEG. Saya juga akan mengajari Anda cara menukar cryptocurrency secara otomatis, dan mengambil pembayaran dalam cryptocurrency atau dari kartu debit biasa sambil bahkan membayar pengunjung Anda bagian dari pendapatan Anda jika Anda memilih untuk melakukannya. Saya akan mengajari Anda cara menghasilkan uang dari situs web Anda melalui iklan juga, cara menyiapkan aplikasi Anda untuk mesin pencari dan membuatnya cepat, peringkat peringkat pertama untuk apa yang akan dicari oleh pelanggan Anda untuk menemukan Anda, dan peringkat dalam banyak hal yang umum umum pencarian mungkin. Saya akan mengajari Anda cara menjual perangkat lunak Anda, mengiklankannya, menarik bagi klien yang mencari layanan Anda, dan membuat nama untuk diri Anda sendiri di internet melalui jalan yang sudah ada, murah, dan bekerja dengan baik. Saya akan mengajari Anda cara menyimpan data Anda di komputer cloud yang cocok untuk Anda dan menyimpan data Anda dengan murah, cara merencanakan dan membangun situs web yang melakukan apa yang diinginkan pengguna Anda dan apa yang Anda inginkan, dan bagaimana menjaga pengguna Anda tetap terlibatSitus Anda mengetuk telepon mereka dengan pemberitahuan, email, pesan teks, panggilan telepon, dan lebih banyak jalan untuk membawa pengguna Anda kembali ke situs web Anda yang Anda inginkan di balik klik tombol yang diamankan hanya untuk Anda. Buku ini akan fokus pada kepraktisan menerbitkan dan mendistribusikan media dalam jumlah besar, dari teks ke foto ke video hingga audio, membuat kesan yang baik pada pengguna akhir (klien Anda), dan menjual diri Anda dengan cara apa pun yang Anda lakukan untuk membuat Situs web, aplikasi yang mewakili Anda dan hanya Anda, dan membuat Anda, perangkat lunak dan perusahaan Anda terlihat bagus dengan cara terbaik. Anda juga akan mempelajari beberapa tips dan trik dari saya, dari kiat pengkodean, kesombongan praktis seperti makeup dan fotografi, pemodelan dan akting, dan banyak lagi, yang akan menjadi penting untuk menggambarkan diri Anda dan perusahaan Anda dalam cahaya terbaik menggunakan semua alat yang tersedia yang tersedia kepada Anda sambil mendistribusikan konten sebanyak yang Anda butuhkan di seluruh keseimbangan platform yang sehat untuk membawa AndaE membuahkan hasil tanpa lebih banyak upaya, pekerjaan, atau uang daripada yang diperlukan. Buku ini disebut "Pembelajaran Deep Berdasarkan Web Praktis dengan Contoh" karena suatu alasan: Berurusan dengan pembelajaran dengan kode, khususnya untuk web, khususnya dengan fokus pada keamanan, dari sudut pandang praktis, dengan contoh kode kerja yang berfungsi tujuan praktis yang diuraikan dalam teks. Komponen pembelajaran teks ini juga mencakup pembelajaran mesin, kode yang akan saya tunjukkan cara menjalankan untuk web yang akan menangani visi komputer, pengenalan wajah, moderasi gambar dan video, peningkatan gambar, peningkatan resolusi, captioning gambar, dan tugas -tugas lain seperti lainnya Metrik prediksi yang bersumber dari gambar, seperti sifat gambar sebagai gambar otentik, yang ditransfer komputer, atau salinan optik (foto gambar, atau foto cetak). Pembelajaran mesin sangat penting dalam hal keamanan web dan keamanan perangkat lunak, karena dapat membentuk tugas yang tidak mungkin. Komputer AndaMasuki Anda dengan kode sandi, tetapi mungkin lebih aman untuk menggunakannya jika mencatat Anda dengan wajah Anda. Anda dapat membuat komputer server aman ini, komputer yang biasanya meminta Anda untuk nama pengguna dan kode sandi dan mencatat Anda, mungkin dengan token konfirmasi untuk setiap login baru atau alamat IP baru, tetapi jika Anda sedang membangun skala besar, mudah untuk dilakukan Penggunaan, secara fundamental aman, dan perangkat lunak yang kuat, ini mungkin cukup. Mengikat perangkat lunak Anda terlalu dekat dengan perangkat lunak orang lain, seperti layanan email atau layanan pesan teks, tidak cukup untuk membuat perangkat lunak Anda aman, atau siapa pun (situs apa pun yang Anda gunakan). Siapa pun yang membangun perangkat lunak yang sangat aman memiliki perasaan tentang apa yang disiratkan. Perangkat lunak secara inheren tidak aman karena perangkat dan akun yang kami gunakan untuk mengaksesnya tidak selalu siap membantu kami, mereka bisa berada di tangan siapa pun dengan niat buruk untuk perangkat lunak dan karenanya dapat menimbulkan risiko pada perangkat lunak itu sendiri. Ini adalah sesuatu dari fokus buku ini. Komputer jaringan secara defaultDiamankan dengan token kunci yang panjang, dipanggil dan kunci shell SSH atau aman, dan sebaliknya diamankan dengan server web, karena server web menyediakan akses terbuka serta alat keamanan canggih yang berjalan di server itu sendiri. Server web memiliki akses ke browser web pengguna, yang bisa dibilang bagian paling kuat dari perangkat pengguna, karena itu adalah tempat di mana pengguna dapat mengakses perangkat lunak jaringan. Toolkit ini dapat membuat teks, halaman web yang Anda lihat, dan juga dapat merekam gambar, audio, dan video (seperti foto wajah atau id negara), dapat membaca dan menulis ke perangkat radio Bluetooth, dan dapat membaca dan menulis ke Field Near Field dekat Tag transponder, kartu kunci yang murah, fob, stiker, cincin dan bahkan implan chip dengan nomor seri unik yang dapat dibaca dan ditulis dengan data yang dihasilkan dan divalidasi oleh server web yang terkait dengan situs web. Menggunakan semua alat yang Anda miliki, dengan buku ini Anda akan melengkapi diri Anda dengan pengetahuan untuk membangun situs web yang aman, dan secara keseluruhan aSistem komputer jaringan Ure yang cocok untuk Anda, melakukan penawaran Anda, dan terlihat dan terasa benar. Tempat Memulai: Anda dipersilakan untuk melewati bagian yang saya mulai buku ini, atau bagian mana pun, ke kode yang tepat yang Anda butuhkan, terutama jika Anda memiliki pengalaman dengan pengkodean sebelum atau alat yang disebutkan di atas yang akan saya gambarkan secara rinci dalam buku ini sebagai sebagai serta mendokumentasikan kasus penggunaan dan contoh -contoh praktisnya. Jika Anda tidak memiliki pengalaman dalam menulis kode, saya sangat menyarankan Anda membaca semua buku ini, dan terutama merekomendasikan Anda membaca bagian sebelumnya, untuk memastikan buku ini tepat untuk Anda. Jika buku ini tidak tepat untuk Anda, pertimbangkan untuk memberi hadiah kepada teman atau kerabat yang mungkin tertarik untuk belajar tentang pengembangan web sendiri, dan bahkan mempertimbangkan untuk meminjamnya kembali dan belajar dari mereka untuk mengisi celah di mana saya mengecewakan Anda sebagai a Guru, atau guru lain melakukannya sebelum saya. Mulailah di mana Anda mau, setiap bagian dari buku ini akan berguna jika Anda berniat membangun yang bermanfaatPP, dan pertimbangkan bahwa aplikasi terbaik dibangun dengan mempertimbangkan pengguna akhir: Ketahui pelanggan Anda. Sekarang Anda mengenal saya, Anda tahu buku ini, dan Anda siap untuk memulai. Untuk memulai, ambil komputer (bahkan laptop termurah dari toko kotak, Amazon, atau desktop tua berfungsi, dan mengaturnya dengan cara yang cocok untuk Anda. Cara membaca buku ini: Teks disorot, menunjukkan bahwa teks tersebut termasuk dalam prompt perintah, di mana Anda akan menulis kode yang Anda jalankan. Perintah prompt sangat terfokus keyboard dan membutuhkan sedikit atau tidak ada mengklik, mempercepat alur kerja Anda dan membuat segalanya lebih mudah pada Anda. Memulai: Mari selami. Kita akan mulai dengan membangun kode di mesin lokal dan mulai tanpa membangun situs web yang terhubung ke internet. Ini lebih aman untuk memulai, tidak ada biaya, dan mudah bagi Anda. Bergantung pada sistem operasi Anda, masuk ke shell bash akan sedikit berbeda. Untuk Mac OS, saya sarankan menginstal mesin virtual pada saat ini, karena Anda akan mendapatkan yang paling kompatibilitasmesin virtual. Berbagai penyedia seperti VirtualBox dan Paralells dapat menjalankan mesin virtual untuk Anda, meskipun juga dimungkinkan untuk menginstal Ubuntu secara langsung di mesin, jika Anda lebih suka menggunakan lingkungan asli yang direkomendasikan untuk membuat pengalaman yang cepat dan ramping. Jika Anda menggunakan Linux atau Windows, yang saya rekomendasikan, harus sangat mudah untuk membuat proyek. Buka terminal Anda, sesuaikan ukuran sesuai keinginan Anda, dan mulailah mengikuti langkah 2. Jika Anda menggunakan Windows, silakan ikuti langkah 1. Langkah 1: - Pengguna Windows saja Di Windows, buka command prompt sebagai administrator dan ketik WSL - instalasi Langkah 2: - Lanjutkan di sini, atau lewati langkah 1 ke sini jika Anda tidak menggunakan Windows Di terminal terbuka, (tergantung pada OS Anda, yang disebut Ubuntu di Windows, Terminal di Mac atau Linux, atau nama serupa), mulailah dengan membuat proyek. Kami melakukan ini dengan perintah MKDIR, yang membuat direktori. Jika Anda perlu membuat direktori untuk menyimpan proyek Anda, yang disarankan, gunakanPerintah CD untuk mengubah ke direktori dan dan CD/PATH/TO/Direktori - Path adalah folder (file) yang mendahului direktori tujuan Anda, jalur default Anda adalah ~ atau/home/nama pengguna (di mana nama pengguna adalah nama pengguna Anda). Untuk mengubah ke direktori default, ketik CD atau CD ~ Contoh mkdir - ganti "contoh" dengan nama direktori Sekarang Anda memiliki direktori yang berfungsi untuk proyek Anda. Karena sangat penting untuk disimpan direktori ini jika Anda perlu beralih ke mesin yang berbeda atau menggunakan kode yang Anda tulis sehingga siap untuk web, kami akan membangun skrip untuk mencadangkan direktori Anda dalam beberapa langkah berikutnya. Tetapi membangun skrip membutuhkan sedikit kode, dan kode harus diotomatisasi agar bermanfaat. Jadi mari kita bangun skrip untuk membuat skrip terlebih dahulu. Mari kita mulai dengan membuat skrip dan membuatnya dapat dieksekusi. Kami akan menggunakan sudo, chmod dan sentuhan untuk ini, dan memanggil skrip


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Sekarang kami telah membuat skrip, membuatnya dapat dieksekusi, dan siap mengeditnya. Nano adalah editor teks yang akan memungkinkan Anda mengedit teks tanpa mengklik, yang jauh lebih mudah daripada menggunakan antarmuka pengguna grafis. Untuk mengedit file dengan nano, gunakan nano dan kemudian jalur ke file. Untuk membuat skrip yang membuat skrip, itu cukup mirip dengan membuat skrip kami di tempat pertama. Kami akan menggunakan kode yang sama seperti di atas, mengganti nama skrip, "Ascript" dengan parameter argumen, $ 1. Ini memungkinkan kami memanggil skrip dengan mengetikkan nawit Sudo Ascript, pada titik mana kami dapat membuat skrip baru dengan mengganti "newscript" dengan nama skrip Anda. Kode di Nano seharusnya terlihat seperti:

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
Dan untuk menutup Nano, kita dapat menahan tombol kontrol dan menekan x, lalu y untuk menunjukkan bahwa kita sedang menyimpan file, dan tekan kembali. Sekarang alih -alih mengetik ketiga perintah ini untuk mengedit skrip, kita akan dapat mengetikkan sudo Ascript Ascript untuk mengedit skrip lagi. Ini berhasil! Dan skrip baru apa pun dapat dijalankan dengan mudah dengan menyebutnya di shell. Mari kita simpan pekerjaan kita sekarang: mari kita tulis skrip cadangan untuk menyimpan skrip baru kita dan kemudian mendukungnya di direktori proyek kita, sementara juga mencadangkan skrip cadangan.

sudo ascript backup
Sekarang, di Nano:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Where/Path/To/Directory adalah jalur menuju proyek yang Anda buat dengan MKDIR. Kemudian kita akan belajar cara menyalin jalur berulang seperti ini dengan loop dan daftar, yang lebih sedikit kode, tetapi untuk sekarang mari kita tetap sederhana dan memiliki beberapa baris. Untuk menjalankan skrip ini dan cadangkan kode Anda, simpan file di nano dengan kontrol+x, y dan kembali, dan ketik di bawah ini ke dalam shell Anda

backup
Jika Anda diminta sama sekali untuk kata sandi saat membaca buku ini dan mengikuti di shell, silakan masukkan kata sandi pengguna Anda dengan benar, Anda akan memiliki tiga percobaan sebelum Anda perlu menjalankan kembali perintah. Anda dapat menggunakan panah atas dan bawah untuk menukar perintah dan mengeditnya, jika Anda perlu menjalankan apa pun dua kali. Sederhana tekan naik dan turun sebentar -sebentar untuk memilih perintah, sebelum mengedit perintah dengan kanan, panah kiri dan menghapus tombol serta keyboard, dan menjalankannya dengan kembali. Selamat! Anda berhasil membuat skrip cadangan yang luar biasa yang mencadangkan dua skrip shell penting di direktori kerja Anda. Kita mungkin memindahkan barang -barang nanti karena proyek semakin besar, tetapi ini berhasil untuk saat ini. Mari kita beralih ke cadangan di cloud, kami akan menggunakan GitHub untuk ini (meskipun ada banyak solusi git lainnya untuk cadangan, semuanya hampir sama.) Git adalah perangkat lunak kontrol verision yang memungkinkan Anda mencadangkan pengeditan untuk Anda perangkat lunak saat Anda membuatnya ke server, sementaraJuga memungkinkan Anda untuk mengunduh seluruh salinan perangkat lunak Anda di balik kata sandi atau kunci. Ini sangat berperan dalam menyimpan perangkat lunak Anda, terutama saat kami bermigrasi ke instance Linux yang mengamankan yang terkadang pecah ketika satu baris kode gagal, membuat Anda terkunci sementara kode Anda mungkin tidak dicadangkan jika Anda tidak mendapatkan kesempatan untuk mendukungnya Naik secara otomatis, yang akan kami bahas. Jika Anda belum menggunakan mesin virtual Ubuntu pada saat ini, saya merekomendasikan menggunakan mesin virtual Ubuntu pada saat ini karena itu akan membuat hidup Anda lebih mudah ketika menginstal semua paket yang diperlukan untuk membangun situs web yang berfungsi dan membentuk pembelajaran mendalam yang mendalam Operasi di komputer Anda. Kami akan memindahkan kode ke server web dalam waktu dekat, tetapi kami ingin memastikan ada setidaknya beberapa lapisan keamanan di belakang server web kami yang tahan terhadap phishing, dan menggunakan sejumlah paket Linux untuk dilakukan ini. Jika Anda masih ingin menggunakan Mac OS, Anda dipersilakan untuk mencari dan menginstale Paket yang diperlukan online, tetapi mungkin tidak ada alternatif untuk setiap paket yang akan dicakup buku atau seri ini. Mari kita tambahkan beberapa perintah untuk melakukan pekerjaan kita dengan skrip cadangan dengan menjalankan perintah sudo ascript

# ...
git add –all
git commit -m “backup”
git push -u origin master
Sekali lagi, kontrol x untuk menyimpan. Sekarang kita perlu melakukan konfigurasi satu kali untuk proyek ini. Karena ini akan segera menjadi proyek git, kita tidak perlu mengetik setiap perintah setiap kali kita menggunakan dari repositori git, tetapi kita akan memahami ini ketika kita menulis skrip penyebaran kita. Untuk memulai, mari kita pastikan kita berada di direktori yang tepat dan menginisialisasi repositori git dan menghasilkan tombol SSH.

cd /path/to/directory
git init
git branch -m master
ssh-keygen
Setelah kami mengetik ssh-keygen, kunci baru harus disimpan di folder home di bawah folder yang disebut .ssh. Ini disebut id_rsa.pub. Mari kita temukan kunci ini dan salin. Untuk melihatnya,

cd ~
cat .ssh/id_rsa.pub
Salin teks yang dikembalikan oleh perintah terakhir, dan buat akun dengan penyedia git Anda (idealnya github), sebelum menambahkan kunci ssh ke akun Anda. Setelah Anda memiliki akun, klik menu kanan atas dan masukkan pengaturan, sebelum menambahkan tombol SSH Anda di tombol SSH dan GPG di bawah akses di menu. Pilih Tambahkan Kunci SSH dan tambahkan milik Anda dengan menempelkannya dan memberikannya judul, sebelum menyimpan dan kembali ke GitHub untuk membuat repositori baru. Ini serupa untuk penyedia git lainnya, Anda harus membaca dokumentasi mereka. Dalam konfigurasi repositori baru, berikan nama deskriptif repositori Anda dan putuskan apakah Anda ingin mempublikasikannya, dan pastikan untuk mengkonfigurasi belum ada file untuk dimasukkan. Setelah repositori dibuat, salin klon dengan URL SSH, dan tempel ke perintah berikut.

git remote add git://… (your remote URL)
Sekarang Anda dapat kembali ke repositori Anda dengan CD, Anda akan terbiasa dengan ini. Coba skrip cadangan Anda sekarang dengan cadangan Besar! Sekarang kita benar -benar bisa mendapatkan pengkodean. Mari kita pasang Django sekarang karena kita memiliki pemahaman yang baik tentang bash dan git. Django akan membiarkan kami secara otomatis mendukung perangkat lunak kami, Bash dapat melakukan ini juga tetapi Django harus memiliki implementasi yang lebih aman yang lebih aman (dapat dinonaktifkan dan dikonfigurasi dengan lebih mudah). Untuk menginstal perangkat lunak di Ubuntu, kami akan menggunakan perintah sudo apt-get. Pertama, mari kita perbarui dan tingkatkan perangkat lunak yang sudah kami miliki. Ini dapat dilakukan dengan pembaruan sudo apt-get dan upgrade sudo apt-get -y. Selanjutnya, mari kita menginstal Python dan lingkungan virtual kami, rumah kode kami, dengan perintah berikut: sudo apt-get menginstal python-is-python3 python3-venv Ini semua yang Anda butuhkan untuk pergi dengan Django dalam hal pemasangan perangkat lunak dalam contoh Ubuntu. Untuk Windows dan Linux ini harus cukup mudah, tetapi untuk Mac Anda mungkin ingin menginstal mesin virtual danLinux di atasnya menggunakan lingkungan virtual gratis atau berbayar seperti VirtualBox atau Paralells Desktop dan menciptakan kembali langkah -langkah di atas untuk mengatur lingkungan Ubuntu. Ubuntu sangat penting dalam hal ini karena itu adalah perangkat lunak yang dijalankan situs web dan memungkinkan mereka untuk meng -host situs web dengan semua perangkat lunak yang disebutkan di atas. Mari kita gali ke dalam Django. Di direktori kami lagi, dengan

python -m venv venv # Menciptakan lingkungan virtual di mana kode disimpan
source venv/bin/activate # Mengaktifkan lingkungan virtual
pip install Django
django-admin startproject mysite . # Di mana saya adalah proyek yang saya mulai di direktori saya saat ini.
Django baru saja memulai, karena Django menjadi tuan rumah server web dan melakukan semua yang kita butuhkan untuk menjalankan dan menjalankan situs web lokal. Sekarang setelah kami menginstal Django, mari kita mengedit pengaturan sedikit untuk membuatnya berfungsi seperti yang kita butuhkan. Pertama, mari kita buat aplikasi baru

python manage.py startapp feed
Anda akan melihat aplikasi pertama disebut feed. Aplikasi harus dipanggil apa pun yang Anda suka, dan kami akan membuat aplikasi baru, tetapi nama setiap aplikasi harus konsisten setiap kali aplikasi dirujuk dalam kode. Untuk menambahkan aplikasi baru, kami akan selalu mengedit settings.py di direktori lain aplikasi yang dibuat, dinamai di startProject, selanjutnya aplikasi. Menggunakan nano,

nano app/settings.py
Di pengaturan, temukan installed_apps dan pisahkan [] menjadi 3 baris. Menggunakan empat spasi di garis tengah kosong, tambahkan 'feed', atau nama aplikasi Anda. Bagian dari pengaturan ini. PYPY akan terlihat seperti:

INSTALLED_APPS = [
    'feed',
]
Sebelum kita lupa, mari kita uji bahwa Django bekerja. Menggunakan perintah python kelola.py runserver 0.0.0.0:8000, kita dapat menjalankan server dan kemudian menavigasi di browser web di komputer yang menjalankan kode ke http: // localhost: 8000 dan lihat contoh halaman web (itu berfungsi!) Keluar dari server dengan kontrol C, sama seperti perintah lainnya. Sekarang, mari kita gali menulis beberapa kode Python. Django memiliki tiga komponen utama, semuanya dijalankan dengan kode sepenuhnya. Komponen disebut model, tampilan dan templat, dan masing -masing berada pada level yang lebih tinggi dan lebih rendah masing -masing sebelum halaman web dikirimkan ke pengguna. Model ini adalah kode yang menyimpan informasi dalam database untuk pengambilan, sortasi dan rendering. Tampilan memutuskan bagaimana model ini diberikan, dimanipulasi, dan dimodifikasi, hampir setiap tampilan akan menggunakan model secara langsung. Templat adalah kode HTML dengan beberapa lonceng dan peluit tambahan yang disebut bahasa template. Template diterjemahkan oleh tampilan di mana ia diisi dengan kode python danKonteks seperti model dan informasi (string dan bilangan bulat) dari tampilan. Django juga memiliki komponen lain, termasuk tetapi tidak terbatas pada: Pengaturan, yang mengkonfigurasi aplikasi seperti yang kita bahas. URL, yang merupakan pola yang diikuti pengguna untuk mendapatkan akses ke bagian -bagian tertentu dari aplikasi web. Formulir, yang menentukan bagaimana informasi yang dikirim ke server ditangani dan diterjemahkan ke database serta kepada pengguna. Ini adalah dasar dari pemrosesan informasi di sisi server, dan dapat menerima semua jenis informasi yang disimpan komputer, terutama string teks, angka, dan boolean benar/palsu (biasanya kotak centang). Templat, yang merupakan kode HTML dan bahasa templat dan menjembatani kesenjangan antara Python dan HTML, yang berarti informasi Python dapat dilayani sebagai kode HTML yang dapat diakses siapa saja dan dapat mengamankan situs web dengan akses terbatas, sambil membuat kode python dapat diakses ke web dan berguna untuk berbagai tujuan pada perangkat jarak jauh yang tidakEed berada di dekat server. File statis, yang biasanya merupakan javascript dan perpustakaan yang dilayani dan ditautkan oleh server dengan templat. File media, yang disajikan server atau di -host secara eksternal, atau hanya ditulis ke server sebelum diproses dan diposting ke server lain (ember) untuk hosting. Middleware, yang merupakan potongan kode yang dijalankan pada saat yang sama dengan setiap tampilan dan dianggap "termasuk" dalam tampilan. Prosesor konteks, yang memproses konteks setiap tampilan dan digunakan untuk menambahkan konteks tambahan. Tes, yang memvalidasi bahwa pengguna atau permintaan melewati persyaratan tertentu sebelum tampilan diberikan. Konsumen, yang menentukan bagaimana websockets menangani dan menanggapi komunikasi. Admin, yang digunakan untuk mendaftarkan model sehingga dapat dimanipulasi secara rinci dalam halaman admin Django, di mana basis data dapat dikelola melalui antarmuka grafis. Seledri, yang mendefinisikan tugas -tugas asinkron bagian -bagian dari kode Django dapat dimulaisebelum segera melanjutkan ke tugas atau baris kode berikutnya. Django dapat memiliki banyak komponen lain, yang akan kita bahas secara rinci di sini. Ada banyak cara untuk membuat Django lebih fungsional, menambahkan websockets, yang cepat dan saluran komunikasi ramping, seledri, yang mengeksekusi tugas asinkron, dan banyak perangkat lunak lainnya untuk memperluas Django, terutama dalam fungsi tampilan, di mana sebagian besar dari Kode dijalankan. Fungsi tampilan adalah kunci karena mereka biasanya mendeklarasikan setiap bagian kode yang khusus untuk pola URL tertentu, atau bagian dari server. Pertama, mari kita jelajahi fungsi tampilan. Fungsi tampilan dimulai dengan impor yang menunjukkan kode yang akan digunakan dalam tampilan, dan didefinisikan menggunakan definisi atau kelas fungsi reguler. Tampilan paling sederhana didefinisikan oleh definisi definisi def, dan mengembalikan httprespons dengan templat dasar. Mari kita mulai dengan mendefinisikan pandangan dasar untuk mengembalikan teks "Hello World". Ingatlah bahwa setiap kali Anda menambahkanSetelah pernyataan seperti def, jika, while, for, dll, Anda perlu menambahkan 4 spasi untuk masing -masing definisi sebelumnya yang ingin Anda terapkan pada fungsi Anda. Kami akan membahas apa artinya masing -masing segera. Dari direktori situs kami, edit file feed/views.py menggunakan nano dan tambahkan baris berikut ke ujung

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
HTTPResponse Django merespons dengan string teks, dilambangkan dengan pembukaan dan penutupan '. Setiap kali Anda meneruskan informasi ke fungsi atau kelas, seperti permintaan atau string, Anda perlu menggunakan tanda kurung (, membuka dan menutup). Ini belum semua yang kita butuhkan untuk melihat pandangan kita. Tentu saja, kami belum memberi tahu server di mana tampilan tepatnya, kami masih perlu mendefinisikan jalur yang harus diterjemahkan oleh tampilan. Mari kita mulai dengan mendefinisikan jalur dasar di aplikasi/urls.py, dan kita akan masuk ke grup jalur nanti. Di App/Urls.py, tambahkan baris setelah pernyataan impor setelah awal mengimpor tampilan yang baru saja kami buat.

from feed import views as feed_views
Sekarang, mari kita tentukan pola tampilan. Pola tampilan memiliki tiga komponen, komponen jalur, yang memberi tahu server di mana tampilan ada di dalam server (jalur URL yang pengguna ketik ke bilah navigasi untuk memasukkan halaman web), komponen tampilan tempat tampilan ditentukan, dan a Nama yang ramah untuk tampilan sehingga mudah untuk mengambil polanya saat bekerja dengan templat, terutama sehingga namanya dapat diubah dan diperbarui jika perlu memberi ruang untuk tampilan lain atau mengambil nama yang lebih logis. Masuk akal untuk melakukan hal -hal dengan cara ini dan menjadi fleksibel, karena basis kode Anda akan menjadi lingkungan yang terus berubah yang membutuhkan fleksibilitas dan improvisasi agar berharga dan mudah dikerjakan. Inilah tampilan Anda nantinya, Anda dapat menambahkan ini ke urlpatterns = [bagian aplikasi/urls.py. Pola tampilan didefinisikan dengan tiga komponen yang dijelaskan di atas, dan fungsi yang disebut jalur. Pola URL Anda adalah daftar, jadi pastikan untuk selalu mengakhiri setiap item di dalamnyadengan koma, karena ini memisahkan masing -masing. Setiap item juga harus menggunakan baris baru, sekali lagi dengan empat spasi sebelumnya, seperti aplikasi di settings.py. Kami akan menentukan komponen pertama tampilan dengan fungsi string kosong, untuk membuat tampilan yang berjalan pada direktori root server web. Urls.py Anda sekarang harus terlihat seperti

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Ini adalah dasar untuk membuat situs web dengan Django yang sepenuhnya statis. Untuk membuat situs web yang lebih dinamis di mana kita dapat memulai informasi caching, seperti gambar, video, audio dan banyak lagi, kita perlu menggunakan model, yang akan kita jelajahi selanjutnya. Untuk saat ini, mari kita periksa kode kami dan jalankan server. Untuk memeriksa kode untuk kesalahan, jalankan:

python manage.py check
Jika ada pesan kesalahan, Anda harus dengan cermat meninjau perubahan yang Anda buat ke aplikasi Anda dan melihat apakah ada sesuatu yang perlu diperbaiki, seperti ruang asing atau kurang, karakter tambahan, string yang tidak tertutup, kesalahan ketik apa pun, secara tidak sengaja karakter yang dihapus, atau apa pun. Membaca pesan kesalahan (jika Anda memilikinya), Anda harus dapat melihat jalur ke file yang Anda buat atau edit bersama dengan nomor baris, jadi lihat ke dalam file dan baris itu dan lihat apakah Anda dapat memperbaiki apa pun yang ada di sana . Jika Anda telah memperbaiki masalah, jalankan perintah di atas lagi. Ketika perangkat lunak Anda siap berjalan dan berfungsi, Anda akan melihat output “Pemeriksaan Sistem mengidentifikasi tidak ada masalah.” Sekarang Anda siap untuk pergi. Jalankan server dengan:

python manage.py runserver 0.0.0.0:8000
Sekarang buka browser web dan navigasikan ke http: // localhost: 8000. Anda harus melihat teks yang dikembalikan dalam tanda kurung dan kutipan fungsi HTTPRESPONSE dalam pandangan Anda. Ini hanya contoh dasar, tetapi jika Anda berhasil sejauh ini, Anda memahami dasar -dasar bagaimana Linux, Bash, Python, dan Django bekerja. Mari kita gali lebih dalam dalam beberapa pemodelan basis data, dan jelajahi kekuatan kelas Python dalam menyimpan informasi. Kemudian, kita akan mulai menguasai HTML dan CSS sebelum kita membuat situs kita sepenuhnya ditampilkan, fleksibel, dan aman menggunakan JavaScript dan pembelajaran mesin. Kelas disimpan di model.py aplikasi Anda. Menggunakan nano, edit aplikasi/model.py dan tambahkan kelas baru. Kelas didefinisikan dengan definisi kelas dan disahkan superclass yang diwarisi, dalam hal ini model.model. Nama kelas muncul setelah definisi kelas, dan setelah definisi kelas A: (usus besar) digunakan, sebelum atribut dan definisi fungsi yang terkait dengan kelas dilambangkan di bawah ini. Kelas kamiMembutuhkan ID yang dapat kita gunakan untuk mengambilnya dan membuatnya unik, dan juga membutuhkan bidang teks untuk menyimpan beberapa informasi. Nanti kita dapat menambahkan cap waktu, file, boolean (definisi benar atau salah yang dapat membantu kode kita membuat keputusan tentang apa yang harus dilakukan dengan model, dan dapat digunakan untuk mengurutkannya), instance untuk mengikat model ke pengguna yang dicatat ke server, dan banyak lagi. Mari kita buka paket kodenya

from django.db import models # Impor yang digunakan untuk mendefinisikan kelas kami dan atributnya

class Post(models.Model): # Definisi kelas kita sendiri
    id = models.AutoField(primary_key=True) # ID dari model kami, kunci yang dihasilkan secara otomatis yang akan memungkinkan kami menanyakan model, tetap unik, dan berguna ketika kami perlu berinteraksi dengan model setelah dibuat.
    text = models.TextField(default='') # Atribut toko kelas kami, dalam hal ini, beberapa teks, default ke string kosong.
Tutup dan simpan file seperti yang kami lakukan sebelumnya untuk menyelesaikannya. Ada banyak bidang dan opsi lain yang akan kami jelajahi ketika kami memperbarui kelas ini seiring perkembangan aplikasi kami, tetapi ini adalah kebutuhan dasar untuk membuat aplikasi untuk memposting beberapa teks. Namun, model ini tidak akan bekerja sendiri. Seperti yang dijelaskan sebelumnya, kami akan membutuhkan tampilan khusus dan pola URL khusus untuk membuat model ini berfungsi, dan kami juga membutuhkan formulir bersama dengan templat. Mari kita jelajahi formulir terlebih dahulu. Untuk mendefinisikan formulir, edit aplikasi/forms.py dengan nano dan tambahkan baris berikut. Kami akan membutuhkan dua impor, kelas formulir kami, serta model yang kami buat (feed.models.post), definisi kelas yang mirip dengan model, dan bidang bersama dengan subkelas yang disebut meta yang akan menentukan model yang berinteraksi berinteraksi dengan. Formulir ini juga dapat memiliki fungsi inisialisasi yang mengaturnya berdasarkan informasi dalam permintaan, model atau sebaliknya, kami akan mengeksplorasi ini nanti. Bentuk model sangat berguna karena mereka dapat membuat model atau juga mengedit model,Jadi kami akan menggunakannya untuk keduanya. Mari kita tentukan satu di forms.py

from django import forms
from feed.models import Post

class PostForm(forms.ModelForm):
    text = forms.CharField(widget=forms.Textarea)
    class Meta:
        model = Post
        fields = ('text',)
Ini adalah dasar dari seperti apa bentuk dan model itu. Bentuk model ini dapat digunakan untuk membuat instantiate atau mengedit posting, mengubah teks yang dikandungnya. Kami akan melihat mengintegrasikan formulir ini ke dalam tampilan berikutnya. Pertama, mari kita buat migrasi dan migrasi database sehingga kode kita dapat berinteraksi dengan model saat berjalan. Untuk melakukan ini, jalankan perintah berikut:

python manage.py makemigrations
python manage.py migrate
Ini akan memakan waktu satu menit untuk dieksekusi, tetapi begitu terjadi, itu akan memungkinkan Anda untuk mengakses model di tampilan, middleware, atau di mana pun di perangkat lunak. Mari kita lanjutkan dengan membuat tampilan di mana kita dapat melihat model kita. Edit feed/views.py dan tambahkan kode berikut, sebagaimana dicatat. Anda tidak perlu menambahkan apa pun setelah tanda #, kode itu adalah komentar yang digunakan untuk menunjukkan informasi tentang kode tersebut. Kami akan mulai dengan mengimpor model kami dalam tampilan, dan menambahkannya ke konteks di mana kami dapat menjadikannya dalam templat sebagai daftar untuk ditampilkan. Selanjutnya, kami akan menambahkan templat di mana kami dapat membuat formulir dan model dengan tombol untuk membuat objek baru berdasarkan model dan mempostingnya ke server. Ini kedengarannya rumit, jadi mari kita ambil langkah demi langkah. Sebelum kita menyelesaikan tampilan, mari kita buat templat yang hanya membuat model dan pastikan kita dapat melihatnya dengan membuat posting baru di shell. Beginilah tampilan itu seharusnya:

from feed.models import Post
from django.shortcuts import render, redirect
from django.urls import reverse

def feed(request):
    posts = Post.objects.all() # Permintaan semua posting dalam database sejauh ini
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })
Ini semua terlihat sangat sederhana sampai kita sampai ke bawah. Render, nilai yang dikembalikan oleh fungsi alih -alih dalam respons HTTP seperti contoh sebelumnya, selalu mengambil permintaan sebagai input pertama, menerima konteks (dalam hal ini posting dalam database), yang sekarang dapat diterjemahkan dalam templat , dan mengembalikan templat yang ditentukan dalam fungsi. Templat akan menjadi dokumen HTML dengan sedikit bahasa yang disebut Jinja2, yang menjadikan informasi Python ke dalam HTML. Untuk mulai membuat template, buat dua direktori dalam feed.

mkdir feed/templates
mkdir feed/templates/feed
Selanjutnya, edit templat di direktori di atas, umpan/templat/pakan, dan tambahkan kode untuk contoh ini. Mari kita lihat templat untuk contoh ini.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Ini adalah templat yang sangat sederhana. Ini mendefinisikan pembukaan dan penutupan tag HTML, tag tipe dokumen, tag tubuh dengan judul legenda, tag istirahat yang menambahkan garis kecil di layar, dan loop yang membuat setiap posting dalam daftar posting sebagai paragraf di template. Hanya ini yang diperlukan untuk membuat posting, tetapi belum ada dalam database. Mari kita buat beberapa dengan shell. Kita bisa menjalankan shell dengan kelola.py

python manage.py shell
Sekarang, mari kita impor model posting kita

from feed.models import Post
Selanjutnya, kami akan membuat posting sederhana dengan string dan keluar dari shell. String bisa apa saja, selama itu teks yang valid.

Post.objects.create(text='hello world')
exit()
Terakhir, kita perlu menambahkan pola URL ke pakan kita. Karena aplikasi umpan kami akan menggunakan beberapa URL dan kami ingin menjaga ukuran file kecil, mari kita buat URLS lokal di aplikasi feed kami yang terlihat seperti ini:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
Kami juga perlu mengedit urls.py di aplikasi dasar, apa pun yang kami putuskan untuk menyebutnya, ini adalah direktori pertama yang kami buat. Edit aplikasi/app.py dan tambahkan yang berikut ini ke pola URL

from django.urls import include # di atas

urlpatterns = [
    # ... kode sebelumnya di sini
    path('feed/', include(('feed.urls'), namespace='feed')),
]
Sekarang, ketika kami menjalankan server dengan python manager.py runserver, kami akan melihat halaman yang kami buat karena kami memiliki model, tampilan dan templat serta pola URL, bersama dengan item dalam database. Selanjutnya, mari kita terapkan formulir yang kami buat dan mulai membuat posting kami sendiri. Tetapi sebelum kita menulis terlalu banyak kode, mari kita buat cadangan menggunakan skrip yang kita tulis sebelumnya, cadangan. Jalankan skrip ini di shell, tunggu beberapa saat, dan semua kode akan didukung ke repositori git kami.

backup
Menerapkan formulir relatif sederhana. Kami akan mengimpor formulir kami, menambahkan penangan permintaan pos ke tampilan, dan menyimpan pos di database sebelum mengarahkan ulang ke tampilan yang sama. Kita dapat menggunakan fungsi pengalihan yang sudah kita impor, dan fungsi lain yang disebut terbalik untuk mendapatkan URL untuk pola tampilan. Kami akan menanyakan ini dengan string 'feed: feed' karena namespace dari pola yang disertakan adalah umpan, dan pandangan juga disebut feed.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Permintaan semua posting dalam database sejauh ini
    if request.method == 'POST': # Tangani Permintaan Posting
        form = PostForm(request.POST) # Buat instance formulir dan simpan data untuk itu
        if form.is_valid(): # Validasi formulir
            form.save() # Simpan objek baru
        return redirect(reverse('feed:feed')) # Redireksi ke URL yang sama dengan permintaan GET
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # Pastikan untuk meneruskan formulir ke dalam konteks sehingga kita dapat membuatnya.
        'posts': posts,
    })
Sekarang, kita perlu memperbarui templat untuk memperhitungkan formulir baru. Kita bisa melakukan ini dengan menggunakan
Tag dalam html dan render formulir di template html dengan tombol kirim. Kami juga akan membutuhkan token CSRF, token yang mencegah situs eksternal dari posting ke formulir tanpa terlebih dahulu memuat halaman.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<form method=”POST”>
{% csrf_token %}
{{ form }}
<button type=”submit”>New Post</button>
</form>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Mari kita hancurkan ini. Ada kelas bentuk baru, token, formulir itu sendiri, dan tombol kirim. Cukup sederhana, tetapi ketika kita melihatnya, kita mungkin ingin membuatnya terlihat lebih baik. Ini berfungsi, kami dapat memposting posting baru dengan formulir dan sekarang disimpan dalam database. Ada beberapa hal yang terjadi di sini. Kami menggunakan tag HTML untuk menyatakan bahwa dokumen tersebut adalah dokumen HTML, kami menggunakan tag template ({ % ... %}) untuk membuat token untuk formulir, dan yang lain, {{...}} untuk membuat formulir. Kami juga memiliki loop untuk membuat teks menggunakan tag blok dan tag template. Tag blok sangat penting karena kita dapat menentukan bagaimana bagian dari template diterjemahkan dengan mereka, dan tag template adalah dasar dari bagaimana kita memasukkan variabel ke dalam kode kita. Sekarang kita perlu membuat aplikasi kita terlihat lebih baik, karena untuk saat ini terlihat sangat mendasar. Kita dapat melakukan ini dengan menggunakan CSS, baik inline, atau di kelas yang terikat pada setiap objek dalam dokumen. CSS sangat bagus karena menceritakan semuanya di halaman bagaimana kelihatannya,Dan bisa membuatnya terlihat sangat bagus. Ada beberapa perpustakaan yang dapat melakukan ini, tetapi orang saya pergi adalah Bootstrap. Bootstrap dapat diunduh dari situs web mereka,getbootstrap.com/. Sesampai di sana, tekan tombol untuk membaca dokumen instalasi, dan salin kode dari bagian include via CDN. Anda akan memerlukan kode ini di bagian atas dokumen HTML Anda, dalam tag yang disebut head. Juga, mari kita lanjutkan dan buat template dasar sehingga kita tidak perlu membuat ulang tautan ini di setiap templat. Buat direktori baru yang disebut templat dengan template mkdir, dan kemudian edit templat/base.html. Seharusnya terlihat seperti ini:
 
<!doctype HTML>
<html>
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
 
Pastikan untuk menyalin file CSS dan JavaScript, file .css dan .js, karena kami akan membutuhkan JavaScript untuk membuat situs kami lebih fungsional di masa mendatang. Sekarang, mari kita kembali ke shell bash dan jalankan perintah cepat. Ingat, jika Anda perlu mengakses lingkungan virtual, ketik sumber venv/bin/aktifkan. Ini akan memungkinkan Anda menginstal paket Python secara lokal dengan cara yang memungkinkan Django mengaksesnya. Untuk memberikan formulir kami yang dihasilkan oleh kelas bootstrap Django, kami akan menggunakan paket Python yang disebut Formulir Crispy. Kami dapat mengunduh ini dengan perintah berikut

pip install django-crispy-forms
Setelah ini diinstal, tambahkan ke settings.py

INSTALLED_APPS = [
    # … Kode sebelumnya di sini
    'crispy_forms',
]
Sekarang, kembali ke template umpan kami, kami dapat menghapus beberapa hal. Mari kita hapus awal dan akhir dokumen dan ganti dengan warisan dari templat dasar kita, menggunakan Extends dan definisi blok. Juga, kami akan menambahkan impor filter templat dengan beban dan filter templat ke formulir. Terakhir, mari kita tambahkan kelas bootstrap ke tombol pada formulir agar terlihat lebih seperti tombol. Itu seharusnya terlihat seperti ini:
 
{% extends 'base.html' %}
{% block body %}
{% load crispy_forms_tags %}
<form method=”POST”>
{% csrf_token %}
{{ form|crispy }}
<button type=”submit” class=”btn btn-outline-primary”>New Post</button>
</form>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
{% endblock %}
 
Cantik! Itu sudah sedikit kode. Selanjutnya, kita harus mengujinya dan memastikan kita dapat melihat bahwa semuanya terlihat bagus, dan juga pastikan semuanya berfungsi dengan baik. Jalankan server sesuai instruksi sebelumnya dan pastikan situsnya terlihat dan berfungsi dengan baik. Kerja bagus! Anda siap untuk melanjutkan ke langkah berikutnya, di mana kami akan menambahkan fungsi login pengguna menggunakan URL, formulir, tampilan, dan templat yang serupa. Template dasar penting, dan kami akan terus memodifikasinya dan membuat perubahan sesuai kebutuhan, tetapi untuk sekarang mari kita fokus membuat situs kami lebih aman, dengan memungkinkan pengguna untuk masuk dengan nama pengguna dan kode sandi, dan pada akhirnya bahkan lebih penting informasi yang lebih penting yang itu yang lebih penting itu yang lebih penting itu yang lebih penting itu yang lebih penting itu yang lebih penting itu yang lebih penting itu yang lebih penting Akan membantu menjaga aplikasi Anda tetap aman dan akun Anda sendiri hanya dapat diakses oleh Anda. Untuk melakukan ini, kita perlu menggunakan model pengguna yang dibangun ke dalam Django. Model pengguna adalah model database, seperti posting kami, yang dapat diterjemahkan untuk mencatat pengguna ke situs web. Di masa depan, sebelum kami menggunakan situs ke internet, kami akan melakukannyaPerluas model ini dengan model lain yang dikaitkan dengannya, dan bangun langkah -langkah keamanan tambahan untuk login yang resisten terhadap phishing. Kami akan mulai dengan menggunakan beberapa formulir login bawaan yang disediakan Django. Pertama, mari kita buat aplikasi baru yang akan kita gunakan untuk membuat templat dan tampilan untuk halaman login dasar. Kami juga akan membuat aplikasi lain untuk mewakili tantangan login yang berkelanjutan untuk mengamankan aplikasi, termasuk pincode, pengenalan wajah, komunikasi lapangan dekat, perangkat eksternal, otentikasi multi -faktor, dan pengenalan sidik jari. Kami sudah berbicara tentang memulai aplikasi. Dari direktori kami, di dalam lingkungan virtual, lulus kelola.py ini

python manage.py startapp users
Sekarang, kita harus memiliki direktori untuk aplikasi baru. Mari kita mulai dengan membuat tampilan di direktori yang sesuai dengan login pengguna. Django telah membangun tampilan untuk login pengguna, tetapi ini tidak akan cocok untuk kita karena kita membutuhkan tampilan khusus, yang lebih disukai dilakukan dengan definisi. Dalam tampilan ini, kami akan mulai dengan memeriksa permintaan POST, lulus permintaan. Di pengguna/views.py, tambahkan kode berikut

from django.shortcuts import render, redirect
from django.urls import reverse
from django.contrib.auth.forms import AuthenticationForm, SetPasswordForm
from django.contrib.auth import authenticate, logout
from django.contrib.auth import login as auth_login
from django.contrib import messages

def login(request):
    if request.method == “POST”:
        username = request.POST['username'] # Dapatkan nama pengguna dan kata sandi dari permintaan posting
        password = request.POST['password'] # Mengotentikasi pengguna
        user = authenticate(username=username, password=password)
        if user:
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.success(request, 'Your password was accepted. Please continue')
            return redirect(reverse('feed:feed'))
        else: messages.warning(request, 'Username or password incorrect. Please try again')
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Ini semua yang Anda butuhkan untuk tampilan login dasar. Sekarang, mari kita buat formulir untuk tampilan dengan memperluas template dasar. Kami akan mulai dengan membuat direktori baru untuk templat di folder pengguna.

mkdir users/templates
mkdir users/templates/users
Sekarang, kita harus dapat mengedit pengguna/templat/pengguna/login.html. Sementara kami melakukannya, kami akan membuat templat untuk memungkinkan pengguna juga mendaftar.

nano users/templates/users/login.html
Sekarang, di template,
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST">
    {% csrf_token %}
    <fieldset class="form-group">
        <legend class="border-bottom mb-4 break">Log In</legend>
        {{ form|crispy }}
    </fieldset>
    <div class="form-group">
        <button class="btn btn-outline-info" type="submit">Login</button>
    </div>
</form>
{% endblock %}
 
Ini adalah dasar -dasar templat login. Ini benar -benar seperti templat lain dalam struktur, tetapi terlihat sedikit berbeda ketika diterjemahkan. Kami dapat menyalin kode ini untuk membangun templat lain yang sangat mirip yang disebut register.html, di mana kami akan mengubah kata -kata dan menggunakan formulir baru yang kami bangun. Mari kita buat template dulu. Edit pengguna/templat/pengguna/register.html dan tambahkan kode berikut:
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST">
    {% csrf_token %}
    <fieldset class="form-group">
        <legend class="border-bottom mb-4 break">Create an account</legend>
        {{ form|crispy }}
    </fieldset>
    <div class="form-group">
        <button class="btn btn-outline-info" type="submit">Register</button>
    </div>
</form>
{% endblock %}
 
Sekarang, mari kita bangun formulir untuk pendaftaran pengguna kami dan lingkari kembali ke tampilan sebelum kami meningkatkan login pengguna kami dengan model. Kami akan membuat formulir ini dasar untuk memulai, tetapi menggabungkan lebih banyak detail dan fitur keamanan seperti perjanjian dan captcha di masa depan. Edit formulir dengan pengguna nano/forms.py, dan tambahkan kode berikut.

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()

    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']
Jadi kami memiliki formulir lain di sini, yang berfungsi cukup sederhana. Ini adalah formulir daftar pengguna dengan nama pengguna, email dan kata sandi, serta bidang kata sandi konfirmasi. Perhatikan bahwa formulir ini tidak memperpanjang formulir reguler. Kelas bentuk, ini adalah bentuk model yang berarti memiliki meta. Satu bidang didefinisikan sama, dan meta kelas mendefinisikan model formulir sesuai dengan sisa informasi yang akan ditulis ke formulir. Sebagian besar sudah ada di Django yang dibangun di UserCreationForm, jadi kami akan menggunakannya sebagai dasar untuk kelas (diteruskan dalam tanda kurung). Selanjutnya, kami akan memeriksa tampilan untuk mendaftarkan pengguna, sekarang kami memiliki formulir dan templat. Ini adalah modelform, seperti yang ada di tampilan posting baru. Edit pengguna/views.py dan tambahkan kode berikut:

# ... jumlah
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Hanya ini yang kita butuhkan untuk mendapatkan pengguna yang terdaftar, tetapi kita harus memiliki lebih banyak informasi. Kami ingin mengetahui waktu yang didaftarkan pengguna, jam berapa mereka terakhir di situs, beberapa informasi tentang mereka, seperti biografi, zona waktu, dll. Kami juga perlu memperbarui model umpan kami, memposting, untuk memperhitungkan pengguna Model dan Posting Atribut untuk Setiap Pengguna. Untuk melakukan itu, kami akan memperbarui model.py di kedua aplikasi. Mari kita mulai dengan mengedit model umpan. Ini seharusnya terlihat seperti ini sekarang:

from django.db import models # ... jumlah
from django.contrib.auth.models import User

class Post(models.Model):
    id = models.AutoField(primary_key=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name='posts') # Tambahkan baris ini
    text = models.TextField(default='')
Perhatikan baris kedua yang ditambahkan ke file. Ini adalah kunci asing, yang akan mengaitkan setiap posting dengan satu pengguna per posting, sehingga kami dapat memastikan bahwa kami menyimpan posting berdasarkan pengguna per pengguna dan tidak ada posting yang dapat dilakukan tanpa menghubungkannya dengan pengguna. Kami mendefinisikan kunci asing ini dengan kelas yang diwakilinya, argumen penghapusan untuk memastikan posting dihapus dengan pengguna, nol dan argumen kosong untuk memastikan kami dapat menghapus pengguna jika perlu, dan untuk mengakomodasi kurangnya pengguna pada posting kami sudah kami sudah sudah kami sudah lama miliki dibuat, dan nama terkait, yang dapat kita gunakan untuk merujuk ke objek posting yang dibuat pengguna. Nama terkait ini, tidak seperti Post.Author, penulis posting, memberi kami pengguna yang memposting posting itu sendiri. Kami sekarang dapat mendapatkan posting yang dibuat pengguna dengan menjalankan user.posts.all (), atau worit.posts.all (). Sekarang, mari kita buat login kita lebih tangguh. Kami sudah dapat membuat situs kami jauh lebih rentan terhadap phishing dengan hanya memberi tingkat yang membatasi berapa kali kami akan mengizinkan login keSitus, ini cukup mudah. Mari kita juga mulai menyimpan beberapa informasi tentang setiap pengguna sebelumnya karena kami terus mengembangkan aplikasi kami. Mengedit pengguna/model.py, tambahkan yang berikut ini

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name='profile')
    account_created = models.DateTimeField(default=timezone.now)
    last_seen = models.DateTimeField(default=timezone.now)
    can_login = models.DateTimeField(default=timezone.now)
    preferred_name = models.CharField(max_length=20,default='', null=True, blank=True)
    bio = models.TextField(blank=True, default='')
Perhatikan bahwa model ini cukup mirip dengan model POST. Kami memiliki impor tambahan, TimeZone, yang akan memungkinkan kami untuk menetapkan default di bidang DateTime, dan kami juga memiliki karakterfeild dan textfield seperti posting. Menggunakan semua cap waktu ini membantu kami mengamankan situs dan memahami penggunaannya, dan bidang teks memungkinkan kami memberikan informasi tentang setiap pengguna, atau penulis, di situs web. OneToonefield harus menjadi satu -satunya pertimbangan kecil, itu berperilaku persis sama dengan ke depan tetapi dengan hanya satu model selanjutnya. Dengan cara ini, pengguna hanya memiliki satu profil, sementara mereka mungkin memiliki banyak posting. Sekarang, mari kita tingkatkan login kami dan daftarkan tampilan untuk memperhitungkan profil. Pertama, edit pengguna/views.py dan fokuslah pada tampilan register:

# ... jumlah
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            Profile.objects.create(user=user) # Pastikan untuk menambahkan baris ini, untuk membuat profil untuk pengguna
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Ini hanya membuat profil untuk pengguna, tanpa mengisi informasi apa pun. Sekarang, kami ingin memastikan akun pengguna tidak dapat terlalu sering masuk, atau setidaknya kata sandi tidak dapat dicoba terlalu sering, jadi mari kita perbarui tampilan login.

# ... jumlah
from .models import Profile
from django.utils import timezone
import datetime

def login(request):
    if request.method == “POST”:
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user and user.profile.can_login < timezone.now(): # Perhatikan bahwa kami sekarang memeriksa apakah pengguna dapat masuk
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.success(request, 'Your password was accepted. Please continue.')
            return redirect(reverse('feed:feed'))
        else: # Jika login tidak berhasil,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Ini adalah bagian di mana kami memperbarui profil pengguna
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Jadi mereka tidak bisa masuk lagi selama beberapa detik
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Ini adalah dasar dasar keamanan. Pastikan situs tidak rentan terhadap seseorang yang hanya mencoba setiap kombinasi kata sandi yang mungkin, atau bahkan beberapa di antaranya pada saat yang sama. Ini tidak akan membuat frustasi bagi pengguna biasa yang mengetahui kode sandi mereka dan hanya masuk pada beberapa perangkat, tetapi itu akan membuat banyak robot phishing keluar dari aplikasi. Perhatikan bahwa kami menambahkan pernyataan IF dengan variabel, can_login, yang seharusnya menjadi waktu di masa lalu, dan memperbarui dengan masing -masing login yang gagal menggunakan nama pengguna yang sama. Dengan cara ini, pengguna jahat tidak akan bisa menebak kata sandi di mana pun dengan cepat. Jumlah detik dalam datetime.timedelta () juga dapat diperbarui, dan situs web akan lebih tangguh namun sedikit kurang dapat digunakan dengan lebih banyak detik. Saya merekomendasikan 15 untuk memulai. Ingat, kami membangun skrip cadangan untuk menyimpan karya kami, jadi mari kita lanjutkan dan mendukung apa yang kami miliki sejauh ini untuk memastikan kami memiliki segalanya yang disimpan. Jalankan perintah:

sudo backup
Sekali lagi, ini akan menyimpan pekerjaan Anda sejauh ini. Saya sarankan menjalankan cadangan yang sering untuk menyimpan pekerjaan Anda, dan Anda bahkan mungkin ingin menjalankan pekerjaan cadangan secara otomatis. Anda dapat melakukan ini dengan menggunakan utilitas UNIX yang disebut Cron. Untuk mengaktifkan utilitas ini, jalankan perintah berikut dan masukkan kata sandi Anda:

sudo crontab -e
Jika Anda belum memilih Opsi 1 untuk Nano, editor teks yang harus Anda kenal, dan gulir ke bagian bawah file menggunakan tombol panah. Tambahkan baris berikut:

0 * * * * sudo backup
Cron menggunakan format menit, jam, hari bulan, bulan, hari dalam seminggu, di mana A * atau angka mewakili kapan harus menjalankan perintah. Menggunakan 0 untuk menit dan * untuk sisa opsi, kami dapat menjalankan perintah pada menit pertama setiap jam di awal menit. Ini memungkinkan kami mendukung kode secara otomatis. Semua pekerjaan Cron ketika dieksekusi dengan sudo berjalan sebagai root, jadi kita tidak perlu mengetikkan kata sandi setiap jam. Untuk membuatnya lebih mudah untuk mencadangkan kode kami tanpa menggunakan kata sandi, mari kita nonaktifkan kata sandi untuk perintah cadangan kami. Kami akan melakukan ini dengan menjalankan perintah berikut dan memasukkan kata sandi:

sudo visudo
Sekarang, mari gulir ke bagian bawah file dan tambahkan baris lain:

ALL ALL=NOPASSWD: /bin/backup
Ini memungkinkan kami menjalankan perintah "cadangan" sebagai pengguna mana pun, tanpa kata sandi. Format untuk ini mudah, cukup awalkan garis dengan “all semua = nopasswd:/bin/” dan akhiri dengan perintah, misalnya/bin/cadangan, yang ada di/usr/bin/. Sekarang, mari kita mulai bekerja dengan email. Email sangat penting untuk situs web, karena ini cara untuk menjaga situs web lebih aman, memverifikasi pengguna adalah orang sungguhan, dan bahkan memasarkan produk atau layanan kepada pelanggan. Banyak orang yang sering mengunjungi internet memeriksa email mereka setiap hari, dan menerima segala macam email pemasaran tentang produk dan layanan yang mereka minati. Ada beberapa opsi dalam hal memungkinkan email di situs web Django, dan Anda dipersilakan untuk memilih mana yang paling cocok untuk Anda. Pertama, Anda dapat membayar layanan email yang akan memungkinkan Anda untuk mengirim email dari domain Anda dan membutuhkan kode minimal. Ada banyak layanan yang menawarkan ini, seperti Google Workspace, SendinBlue, Mailgun, dan banyak lagi. Kalau tidak, Anda sedang bangun dengan baikLayanan email Anda sendiri di dalam server Anda dari awal. Saya merekomendasikan opsi ini, meskipun lebih banyak kode dan mungkin memerlukan hosting khusus. Anda tidak akan dapat memulai server surat dari komputer rumah Anda kemungkinan besar, jadi mari kita lanjutkan dan periksa konfigurasi dan kode untuk mengirim email sebelum kami memulai server di cloud dan membuat server surat kami sendiri di dalam. Pertama, edit settings.py dengan yang berikut

nano app/settings.py
Di mana aplikasi adalah nama aplikasi yang Anda buat dengan StartApp. Tambahkan baris berikut:

SITE_NAME = 'Django App'

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = username@server.com'
EMAIL_HOST_USER = 'username'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
Pastikan untuk mengubah ini saat Anda siap untuk menggunakan aplikasi Anda, kami akan meninjau kembali ini nanti. Pengaturan email_address harus berupa email yang ingin Anda kirim, dan kata sandi (email_host_password) harus disetel ke kata sandi yang Anda hasilkan untuk server. Saya memuat kata sandi dari file konfigurasi untuk menjauhkannya dari kode menggunakan logika berikut, di atas baris ini di settings.py:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Kemudian, saya telah mengatur file JSON dengan konfigurasi di /etc/config.json menggunakan nano sebagai berikut. Untuk mengedit file:

sudo nano /etc/config.json
Tambahkan baris berikut:

{
	“EMAIL_HOST_PASSWORD”: “<some password here>”
}
Kami akan terus mengedit file konfigurasi dan menambahkan semua kata sandi dan kunci yang akan kami gunakan di aplikasi. Untuk saat ini, mari kita periksa cara mengirim email dengan cepat menggunakan Python. Pertama, mari kita buat templat untuk email verifikasi yang dapat kami kirim ke pengguna kami, dan letakkan di direktori Template Pengguna. Template ini akan ditulis dalam HTML.

nano users/templates/users/verification_email.html
 
<h1>Django App - Verify Your Email</h1>
<p>Dear {{ user.username }},</p>
<p>To verify your email, please <a href="{{ base_url }}{% url 'users:activate' uidb64=uid token=token %}">click here</a>.</p>

<p>Alternatively, you can paste the following link in your browser's address bar:</p>
<p>{{ base_url }}{% url 'users:activate' uidb64=uid token=token %}</p>

<p>The link will expire in 30 minutes.</p>
<p>If you have not requested a verification email you can simply ignore this email.</p>
<p>See you there,</p>
<p>Daisy</p>
 
Email ini cukup sederhana. Dibutuhkan konteks pengguna, URL dasar untuk situs, dan ID pengguna dan token yang digunakan untuk memverifikasi email pengguna. Pastikan untuk mendefinisikan URL dasar di settings.py sebelum kita menulis beberapa kode Python untuk membuat template. Silakan dan tambahkan baris berikut ke app/settings.py, dekat awal.

SITE_NAME = 'Django App'
PROTOCOL = 'https'
DOMAIN = 'example.com'

BASE_URL = PROTOCOL + '://' + DOMAIN
Akhirnya, ketika situs Anda siap untuk internet dan Anda menggunakannya, Anda akan ingin mendefinisikan domain Anda sebagai nama domain yang Anda beli untuk mewakili situs. Ini adalah nama yang akan Anda ketik di navbar untuk mengakses situs Anda. Untuk saat ini, Anda dapat membiarkan domain kosong atau menggunakan placeholder. Anda juga ingin mengubah situs_name menjadi nama yang ingin Anda berikan kepada situs Anda, pilihan Anda. Sebelum kami mengirim email, mari kita buat generator token sehingga kami dapat memiliki token aktivasi akun yang tidak pernah kedaluwarsa. Kita dapat melakukan ini dengan membangun dan mengimpor token aktivasi akun yang terlihat seperti berikut. Edit file:

nano users/tokens.py
Tambahkan kode berikut:

from django.contrib.auth.tokens import PasswordResetTokenGenerator
import six
class TokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        return (
            six.text_type(user.pk) + six.text_type(timestamp)
        )
account_activation_token = TokenGenerator()
unsubscribe_token = TokenGenerator()
Generator token dasar ini menghasilkan token yang dapat kami kirimkan kepada pengguna dalam URL dan pengguna dapat menggunakan untuk memverifikasi email mereka dan mengaktifkan akun mereka. Selanjutnya, mari kita lihat cara mengirim email. Menggunakan Nano, edit pengguna/email.py.

nano users/email.py
Mengirim email verifikasi html akan terlihat seperti ini:

from django.contrib.auth import get_user_model
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes
from django.core.mail import EmailMultiAlternatives
from django.shortcuts import render
from .tokens import account_activation_token
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.template import Template, Context
from django.conf import settings
import traceback

def send_verification_email(user):
    User = get_user_model()
    mail_subject = '[{}] Activate your account.'.format(settings.SITE_NAME)
    html_message = render_to_string('users/verification_email.html', {
        'user': user,
        'domain': settings.DOMAIN,
        'protocol': 'https',
        'uid': urlsafe_base64_encode(force_bytes(user.pk)),
        'token': account_activation_token.make_token(user),
    })
    send_html_email(user, mail_subject, html_message)
Ini cukup sederhana. Kami mengimpor fungsi yang kami butuhkan untuk mengirim email, membuat email dengan templat, dan pengaturan kami, dan kemudian kami menentukan email dengan nama templat dan mengirimkannya ke pengguna menggunakan fungsi. Anda akan melihat kami belum menentukan fungsi untuk mengirim surat, send_html_email, jadi, jadi mari kita tulis ini di bawah kode yang sudah kami tambahkan ke pengguna/email.py

def send_html_email(user, mail_subject, html_message):
    to_email = user.email
    username = user.username
    if to_email == '':
        return None
    unsub_link = settings.BASE_URL + user.profile.create_unsubscribe_link()
    html_message = html_message + "<p><a href=\"" + unsub_link +  "\" + title=\"Unsubscribe from " + settings.SITE_NAME + " emails\">Unsubscribe</a></p></body></html>"
    msg = EmailMultiAlternatives(mail_subject, strip_tags(html_message), settings.DEFAULT_FROM_EMAIL, [to_email], headers={'List-Unsubscribe' : '<' + unsub_link + '>'},)
    msg.attach_alternative(html_message, "text/html")
    profile = user.profile
    try:
        msg.send(fail_silently=False)
        if not profile.email_valid:
            profile.email_valid=True
            profile.save()
    except:
        profile.email_valid=False
        profile.save()
Ini sedikit lebih kompleks, dan kami belum siap menjalankan semua kode ini. Perhatikan kami mendefinisikan unsub_link, tautan yang dapat digunakan pengguna untuk berhenti berlangganan dari email kami. Ini penting, karena pengguna harus dapat memilih keluar dari email kami kecuali mereka ingin melihatnya, kapan saja. Kami juga menambahkan alternatif teks ke pesan kami, yang merupakan pesan HTML yang dilucuti dari tag HTML. Terakhir, kami memeriksa apakah email dikirim, dan jika tidak, kami menandai di profil pengguna bahwa email mereka tidak valid. Mari kita kembali ke model pengguna sehingga kita dapat membuat ini semua berfungsi. Kita perlu mendefinisikan fungsi untuk menghasilkan tautan untuk berhenti berlangganan, dan mendefinisikan bidang Boolean untuk menandai bahwa email pengguna tidak valid. Pertama, tambahkan impor berikut ke bagian atas pengguna/model.py

nano users/models.py

# ...
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
Selanjutnya, mari kita tambahkan fungsi ke model pengguna untuk membuat token dan periksa token yang digunakan untuk mengaktifkan email, serta bidang untuk menyimpan apakah pengguna berhasil menerima surat mereka. Di pengguna/model.py lagi, tambahkan kode berikut ke akhir model (kode indentasi)

# ...
    email_valid = models.BooleanField(default=True)
    
    def make_token(self):
        return TimestampSigner().sign(self.user.username)

    def check_token(self, token):
        try:
            key = '%s:%s' % (self.user.username, token)
            TimestampSigner().unsign(key, max_age=60 * 60 * 24 * 30) # Berlaku selama 30 hari
        except (BadSignature, SignatureExpired):
            return False
        return True

    def create_unsubscribe_link(self):
        username, token = self.make_token().split(":", 1)
        return reverse('users:unsubscribe', kwargs={'username': username, 'token': token,})
Ini cukup sederhana, kami menggunakan timestampSigner, yang merupakan alat kriptografi dasar, untuk membuat token yang akan kedaluwarsa setelah waktu tertentu, dan kami juga menggunakan fungsi lain untuk memeriksa apakah itu valid. Kami menggunakan token ini dua kali, sekali untuk memverifikasi email, dan sekali untuk tautan berhenti berlangganan. Sekarang kita memiliki ini, pekerjaan terakhir yang perlu kita lakukan adalah dalam pandangan. Di dalam pengguna/views.py, mari tambahkan tampilan untuk memverifikasi alamat email, dan untuk berhenti berlangganan.

nano users/views.py
Pertama, tambahkan impor berikut. Saya melemparkan beberapa tambahan sehingga kami tidak perlu mengimpor lebih banyak item lagi nanti.

from django.contrib.auth import logout
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.models import User
from django.utils.encoding import force_str
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
import json
import requests
import datetime, traceback
from django.contrib import messages
from .models import Profile
from django.utils import timezone
from django.views.decorators.cache import never_cache
from .email import send_verification_email # Pastikan untuk mengimpor fungsi pengiriman email verifikasi
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.utils.decorators import method_decorator
from django.http import HttpResponseRedirect
from django.conf import settings
from django.utils import timezone
import datetime
import pytz
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.contrib.auth.tokens import default_token_generator
from django.utils.http import urlsafe_base64_decode
from .tokens import account_activation_token
Anda mungkin sudah memiliki beberapa impor ini, tetapi tidak ada salahnya untuk mengulanginya. Anda perlu mengimpor fungsi pengiriman email verifikasi, serta account_activation_token dari pengguna. Tokens, di antara impor lainnya. Sekarang, di bagian bawah file, tambahkan kode berikut:

def unsubscribe(request, username, token):
    user = get_object_or_404(User, username=username)
    if((request.user.is_authenticated and request.user == user) or user.profile.check_token(token)):
        # berhenti berlangganan mereka
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    # Jika tidak, redirect ke halaman login
    messages.warning(request,f'Your unsubscribe link has expired. Please log in to unsubscribe.')
    next_url = reverse('users:unsubscribe', kwargs={'username': username, 'token': token,})
    return HttpResponseRedirect('%s?next=%s' % (reverse('login'), next_url))

def activate(request, uidb64, token):
    try:
        uid = force_str(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except(TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None
    ip = get_client_ip(request)
    if user is not None and account_activation_token.check_token(user, token):
        user.profile.email_verified = True
        user.profile.save()
        user.save()
# Sendwelcomeemail (permintaan, pengguna)
        messages.success(request, f'Thanks for confirming your email! You can now log into your account, and a welcome email has been sent to you.')
        return redirect(user.profile.create_face_url())
    else:
        messages.success(request, f'Your activation link has expired. Please request a new activation link.')
        return redirect('verify:verify')

def resend_activation(request):
    if request.method == 'POST':
        form = ResendActivationEmailForm(request.POST)
        email = request.POST['email']
        try:
            user = User.objects.get(email=email)
            send_verification_email(user)
            messages.success(request,'Your verification email sent. Please click the link in your email to verify your account.')
            return redirect(reverse('verify:verify'))
        except:
            messages.warning(request,f'Your email is not correct. Please try again.')
    else:
        form = ResendActivationEmailForm()
    return render(request,'users/resend_activation.html',{'form': form, 'title': 'Resend Activation', 'small': True})
Ini banyak kode. Mari kita hancurkan. Fungsi pertama, bersih dan sederhana, berhenti berlangganan pengguna dari milis. Fungsi kedua mengaktifkan email mereka, dan Anda akan melihat saya menambahkan fungsi berkomentar, SendWelcomeemail. Anda dipersilakan untuk menggunakan templat email dan definisi fungsi untuk mengirim email selamat datang, saya belum melakukannya. Fungsi terakhir yang saya lemparkan adalah penting, karena email aktivasi kedaluwarsa. Oleh karena itu, kita perlu mengirimkan kembali email aktivasi beberapa waktu. Kami dapat menggunakan formulir dasar untuk ini, dan memanggil fungsi untuk mengirim email verifikasi. Sebelum kita melakukan ini, mari kita pastikan itu akan dikirim ke tempat pertama, dengan menambahkan panggilan fungsi ke tampilan register. Tambahkan baris ini tepat sebelum pengalihan dalam tampilan register, DEF Daftar, di pengguna/views.py.

nano users/views.py

# … (Setelah) Def Register (permintaan):
            send_verification_email(user)
# ... (Sebelum) Redirect (
Anda tidak perlu menambahkan baris pertama dan terakhir dalam cuplikan kode itu, pastikan tampilan register mengirimkan email verifikasi ke pengguna. Seharusnya terlihat seperti ini:

# ... jumlah
from .forms import UserRegisterForm

def register(request):
    if request.method == “POST”:
        form = UserRegisterForm(request.POST)
        if form.is_valid():
            user = form.save()
            send_verification_email(user) # Pastikan untuk menambahkan baris ini!
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Sekarang, kita perlu menambahkan formulir untuk mengirimkan kembali email aktivasi. Di pengguna/forms.py, tambahkan formulir berikut:

# … (Jumlah)
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)
Kami juga membutuhkan templat yang sesuai dengan formulir aktivasi email ini. Mari kita tambahkan template ini. Edit file:

nano users/templates/users/resend_activation.html
Selanjutnya, tambahkan kode berikut ke file.

{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Resend activation email</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Resend activation email</button>
            </div>
        </form>
{% endblock %}
Wah, itu banyak! Sekarang, ketika kami menggunakan kode ke server kami, kami akan dapat mengirim email HTML dan mengaktifkan akun pengguna dengan klik di email. Kami juga mungkin ingin mengirim email selamat datang sederhana, jadi mari kita lihat bagaimana melakukannya. Kembali ke pengguna/email.py, tambahkan kode berikut:

def sendwelcomeemail(user):
    User = get_user_model()
    html = open('{}/users/welcome_email.html'.format(settings.BASE_DIR)).read()
    subject = 'Welcome to ' + settings.SITE_NAME + ', {{ username }}!'
    template = Template(html)
    subjtemplate = Template(subject)
    context = Context({'username': user.username, 'base_url': settings.BASE_URL, 'model_name': 'Daisy Holton, 'site_name': settings.SITE_NAME})
    renderedtemplate = template.render(context)
    subjcontext = Context({'username': user.username})
    subjrenderedtemplate = subjtemplate.render(subjcontext)
    send_html_email(user, subjrenderedtemplate, renderedtemplate)
Juga, kami akan membutuhkan templat untuk membuat semua informasi ini. Di situs web saya, template terlihat seperti di bawah ini, tetapi Anda dipersilakan untuk memformatnya sesuka Anda.
 
<html>
<body>
<h3>Welcome to {{ site_name }}</h3>
<p>Hello {{ username }},</p>
<p>We are happy to see you here! Thank you for joining {{ site_name }} and being a part of the fun. To get started, here are a few things you can do after you verify your identity.</p>
<ol>
    <li><a href="{{ base_url }}/" title="Use the app">Use the app</a>. This is the main page of {{ site_name }}</li>
    <li><a href="{{ base_url }}/feed/profile/Clementine/" title="See my profile">Visit my private {{ site_name }} profile</a>. This is a page for anyone wanting to get to know me.</li>
    <li><a href="{{ base_url }}/feed/profiles/" title="See all profiles currently on the site">More profiles</a>. You can find these people on the site, and see their content.</li>
    <li><a href="{{ base_url }}/feed/all/" title="See everything on {{ site_name }}">See all posts here</a>. This is the private front page of {{ site_name }}.</li>
</ol>
<p>There is even more on the site, so feel free to visit and see what you find. You can share the site with any of the social buttons on each page. I hope you enjoy your time with {{ site_name }}! Thanks for being here.</p>
<p>With much love,</p>
<p>{{ model_name }}</p>
<a href="{{ base_url }}" title="{{ site_name }}">{{ base_url }}</a>
 
Perhatikan bahwa kami tidak memiliki tag bodi atau html, karena kami menambahkannya saat kami menambahkan tautan berhenti berlangganan HTML. Ini penting, tetapi kami tidak ingin mendefinisikannya dua kali. Terus gimana? Kami telah menempuh perjalanan panjang. Sungguh, kita harus siap untuk menggunakan situs ke server. Kami dapat menambahkan dekorator @login_required dan membuat pandangan kami aman, mengambil pendaftaran pengguna, mengirim email yang sesuai, dan informasi cache, yang merupakan dasar dari apa yang perlu dilakukan situs web agar tetap relevan. Kami akan menambahkan beberapa fitur yang lebih berguna, dan kemudian membangun dasar untuk menggunakan kode kami ke server jarak jauh, menyiapkan server surat, konfigurasi domain, dan filter untuk membuat situs kami aman dan sesuai. Kami juga membutuhkan tampilan reset kata sandi, jadi mari kita tambahkan dengan sangat cepat. Tampilan reset kata sandi bawaan Django rusak dalam beberapa fungsi, tetapi kita akan melihat cara menulis tampilan kita sendiri, templat email, formulir, dan pola URL. Begitulah tampilannya, di pengguna/views.py

# ... jumlah
from django.contrib.auth.tokens import default_token_generator
from django.contrib.auth.forms import SetPasswordForm
from django.utils.http import urlsafe_base64_decode

def password_reset(request, uidb64, token):
    user = get_object_or_404(User, id=urlsafe_base64_decode(uidb64))
    if request.method == 'POST':
        form = SetPasswordForm(user, request.POST)
        if form.is_valid() and default_token_generator.check_token(user, token):
            form.save()
            messages.success(request, 'Your password has been reset.')
        elif not form.is_valid():
            messages.warning(request, 'Your passwords do not match, or do not meet the requirements. Please try again.')
            return redirect(request.path)
        else:
            messages.warning(request, 'Your password reset link has expired. Please create a new one.')
        return redirect(reverse('users:login'))
    return render(request, 'users/password_reset_confirm.html', {
        'title': 'Reset your Password',
        'form': SetPasswordForm(user)
Formulir ini dibangun untuk Django, tetapi kami akan memerlukan templat untuk mengonfirmasi reset kata sandi, pengguna/templat/pengguna/kata sandi_reset_confirm.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Reset Password</button>
            </div>
        </form>
{% endblock content %}
 
Kami juga memiliki template untuk mengirim email reset kata sandi, dengan formulir sederhana, di pengguna/templat/pengguna/kata sandi_reset.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Request Password Reset</button>
            </div>
        </form>
{% endblock content %}
 
Templat untuk email itu sendiri sederhana, itu adalah file dasar HTML yang membuat tautan untuk mengatur ulang kata sandi, di pengguna/templat/pengguna/kata sandi_reset_email.html. Django akan secara otomatis menafsirkan file ini.
 
<h1>Uglek - Reset Your Password</h1>
<p>Hello,</p>
<p>To reset your password, please <a href="https:/uglek.com{% url 'password_reset_confirm' uidb64=uid token=token %}">click here</a>.</p>
<p>Alternatively, you can paste the following link into your browser:</p>
<p>https://uglek.com{% url 'password_reset_confirm' uidb64=uid token=token %}</p>
<p>If you have not requested a password reset you can simply ignore this email.</p>
<p>Thanks for joining us,</p>
<p>Daisy</p>
 
Kami juga membutuhkan dua templat lagi. Yang pertama adalah mengkonfirmasi bahwa email telah dikirim. Pandangan untuk ini sudah ada di Django, jadi kita hanya perlu mengatasinya di urls.py. Templat ini terletak di pengguna/templat/pengguna/kata sandi_reset_done.html
 
{% extends 'base.html' %}
{% block content %}
  <div class="media-body">
    <div class="alert alert-info">
        An email has been sent with instructions to reset your password.
    </div>
  </div>
{% endblock content %}
 
Dan terakhir, untuk mengonfirmasi bahwa reset kata sandi selesai, pengguna/templat/pengguna/kata sandi_reset_complete.html
 
{% extends 'base.html' %}
{% block content %}
 <div class="media-body">
    <div class="alert alert-info">
        Your password has been set.
    </div>
    <a href="{% url 'users:login' %}">Sign In Here</a>
  </div>
{% endblock content %}
 
Sekarang, kita membutuhkan pola URL untuk pandangan ini. Di pengguna/urls.py, tambahkan pola URL berikut:

urlpatterns = [
    # ... URL sebelumnya di sini
    path('password-reset/',
         auth_views.PasswordResetView.as_view(
             template_name='users/password_reset.html',
             html_email_template_name='users/password_reset_html_email.html'
         ),
         name='password_reset'),
    path('password-reset/done/',
         auth_views.PasswordResetDoneView.as_view(
             template_name='users/password_reset_done.html'
         ),
         name='password_reset_done'),
    path('password-reset-confirm/<uidb64>/<token>/',
         auth_views.PasswordResetConfirmView.as_view(
             template_name='users/password_reset_confirm.html'
         ),
         name='password_reset_confirm'),
    path('password-reset-complete/',
         auth_views.PasswordResetCompleteView.as_view(
             template_name='users/password_reset_complete.html'
         ),
         name='password_reset_complete'),
]
Empat template, itu banyak! Tapi sekarang kita dapat memastikan untuk dapat mengatur ulang kata sandi pengguna kapan saja kita perlu, semua dari browser web. Saya mengerti ini banyak kode. Jika sepertinya sedikit di atas kepala Anda, tidak apa -apa. Anda akan meningkatkan, pemahaman Anda akan meningkat, dan Anda akan menjadi jauh lebih kompeten dengan kode segera. Jika Anda benar-benar tersesat, saya sarankan untuk kembali ke perangkat lunak ini nanti setelah bekerja pada kursus pembelajaran yang berjalan sendiri secara online. Ini biasanya bebas untuk memulai, dan akan memandu Anda melalui semua yang Anda butuhkan untuk sukses ketika Anda kembali ke proyek ini. Jika Anda merasa siap untuk melanjutkan, baca terus, selanjutnya, kami akan membahas penyebaran kode Anda ke server jarak jauh dan menyiapkan server email, serta mengotomatisasi penyebaran Anda menggunakan bash sehingga Anda selalu dapat mengatur proyek baru dengan beberapa perintah sederhana. Hal terakhir yang perlu kami lakukan sebelum digunakan ke server jarak jauh adalah membuat situs kami sedikit lebih aman. Anda akanPerhatikan bahwa tampilan login hanya mengambil nama pengguna dan kata sandi, dan tidak ada otentikasi multi -faktor atau satu kode waktu. Ini adalah perbaikan yang mudah, dan dengan kode yang sama, kami dapat membuat situs kami mengirim pesan teks dan bahkan responsif terhadap pesan teks yang dikirim ke server. Untuk memulai, kami akan kembali ke model pengguna dan menambahkan penandatangan stempel waktu yang akan mewakili setiap login. Kami juga akan menambahkan pengidentifikasi yang unik dan berputar ke model pengguna yang akan digunakan untuk menambahkan keamanan ekstra ke login kami. Mengedit model pengguna, pengguna/model.py, tambahkan yang berikut ini

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# Pastikan untuk mengimpor penandatangan UUID, timestamp dan generator URL (terbalik)
import uuid
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name='profile')
    account_created = models.DateTimeField(default=timezone.now)
    last_seen = models.DateTimeField(default=timezone.now)
    can_login = models.DateTimeField(default=timezone.now)
    preferred_name = models.CharField(max_length=20,default='', null=True, blank=True)
    bio = models.TextField(blank=True, default='')
    # Tambahkan kode ini di sini
    uid = models.CharField(max_length=32, default=uuid.uuid4, null=True, blank=True)
    mfa_enabled = models.BooleanField(default=False)
    enable_mfa = models.BooleanField(default=False)
    phone_number = models.CharField(default='', null=True, blank=True, max_length=15)
    verification_code = models.CharField(default='', null=True, blank=True, max_length=15)
    verification_code_length = models.IntegerField(default=6)
    mfa_code_expires = models.DateTimeField(default=timezone.now)
    mfa_attempts = models.IntegerField(default=0)

    def make_auth_token(self):
        return TimestampSigner().sign(self.uid)

    # Dan tambahkan fungsi ini
    def create_auth_url(self):
        username, token = self.make_auth_token().split(":", 1)
        return reverse('users:mfa', kwargs={'username': username, 'token': token,})

    def check_auth_token(self, token):
        try:
            key = '%s:%s' % (self.uid, token)
            TimestampSigner().unsign(key, max_age=60 * settings.AUTH_VALID_MINUTES) # Berlaku selama 3 menit
        except (BadSignature, SignatureExpired):
            return False
        return True
Pastikan pengguna/model.py Anda terlihat seperti ini, selain komentar (kode pada baris dengan #). Memecah ini, sederhana. Kami memiliki beberapa impor, penampungan timestams yang merupakan utilitas kriptografi yang dapat menghasilkan kode yang aman dan memverifikasi untuk memastikan itu valid, hanya digunakan sekali, dan tidak lebih tua dari jumlah detik tertentu. Kami juga menggunakan UUID, yang merupakan pengidentifikasi unik yang mengidentifikasi pengguna kami dalam penandatanganan token, dan di URL tempat token dikirim ke pengguna. Kami akan menggunakan kriptografi dasar ini untuk membangun tampilan otentikasi dua faktor. Sebelum kita melakukan hal lain, mari kita jalankan migrasi sehingga model pengguna kami diperbarui. Di direktori dengan kelola.py, jalankan perintah berikut untuk membuat dan menyelesaikan migrasi.

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Ini penting karena setiap kali kami melakukan perubahan pada model, kami perlu membuat tabel dan memperbarui database dengan default sebelum kami benar -benar dapat menggunakan model. Selanjutnya, mari kita berimprovisasi tampilan login kita untuk mengarahkan kembali ke tampilan otentikasi sekunder. Di pengguna/views.py, hapus fungsi login dan redirect ke URL yang baru saja kami hasilkan dalam model pengguna.

# … Impor

def login(request):
    if request.method == “POST”:
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        if user and user.profile.can_login < timezone.now(): # Perhatikan bahwa kami sekarang memeriksa apakah pengguna dapat masuk
            # Hapus fungsi auth_login yang ada di sini
            messages.success(request, 'Your password was accepted. Please continue.')
            if user.profile.mfa_enabled:
                return redirect(user.profile.create_auth_url()) # Catatan Kami mengarahkan ulang ke URL baru di sini
            else: # Jika pengguna tidak menggunakan otentikasi multi-faktor, cukup login.
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # Jika login tidak berhasil,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Ini adalah bagian di mana kami memperbarui profil pengguna
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Jadi mereka tidak bisa masuk lagi selama beberapa detik
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Jadi ini cukup sederhana, kami sekarang memiliki cara untuk mengarahkan kembali tampilan otentikasi dua faktor saat kami membuatnya. Kami juga memiliki fallback jika pengguna belum menambahkan nomor telepon. Kami akan menambahkan tampilan dasar untuk segera menambahkan nomor telepon dan segera masuk dengan pesan teks. Pertama, kami membutuhkan cara mudah untuk mengirim pesan teks dari kode kami. Untuk melakukan ini, kita dapat memilih dari sejumlah API, tetapi yang termudah menurut saya adalah Twilio. Mereka juga menawarkan harga yang baik untuk proyek yang lebih kecil, serta diskon massal. Buat akun di twilio.com, isi beberapa detail tentang proyek Anda, beli nomor telepon, dan salin tombol API Anda ke settings.py Anda. Kemudian, tambahkan kode ini di bawah file baru, pengguna/sms.py.

nano users/sms.py

# Impor semua paket yang diperlukan
from django.utils import timezone
import random
import datetime
from django.conf import settings
from feed.middleware import get_current_request
from django.contrib import messages
import traceback

account_sid = settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
source_phone = settings.PHONE_NUMBER

# Kode ini mengirimkan teks dengan twilio
def send_text(target_phone, text):
    from twilio.rest import Client
    try:
        client = Client(account_sid, auth_token)
        if len(target_phone) >= 11:
            message = client.messages.create(
                to=target_phone,
                from_=source_phone,
                body=text)
    except:
        print(traceback.format_exc())

# Fungsi pembantu untuk mendapatkan angka dengan begitu banyak digit
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# Kirim teks untuk memverifikasi pengguna
def send_verification_text(user):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    user.profile.verification_code = code
    user.profile.mfa_code_expires = timezone.now() + datetime.timedelta(minutes=3)
    user.profile.save()
    send_user_text(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)))

# Kirim pengguna apa pun dengan pengguna dengan fungsi ini
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# Validasi kode dengan fungsi ini
def check_verification_code(user, code):
    user.profile.mfa_attempts += 1
    result = user.profile.verification_code != None and code != '' and user.profile.verification_code == code and user.profile.mfa_code_expires > timezone.now() and user.profile.mfa_attempts <= 3
    if user.profile.mfa_attempts < 3 and result:
        user.profile.verification_code_length = 6
    elif user.profile.mfa_attempts > 2 and not result:
        user.profile.verification_code_length = 8
    user.profile.save()
    return result

# Validasi waktu
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
Pastikan untuk mengubah pengaturan Anda dengan tepat, menambahkan baris ini dengan kunci Anda:

# Pastikan untuk menyalinnya dari dasbor twilio Anda
TWILIO_ACCOUNT_SID = “<your sid>”
TWILIO_AUTH_TOKEN = “<your token>”
PHONE_NUMBER = “<your twilio phone number>”
SITE_NAME = “<Your site name>”
AUTH_VALID_MINUTES = 3 # Jumlah menit halaman TFA aktif setelah dipakai
Pertama, kami akan membutuhkan formulir untuk dua tampilan otentikasi faktor kami. Mengedit pengguna/forms.py, tambahkan kode berikut.

# ... jumlah
from django import forms

# Formulir untuk memasukkan nomor telepon kami
class PhoneNumberForm(forms.Form):
    phone_number = forms.RegexField(regex=r'^\+?1?\d{9,15}$', error_messages = {'invalid': "Phone number must be entered in the format: '+999999999'. Up to 15 digits is allowed."})
    def __init__(self, *args, **kwargs):
        super(PhoneNumberForm, self).__init__(*args, **kwargs)
        self.fields['phone_number'].label = phone_number_label

# Formulir untuk mengautentikasi
class TfaForm(forms.Form):
    code = forms.IntegerField(required=False)
    def __init__(self, *args, **kwargs):
        super(TfaForm, self).__init__(*args, **kwargs)
        self.fields['code'].widget.attrs.update({'autocomplete': 'off'})
    help_texts = {
        'code': 'Please enter the six digit code after sending it to your phone with the button above.'
    }
Selanjutnya, mari kita buat tampilan di pengguna/views.py

# ... jumlah
from django.http import HttpResponseRedirect
from .forms import PhoneNumberForm, TfaForm

def mfa(request, username, token):
    user = User.objects.filter(profile__uuid=username).first()
    if not user: return HttpResponseRedirect(reverse('verify:age') + '?next=' + request.GET.get('next') if request.GET.get('next') else '/go/' if request.user.is_authenticated and request.user.profile.vendor else '/' if request.user.is_authenticated else reverse('users:login'))
    user = get_object_or_404(User, profile__uuid=username)
    next = request.GET.get('next','')
    if not user.profile.mfa_enabled:
        if not check_verification_time(user):
            user.profile.mfa_enabled = False
            user.profile.enable_two_factor_authentication = True
            user.profile.phone_number = '+1'
            user.profile.save()
            print('Logging in user')
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
            messages.warning(request, 'Please enter a valid phone number and verify it with a code.')
            return redirect(reverse('users:mfa_onboarding'))
    if request.method == 'POST':
        form = TfaForm(request.POST)
        code = form.data['code']
        if code and code != '' and code != None:
            token_validated = user.profile.check_auth_token(token)
            p = user.profile
            is_verified = check_verification_code(user, int(code))
            p.mfa_authenticated = is_verified
            if token_validated:
                if is_verified:
                    user.profile.mfa_enabled = True
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                    p.verfication_code = None
                    p.uid = get_uuid()
                    p.save()
                    messages.success(request, 'You have been authenticated. Welcome.')
                    qs = '?'
                    for key, value in request.GET.items():
                        qs = qs + key + '=' + value + '&'
                    if next != '' and not (next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/admin/login/') or next.startswith('/accounts/register/')):
                        return HttpResponseRedirect(ext)
                    elif next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/accounts/register/'):
                        return redirect('feed:feed')
                    elif request.META.get('HTTP_REFERER', '/').startswith('/accounts/login/'):
                        return redirect(reverse('feed:feed'))
                    elif not next:
                        return redirect(reverse('feed:feed')
                    else:
                        return HttpResponseRedirect('feed:feed')
                else:
                    messages.warning(request, 'The code you entered was not recognized. Please try again.')
            elif not token_validated:
                messages.warning(request, 'The URL token has expired or was not recognized. Please try again.')
                logout(request)
                return redirect(reverse('users:login'))
            if p.mfa_attempts > 3:
                messages.warning(request, 'You have entered the incorrect code more than 3 times. please send yourself a new code.')
                p.verification_code = None
                p.save()
        elif user.profile.can_send_mfa < timezone.now():
            user.profile.mfa_attempts = 0
            user.profile.can_send_mfa = timezone.now() + datetime.timedelta(minutes=2)
            user.profile.save()
            send_verification_text(user)
            messages.success(request, "Please enter the code sent to your phone number. The code will expire in 3 minutes.")
        else:
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    return render(request, 'users/mfa.html', {'title': 'Enter Code', 'form': form, 'xsmall': True, 'user': user, 'hide_logo': hide_logo, 'accl_logout': user.profile.shake_to_logout, 'preload': False})

@login_required
def mfa_onboarding(request):
    if request.method == 'POST':
        form = PhoneNumberForm(request.POST)
        request.user.profile.phone_number = form.data['phone_number'].replace('-', '').replace('(','').replace(')','')
        request.user.profile.mfa_enabled = True
        request.user.profile.enable_two_factor_authentication = True
        request.user.profile.save()
        messages.success(request, 'You have added a phone number to your account.')
        user = request.user
        return redirect(user.profile.create_auth_url())
    form = PhoneNumberForm(initial={'phone_number': request.user.profile.phone_number if request.user.profile.phone_number else '+1'})
    return render(request, 'users/mfa_onboarding.html', {'title': 'Enter your phone number', 'form': form, 'small': True})
Kami juga akan membutuhkan templat untuk kedua pandangan ini. Mari kita tambahkan template MFA terlebih dahulu.

nano users/templates/users/mfa.html
Tambahkan kode HTML ini ke template
 
{% extends 'base.html' %}
{% block content %}
{% load app_filters %}
{% load crispy_forms_tags %}
        <form action="{{ request.path }}{% if request.GET.next %}?next={{ request.GET.next }}{% endif %}" method="POST">
            {% csrf_token %}
            <legend class="border-bottom mb-4">Enter Verification Code</legend>
            <p>Step 1: Send the code</p>
	    <i>Never share your code with anyone, as it can be used to access your account temporarily.</i>
	    <div class="form-group">
                <button class="btn btn-outline-primary" type="submit">Send code</button>
            </div>
	    <hr>
	    <p>Step 2: Enter the code</p>
            <fieldset class="form-group">
                {{ form|crispy }}
		<p>Press the enter button to send yourself the code at {{ user.profile.phone_number|securephone }}. Then, enter the code and press enter.</p>
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Enter code</button>
            </div>
        </form>
{% endblock %}
 
Ini cukup jelas. Formulir mengirimkan kode atau kode kosong, dan Anda akan melihat di tampilan kami mengirim kode jika kami menerima kode kosong. Kemudian kami hanya memiliki dua tombol kirim, dan dengan cara ini kami dapat mengirim kode dengan kedua tombol. Selanjutnya, kami akan menambahkan formulir sederhana untuk menambahkan nomor telepon.

nano users/templates/users/mfa_onboarding.html
Tambahkan html berikut:
 
{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Set Up Two Factor Authentication</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-secondary" type="submit">Add phone number</button>
            </div>
        </form>
{% endblock %}
 
Formulir ini jauh lebih sederhana, hanya membuat formulir nomor telepon yang kami buat dan memungkinkan pengguna menambahkan nomor telepon. Ini terlihat sangat bagus! Selama semuanya diatur dengan benar, kita harus dapat mengirim pesan, dan mencatat pengguna dengan nomor telepon mereka segera setelah kita menambahkan pola URL. Hal terakhir yang perlu kami atur adalah tampilan profil sehingga kami dapat memastikan pengguna dapat mengubah nomor telepon mereka tanpa masuk. Juga, pada akhirnya kami ingin menambahkan opsi "berhenti untuk berhenti", sehingga pengguna dapat mengirim pesan teks "Berhenti" untuk memilih keluar dari pesan teks di masa mendatang. Mari kita tambahkan tampilan profil ke pengguna/views.py. Tampilan ini akan memperbarui bio, email, nama pengguna, dan nomor telepon pengguna, serta memungkinkan kami untuk mengaktifkan otentikasi multi -faktor. Pertama, kami akan membutuhkan dua formulir lagi di pengguna/forms.py

# ... jumlah
class UserUpdateForm(forms.ModelForm):
    email = forms.EmailField()
    class Meta:
        model = User
        fields = ['username', 'email']

phone_number_label = 'Phone number (no spaces, parenthesis \'(\' or dashes \'-\', numbers beginning with + only)'

class ProfileUpdateForm(forms.ModelForm):
    subscribed = forms.BooleanField(required=False)
    phone_number = forms.CharField(required=False)
    def __init__(self, *args, **kwargs):
        super(ProfileUpdateForm, self).__init__(*args, **kwargs)
    class Meta:
        model = Profile
        fields = ['bio', 'phone_number', 'enable_mfa', 'subscribed']
Selanjutnya, kita dapat membuat tampilan untuk menggunakan kedua formulir ini. Edit pengguna/views.py dan tambahkan tampilan.

# Tambahkan impor ini
from .forms import UserUpdateForm, ProfileUpdateForm
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt
from .models import Profile
from .mfa import send_user_text

@csrf_exempt
@never_cache
@login_required
def profile(request):
    if request.method == 'POST':
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = ProfileUpdateForm(request.POST,
                                       request.FILES,
                                       instance=request.user.profile)
        if u_form.is_valid() and p_form.is_valid():
            new_phone_number = p_form.data['phone_number']
            u_form.save()
            profile = p_form.save(commit=False)
            profile.phone_number = profile.phone_number.replace('-', '').replace('(','').replace(')','')
            profile.save()
            if new_phone_number != oldprofile.phone_number and oldprofile.phone_number and len(oldprofile.phone_number) >= 11:
                profile.mfa_enabled = True
                profile.save()
                send_text(oldprofile.phone_number, 'Your phone number has been updated to ' + new_phone_number + '. Please refer to texts on that phone to log in. If you didnt make this change, please call us. - {}'.format(settings.SITE_NAME))
            if profile.enable_two_factor_authentication and profile.phone_number and len(profile.phone_number) < 11:
                profile.enable_two_factor_authentication = False
                messages.success(request, f'Two factor authentication can\'t be activated without entering a phone number. Please enter a phone number to enable two factor authentication.')
            profile.save()
            if new_phone_number != oldprofile.phone_number and new_phone_number and len(new_phone_number) >= 11:
                send_user_text(request.user, 'You have added this number to {} for two factor authentication. You can now use your number for two factor authentication. If you didnt make this change, please call us. - {}'.format(settings.SITE_NAME, settings.DOMAIN))
                profile.mfa_enabled = True
                profile.mfa_code_expires = timezone.now() + datetime.timedelta(minutes=3)
                profile.save()
                return redirect(profile.create_auth_url())
            messages.success(request, f'Your profile has been updated!')
            print('Profile updated')
            return redirect('users:profile')
    else:
        u_form = UserUpdateForm(instance=request.user)
        p_form = ProfileUpdateForm(instance=request.user.profile, initial={'phone_number': request.user.profile.phone_number if request.user.profile.phone_number else '+1'})
    context = {
        'u_form': u_form,
        'p_form': p_form,
        'title':'Update Your Profile',
    }
    return render(request, 'users/profile.html', context)
Kami juga membutuhkan templat untuk tampilan ini.

nano users/templates/users/profile.html
 
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load feed_filters%}
{% block content %}
	<h2>Edit Your Profile</h2>  
	<form method="POST" enctype="multipart/form-data" id="profile-form">
          {% csrf_token %}
          <fieldset class="form-group">
              <legend class="border-bottom mb-4 mt-4">Profile info</legend>
              {{ u_form|crispy }}
              {{ p_form|crispy }}
          </fieldset>
          <div class="form-group">
              <button class="btn btn-outline-info" type="submit">Update}</button>
          </div>
	</form>
        <p style="text-color: green;" class="hide" id="posted">Saved</p>

{% endblock content %}
{% block javascript %}
var form = document.getElementById('profile-form');
$('input').change(function(){
	var formdata = new FormData(form);
	$.ajax({
		url: window.location.href,
		type: "POST",
		data: formdata,
		processData: false,
		contentType: false,
		timeout: 1000 * 60,
                success: function(data) {
                  $(posted).removeClass("hide");
		  setTimeout(function() {
			$(posted).addClass("fade-hidden");
			setTimeout(function() {
				$(posted).addClass("hide");
				$(posted).removeClass("fade-hidden");
			}, 2000);
		  }, 2000);
                }
	});
});
{% endblock %}
 
Anda akan melihat ini adalah bentuk yang cukup sederhana, tetapi memiliki beberapa javascript di dalamnya yang secara otomatis memposting isi formulir saat diperbarui. Ini berguna untuk dimiliki, jadi Anda dapat mengedit tanpa harus menekan kirim setiap saat. Selanjutnya, kita membutuhkan URL yang mewakili semua pandangan ini di URL Patters pengguna. Edit pengguna/urls.py dan tambahkan kode ini:

# … Kode sebelumnya, impor
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
# … Pola URL yang sebelumnya kami masukkan, tambahkan tiga baris berikutnya
    path('mfa/<str:username>/<str:token>/', views.mfa, name='mfa'),
    path('mfa/onboarding/', views.mfa_onboarding, name='mfa_onboarding'),
    path('profile/', views.profile, name='profile'),
]
Sekarang adalah saat yang tepat untuk menguji proyek kami. Tapi pertama -tama, mari kita jalankan cadangan lain.

backup
Dan jalankan server. Sebelum kita menggunakan server Linux, itu ide yang bagus untuk mengaktifkan otentikasi dua faktor pada akun. Kami akan melakukan ini pergi ke URL profil kami,/pengguna/profil/, dan mencentang kotak untuk mengaktifkan otentikasi setelah memasukkan nomor telepon kami, dan kemudian mengirimkan formulir.

python manage.py runserver localhost:8000
Kunjungi halaman web dengan pergi ke browser web Anda, saya menggunakan Google Chrome dalam contoh ini, dan memasukkan URL https: // localhost: 8000/akun/profil/ Anda akan dapat masuk jika perlu dan mengaktifkan otentikasi dua faktor. Proyek ini membutuhkan server untuk berjalan sehingga dapat benar -benar mengirim surat. Tapi pertama -tama, kita membutuhkan cara untuk melihat kesalahan. Anda akan melihat bahwa jika Anda menjalankan server dalam mode debug, dengan pengaturan.debug sama dengan True, server menunjukkan kesalahan secara otomatis. Untuk menunjukkan kesalahan tanpa menggunakan mode debug, yang tidak aman di server produksi, kita harus menambahkan tampilan untuk itu. Kesalahan terpenting yang perlu kita tangani adalah: Kesalahan 500 - Masalah dengan kode kami Kesalahan 404 - Halaman yang tidak ditemukan (URL rusak) Kesalahan 403 - kesalahan yang ditolak izin Mari kita tambahkan aplikasi baru untuk menangani kesalahan ini, yang disebut kesalahan.

python manage.py startapp errors
Tambahkan ini ke settings.py seperti yang kami lakukan sebelumnya, dalam pengaturan Installed_Apps, dan mulailah dengan menambahkan referensi ke beberapa tampilan di App/Urls.py, di mana aplikasi adalah nama proyek Django Anda.

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
Ini semua yang kita butuhkan selain tampilan kesalahan, templat, dan sedikit middleware. Mari kita tentukan itu seperti:

from django.shortcuts import render, redirect
from django.http import HttpResponse
from stacktrace.models import Error
from errors.middleware import get_current_exception
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .logs import get_logs
from face.tests import is_superuser_or_vendor
from django.views.decorators.csrf import csrf_exempt
from errors.highlight import highlight_code
from django.shortcuts import redirect
from django.urls import reverse

# Buat pandangan Anda di sini.
@login_required
@user_passes_test(is_superuser_or_vendor)
def logs(request):
    logs = highlight_code(get_logs())
    return render(request, 'errors/live_error.html', {'title': 'Error Logs', 'pagetitle': 'Error Logs', 'notes': 'These are the recent error logs.', 'trace': logs, 'full': True})

@login_required
@user_passes_test(is_superuser_or_vendor)
def logs_api(request):
    logs = highlight_code(get_logs())
    return HttpResponse(logs)

@login_required
def handler404(request, exception):
    if not request.path.endswith('/'): return redirect(request.path + '/')
    return render(request, 'errors/error.html', {'title': 'Error 404', 'pagetitle': 'Error 404', 'notes': 'This page was not found on the server. It may have moved or been deleted.', 'is_404': True})

def handler500(request):
    print(get_current_exception())
    user = None
    if hasattr(request, 'user') and request.user and request.user.is_authenticated:
        user = request.user
    try:
        Error.objects.create(user=user, stack_trace=get_current_exception(), notes='Logged by 500 handler.')
    except: pass
    return render(request, 'errors/error.html', {'title': 'Error 500', 'pagetitle': 'Error 500', 'notes': 'There is a problem with the server, or with a request coming from you. Thank you for your understanding while we get things set up.', 'trace': get_current_exception()})

def handler403(request, exception):
    return render(request, 'errors/error.html', {'title': 'Error 403', 'pagetitle': 'Error 403', 'notes': 'You don\'t have permission to preform this request. If you think this is in error, please contact the server administrator.', 'is_403': True})

def handler400(request, exception):
    return render(request, 'errors/error.html', {'title': 'Error 400', 'pagetitle': 'Error 400', 'notes': 'This was a bad request.'})
Selanjutnya, mari kita tentukan middleware untuk menangani kesalahan ini. Kami akan melakukan ini dengan terlebih dahulu menambahkan ke middleware_classes di settings.py, dengan nama middleware kami.

MIDDLEWARE_CLASSES = [
    # ... middleware sebelumnya
    'errors.middleware.ExceptionVerboseMiddleware,
]
Selanjutnya, mari tambahkan middleware.

from threading import local
import traceback
from django.utils.deprecation import MiddlewareMixin

_error = local()

class ExceptionVerboseMiddleware(MiddlewareMixin):
    def process_exception(self, request, exception):
        _error.value = traceback.format_exc()

def get_current_exception():
    try:
        return _error.value
    except AttributeError:
        return None

def set_current_exception(exception):
    try:
        _error.value = exception
    except AttributeError:
        print('Attribute error setting exception.')
Kami menambahkan fungsi untuk mendapatkan pengecualian saat ini dengan menggunakan threading lokal, yang membantu kami melacak kesalahan dalam kode kami. Dalam hal template, kami hanya perlu satu, karena kami secara dinamis mendefinisikan judul dalam tampilan. Template hanya perlu membuat judul dan "melacak", Traceback kesalahan kami dari konteks.

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
Ini adalah templat paling sederhana kami, tapi begitulah mudahnya melihat kesalahan dalam proyek kami. Selanjutnya, mari kita nonaktifkan debug dalam pengaturan.

nano app/settings.py
Temukan baris ini di mana diatur ke true, dan ubah menjadi false

DEBUG = False
Silakan dan cadangkan aplikasi sekarang. Kami siap digunakan ke server Linux jarak jauh, dan terus menambahkan fitur dari sana.

sudo backup
Sebelum kami memposting kode ini ke server, kami harus mempertimbangkan bahwa mungkin ada beberapa masalah dengan kode. Bergantung pada kasusnya, situs yang menerima informasi yang diposting kepada mereka akan memiliki masalah dengan spam yang diposting dan kesulitan menghapus spam. Ini seharusnya tidak terjadi segera, tetapi jika itu terjadi, kita nanti akan memeriksa cara memoderasi spam secara otomatis di situs dan membuatnya lebih sulit bagi robot untuk mengakses situs, bersama dengan cara menonaktifkan akun pengguna, dan memverifikasi identitas pengguna dengan Pemindaian ID mereka atau pemindaian biometrik, seperti sidik jari atau pengenalan wajah. Melihat contoh otentikasi multi -faktor yang kami periksa, dalam produksi, hal -hal bisa berbeda. Perhatikan bagaimana kami membatasi login, dan token yang kedaluwarsa. Jika robot mengakses situs, dua faktor otentikasi bisa lebih sulit karena mereka dapat memasukkan kode pada saat yang sama pengguna. Untuk melawan ini, mari kita gunakan model dalam model pengguna, menyatakan bagaimana kita berinteraksi dengan situs saat kita beradaMengotentikasi menggunakan otentikasi multi -faktor dengan nomor telepon. Kami juga akan menambahkan opsi untuk mengotentikasi dengan email. Mulailah dengan mengedit model pengguna dengan

nano users/models.py
Seperti inilah model yang kita tambahkan seharusnya. Kami tidak memerlukan metode apa pun, hanya variabel untuk menyimpan ID, pengguna, stempel waktu, kedaluwarsa, panjang dan upaya terhadap otentikasi multi -faktor apa pun (kode seperti 123456 dikirim ke telepon atau email).

# Token dasar yang digunakan untuk masuk ke situs web
class MFAToken(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='mfa_tokens')
    timestamp = models.DateTimeField(default=timezone.now)
    expires = models.DateTimeField(default=timezone.now)
    token = models.CharField(default='', max_length=100)
    length = models.IntegerField(default=6)
    attempts = models.IntegerField(default=0)
    uid = models.CharField(default=uuid.uuid4, max_length=100)
Mari kita juga menambahkan hak istimewa kepada pengguna kami, dan kami akan mengaturnya secara manual untuk saat ini, sebelum akhirnya bermigrasi ke mendaftar pengguna istimewa secara otomatis. Di model pengguna, tambahkan baris ini di profil:

    vendor = models.BooleanField(default=False)
Seperti halnya perubahan pada database, kita perlu membuat migrasi dan memigrasikan database setiap kali kita mengedit file model.py di Django. Ingat, untuk melakukan ini, kami menggunakan sumber terlebih dahulu (jika belum digunakan karena terminal terbuka) dan kemudian Python mengelola.py untuk membuat migrasi dan bermigrasi.

cd project-directory-you-named # (jika perlu)
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Untuk saat ini, Anda dapat meminta akun apa pun yang telah Anda buat sebagai vendor dengan menggunakan shell.

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
Sekarang, mari kita berevolusi tampilan otentikasi multi -faktor kami untuk menggunakan token ini. Pertama, kita perlu memodifikasi utilitas pembantu MFA kami. Menggunakan nano,

nano users/mfa.py

from django.utils import timezone
import random
import datetime
from django.conf import settings
from feed.middleware import get_current_request
from django.contrib import messages
from .email import send_html_email
import traceback
from .models import MFAToken

account_sid = settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
source_phone = settings.PHONE_NUMBER

def send_text(target_phone, text):
    from twilio.rest import Client
    try:
        client = Client(account_sid, auth_token)
        if len(target_phone) >= 11:
            message = client.messages.create(
                to=target_phone,
                from_=source_phone,
                body=text + ' Text STOP to cancel.')
    except:
        messages.warning(get_current_request(), 'There was an error sending the message.')
        print(traceback.format_exc())

def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

def send_verification_text(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_user_text(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)))

def send_verification_email(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_html_email(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)), "<p>Dear {},</p><p>Your verification code for {} is {}. Thank you for using this code to secure your account.</p><h2>{}</h2><p>Sincerely, {}</p>".format(user.profile.name, settings.SITE_NAME, str(code), str(code), settings.SITE_NAME))

def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

def check_verification_code(user, token, code):
    token.attempts = token.attempts + 1
    profile = user.profile
    result = (token != None and code != '' and token.token == code and (token.expires > timezone.now()) and token.attempts <= settings.MFA_TOKEN_ATTEMPTS)
    if token.attempts < 3 and result:
        profile.verification_code_length = 6
    elif token.attempts > 1 and not result:
        profile.verification_code_length = profile.verification_code_length + 2
        if profile.verification_code_length > settings.MFA_TOKEN_LENGTH: profile.verification_code_length = settings.MFA_TOKEN_LENGTH
    token.save()
    profile.save()
    return result

# Mengotentikasi pengguna menggunakan email atau nomor telepon mereka
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() # Saring token dengan nilai yang diteruskan di URL (A UUID)
    if not token: token = MFAToken.objects.create(user=User.objects.filter(profile__uuid=username).first(), uid=username, expires=timezone.now() + datetime.timedelta(seconds=115)) # Jika sesi ini belum dibuat, buatlah
    user = User.objects.filter(id=token.user.id).first() # Dapatkan pengguna dari token
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # Jika sudah diautentikasi, login
    if not user: raise PermissionDenied() # Tolak jika tidak ada pengguna yang ditemukan
    next = request.GET.get('next','')
    if not user.profile.enable_two_factor_authentication and user.is_active and user.profile.check_auth_token(usertoken, token): # Periksa token auth
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Masuk pengguna jika belum masuk
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # Tetapkan kedaluwarsa pada otentikasi multi -faktor mereka
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # Mengalihkan pengguna ke halaman berikutnya
    if not user.profile.mfa_enabled: # Periksa apakah MFA diaktifkan
        if not check_verification_time(user, token): # Periksa waktu
            user.profile.mfa_enabled = False # Bersihkan Nomor Telepon
            user.profile.enable_two_factor_authentication = True # Aktifkan MFA
            user.profile.phone_number = '+1' # Nonaktifkan Nomor Telepon
            user.profile.save() # Simpan profil
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Masuki pengguna jika MFA mereka tidak diaktifkan
            messages.warning(request, 'Please enter a valid phone number and verify it with a code.')
            return redirect(reverse('users:mfa_onboarding'))
    if request.method == 'POST' and not fraud_detect(request, True): # Jika permintaan adalah permintaan pos
        form = TfaForm(request.POST) # Instantiate formulir
        code = str(form.data.get('code', None)) # Dapatkan kodenya
        if code and code != '' and code != None: # Pastikan itu tidak kosong
            token_validated = user.profile.check_auth_token(usertoken) # Periksa token auth
            p = user.profile
            is_verified = check_verification_code(user, token, code) # Periksa kodenya
            p.mfa_authenticated = is_verified
            if token_validated: # Jika semuanya
                if is_verified: # Beres
                    user.profile.mfa_enabled = True # Aktifkan MFA (jika belum diaktifkan)
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Masuk Pengguna
                    face = user.faces.filter(session_key=None).last() 
                    p.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES)
                    p.save()
                    messages.success(request, 'You have been authenticated. Welcome.')
                    qs = '?'
                    for key, value in request.GET.items(): # Bangun querystring untuk parameter berikutnya (jika ada)
                        qs = qs + key + '=' + value + '&'
                    if next != '' and not (next.startswith('/accounts/logout/') or  next.startswith('/accounts/login/') or next.startswith('/admin/login/') or next.startswith('/accounts/register/')):
                        return HttpResponseRedirect(next) # Redirect
                    elif next.startswith('/accounts/logout/') or next.startswith('/accounts/login/') or next.startswith('/accounts/register/'):
                        return redirect(reverse('/'))
                    elif request.META.get('HTTP_REFERER', '/').startswith('/accounts/login/'):
                        return redirect(reverse('/'))
                    elif not next:
                        return redirect(reverse('/'))
                    else:
                        return HttpResponseRedirect(reverse('verify:age') + '?next=' + request.META.get('HTTP_REFERER', '/'))
                else:
                    messages.warning(request, 'The code you entered was not recognized. Please try again.')
            elif not token_validated: # Jika tokennya tidak valid
                messages.warning(request, 'The URL token has expired or was not recognized. Please try again.')
                logout(request)
                return redirect(reverse('users:login'))
            if p.mfa_attempts > 3: # Jika ada terlalu banyak upaya
                messages.warning(request, 'You have entered the incorrect code more than 3 times. please send yourself a new code.')
                p.verification_code = None
                p.save()
        elif user.profile.can_send_mfa < timezone.now():
            user.profile.mfa_attempts = 0
            user.profile.can_send_mfa = timezone.now() + datetime.timedelta(minutes=2)
            user.profile.save()
            if form.data.get('send_email', False): # Kirim email (atau teks)
                send_mfa_verification_email(user, token)
            else:
                send_verification_text(user, token)
            messages.success(request, "Please enter the code sent to your phone number or email. The code will expire in 3 minutes.")
        elif user.profile.can_send_mfa < timezone.now() + datetime.timedelta(seconds=115):
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    if request.user.is_authenticated: return redirect(reverse('/'))
    # Render formulir (untuk mendapatkan permintaan)
    return render(request, 'users/mfa.html', {'title': 'Enter Code', 'form': form, 'xsmall': True, 'user': user, 'hide_logo': hide_logo, 'accl_logout': user.profile.shake_to_logout, 'preload': False, 'autofocus': request.method == 'POST'})
Saat kami menambahkan kode ini, pastikan untuk mengimpor fungsi untuk mengirim email. Di bagian atas file, pengguna melihat (dengan impor lainnya), tambahkan

from .mfa import send_verification_email as send_mfa_verification_email
Sekarang, kita perlu menulis fungsi itu sebelum semua ini akan berhasil. Ini harus memperpanjang fungsi Kirim Email kami, dan cukup kirim email ke pengguna dengan kode verifikasi.

nano users/mfa.py

def send_verification_email(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_html_email(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)), "<p>Dear {},</p><p>Your verification code for {} is {}. Thank you for using this code to secure your account.</p><h2>{}</h2><p>Sincerely, {}</p>".format(user.profile.name, settings.SITE_NAME, str(code), str(code), settings.SITE_NAME))
Jadi ini semua berfungsi dengan baik, sekarang kami memiliki sistem otentikasi multi -faktor yang tergantung pada nomor telepon atau email untuk masuk. Tetapi kami juga membutuhkan cara untuk menghapus, atau setidaknya menyembunyikan pengguna yang tidak bekerja sama dengan persyaratan kami. Ini bisa berupa spammer, robot atau siapa pun yang tidak bermaksud baik untuk pekerjaan kami. Lihatlah tampilan yang saya miliki untuk memantau pengguna di situs web saya:

# jumlah
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor # Kami perlu membuat tes ini

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # Dapatkan daftar pengguna
    new_today = User.objects.filter(is_active=True, date_joined__gte=timezone.now() - datetime.timedelta(hours=24)).count()
    new_this_month = User.objects.filter(is_active=True, date_joined__gte=timezone.now() - datetime.timedelta(hours=24*30)).count()
    subscribers = User.objects.filter(is_active=True, profile__subscribed=True).count()
    return render(request, 'users/users.html', { # Mengembalikan pengguna dalam templat
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
Perhatikan bahwa kode ini menggunakan tes, kita perlu mendeklarasikan tes ini dalam file tests.py dan mengimpornya. Mengedit pengguna/tests.py, mari kita buat tes.

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
Ini bersamaan dengan Template Pengguna/Pengguna.html, yang terlihat seperti ini:
 
{% extends 'base.html' %}
{% load app_filters %}
{% block content %}
<h1>All Registered Visitors</h1>
<p>{{ new_today|nts|capitalize }} new today, {{ new_this_month|nts }} new this month, {{ subscribers|nts }} subscribers, {{ users.count|nts }} total.</p>
<hr style="color: red;">
{% for user in users %}
{% include 'users/_user.html' %}
<hr style="color: blue;">
{% endfor %}
{% endblock %}
 
Perhatikan bahwa template termasuk templat lain, pengguna/_user.html. Saat menggunakan templat yang memiliki subtemplate dan tidak menggunakan Extends, itu ide yang bagus untuk menambahkan garis bawah (_) sebelum nama file untuk diperpanjang, untuk membedakan templat. Perhatikan bahwa ini adalah banyak jinja, Anda mungkin tidak memiliki semua variabel ini. Tapi seperti inilah kode saya.
 
{% load app_filters %}
<div>
<img src="{{ user.profile.get_image_url }}" alt="@{{ user.profile.name }}'s profile photo" width="120" height="120" align="left" style="margin-top:5px; margin-right:10px; margin-bottom:10px; border-radius: 50%;"/>
    <div class="article-metadata">
      <p class="mr-2">@{{ user.username }} - {{ user.profile.name }} ({{ user.profile.preferred_name }})</p>
      <small class="text-muted">Last seen {{ user.profile.last_seen|date:"F d, Y" }} {{ user.profile.last_seen|time:"H:i" }}</small>
      <small class="text-muted">Joined on {{ user.profile.date_joined|date:"F d, Y" }} {{ user.profile.date_joined|time:"H:i" }}</small>
      <small>{{ user.email }}</small>
      {% if user.profile.phone_number %}<small><i class="bi bi-phone-fill"></i>{{ user.profile.phone_number }}</small>{% endif %}
      {% if user.verifications.last %}
      <small>'{{ user.verifications.last.full_name }}'</small>
      <small><i class="bi bi-123"></i> {{ user.verifications.last.document_number }}</small>
      <small><i class="bi bi-calendar-heart-fill"></i> {{ user.verifications.last.birthdate }}</small>
      <a href="{{ user|document_front }}" class="btn btn-sm btn-outline-primary" title="ID front"><i class="bi bi-person-badge-fill"></i> ID front</a>
      <a href="{{ user|document_back }}" class="btn btn-sm btn-outline-primary" title="ID back"><i class="bi bi-upc-scan"></i> ID back</a>
      {% endif %}
      <small># {{User.id}} </small>
      <small>{% if user.profile.subscribed %}Subscribed{% else %}Not subscribed{% endif %}</small>
    </div>
    {%if not user.is_superuser %}
    <div style="float: right;">{% include 'users/toggle_active.html' %}</div>
    {% endif %}
    {% autoescape off %}    
    <p class="article-content">{{ user.bio }}</p>
    {% endautoescape %}
    <hr>
    <p>{% if user.profile.identity_verified %}Verified user.{% else %}Unverified user.{% endif %} Verifications: {{ user.verifications.count|nts }}</p>
 
Kami juga membutuhkan subtemplate lain, toggle_active.html. Template ini harus menjadi formulir yang memungkinkan kita untuk beralih apakah pengguna aktif.
 
<form style="display: inline-block;" action="{% url 'users:toggle-user-active' user.id %}" method="POST" id="publishForm">
<button class="btn btn-sm btn-outline-danger" type="submit">{% if user.is_active %}<i class="bi bi-eye-fill"></i>{% else %}<i class="bi bi-eye-slash-fill"></i>{% endif %}</button>
</form>
 
Kami juga perlu menambahkan tampilan untuk beralih aktivitas pengguna, dan pola URL yang sesuai. Sementara kita melakukannya, mari kita tambahkan tampilan untuk menghapus pengguna jika kita membutuhkannya.

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
@login_required
@user_passes_test(is_superuser_or_vendor)
def toggle_user_active(request, pk):
    user = User.objects.get(id=pk)
    if request.method == 'POST':
        user.is_active = not user.is_active
        user.save()
    return HttpResponse('<i class="bi bi-eye-fill"></i>' if user.is_active else '<i class="bi bi-eye-slash-fill"></i>')


# Jumlah
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import DeleteView

class UserDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = User
    success_url = '/' # Redirect pada URL sukses
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return context

    def test_func(self): # Menguji apakah pengguna superuser dan memiliki izin untuk menghapus
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
Meskipun ini praktis bila perlu, menghapus pengguna seharusnya tidak perlu sebagian besar waktu, kami hanya dapat beralih visibilitas pengguna yang mengunjungi situs jika kami perlu mengabaikannya. Pola URL yang kami tambahkan terlihat seperti ini. Dengan Nano, edit pengguna/urls.py dan tambahkan baris ini:

nano users/urls.py
Baris harus masuk dalam daftar jalur dalam tampilan pengguna, sebelum akhir "]" tetapi setelah awal "[".

# ...
    path('user/<int:pk>/delete/', UserDeleteView.as_view(template_name='blog/user_confirm_delete.html'), name='delete-user'),
    path('user/<int:pk>/active/', views.toggle_user_active, name='toggle-user-active'),
# ...
Sekarang, pastikan untuk mencadangkan situs sehingga Anda dapat mengunduhnya di server web yang akan terus kami kerjakan. Dari baris perintah,

sudo backup
Sekarang situs kami didukung. Jadi sekarang kami memiliki beberapa fitur yang lebih berguna. Tapi bagaimana dengan gambaran besar di sini? Kode ini masih belum dapat diakses dari internet, kami belum memiliki server surat, dan kami perlu memperluas aplikasi kami untuk memasukkan proses verifikasi yang komprehensif serta tata letak yang halus untuk membantu kami menjelajahi Situs, bersama dengan protokol yang aman untuk mengautentikasi pengguna istimewa yang mengautentikasi hak istimewa yang mengautentikasi . Kami akan mencapai semua ini. Hal terpenting untuk saat ini hanya adalah mendapatkan kode ini secara online, yang dapat kami lakukan hanya dengan beberapa baris bash di server Ubuntu. Anda perlu menyewa server untuk ini, kecuali jika Anda memiliki server di rumah dan langganan internet bisnis yang memungkinkan Anda membuka port. Saya pribadi menjalankan situs web saya di HP Z440 yang diinstal di apartemen saya, tetapi biasanya jauh lebih murah untuk kebutuhan dasar untuk menyewa server pribadi virtual (VPS). Perlu diingat bahwa kode yang kami jalankan sekarang relatif tipis, itu perlu dipertahankan dan ditingkatkan sebelum kita beradaSiap menggunakan apa yang kita miliki untuk membangun suatu produk. Pastikan untuk berhati -hati dengan apa yang Anda lakukan dengan internet, pastikan jika Anda menggunakan situs ini secara publik ke web di server Linux, Anda memiliki rencana untuk memblokir interaksi yang tidak diinginkan dengan situs web Anda. Ini kemungkinan tidak akan menjadi masalah pada awalnya, tetapi kami akan melihat berbagai solusi untuk memerangi ini, termasuk pembelajaran mesin, kecerdasan buatan dan visi komputer. Ketika itu menjadi masalah, lihat lebih jauh dalam teks ini untuk solusi. Dalam hal menyewa VPS, ada banyak tempat yang bisa Anda kunjungi. Google Cloud memiliki server VPS, Ionos, Kamatera, Amazon AWS, dan lebih banyak penyedia menawarkan solusi server cloud yang sesuai dengan kebutuhan kita. Anda harus mengklik formulir mereka dan memilih rencana untuk memulai. Anda dapat menggunakan paket dasar dengan penyedia mana pun, tetapi pastikan penyedia memungkinkan Anda untuk membuka port server mail port untuk mengirim email (ini harus port 587 dan port 25), beberapa penyedia memblokir port ini. Sejauh ini saya memilikiPengalaman EST dengan Ionos dan Kamatera, keduanya akan memungkinkan saya untuk mengirim email tanpa batas dan harga mereka cukup murah. Anda akan terhubung ke server baru Anda melalui protokol yang disebut SSH atau Secure Shell, yang memungkinkan Anda untuk berinteraksi dengan server persis seperti komputer pribadi Anda, dari komputer pribadi Anda. Saat Anda mengatur server, penyedia hosting kemungkinan akan meminta Anda untuk menambahkan kunci SSH, atau mereka akan memberi Anda nama pengguna dan kata sandi. Kunci SSH adalah bagaimana Anda akan masuk ke server dari baris perintah untuk mengedit kode. Gunakan opsi SSH-Keygen di bawah ini untuk menghasilkan SSH

ssh-keygen
Simpan file dan timpa jika Anda perlu, ada baiknya memutar kunci SSH Anda jika Anda belum melakukannya. Sekarang, Anda dapat menggunakan perintah berikut untuk melihat kunci SSH Anda. Anda ingin menyalinnya ke server jarak jauh Anda sehingga Anda dapat menggunakannya untuk mengotentikasi.

cat ~/.ssh/id_rsa.pub
Jika Anda tidak dapat melihat kunci SSH saat mengetikkan perintah itu (serangkaian angka panjang dan huruf yang dimulai dengan "SSH-RSA AAA"), cobalah menghasilkan kunci RSA (mereka lebih aman, jadi saya sarankan untuk menggunakannya .) Kode berikut akan menghasilkan kunci SSH RSA 4096 bit.

ssh-keygen -t rsa -b 4096
Buat VPS yang menjalankan Ubuntu, namun Anda berencana untuk melakukan ini. Setelah Anda membuat VPS dengan mengklik formulir di situs web penyedia (Kamatera.com, ionos.com atau serupa), Anda ingin masuk. Untuk melakukan ini, gunakan perintah SSH dengan alamat IP Anda (alamat Itu terlihat seperti xx.xx.xx.xx). Anda juga harus peka terhadap nama pengguna default di server yang kami buat, misalnya, Ubuntu.

ssh ubuntu@XX.XX.XX.XX
Anda mungkin diminta kata sandi, jika Anda diminta kata sandi, masukkan. Kami tidak akan menggunakan nama pengguna default, jadi mari kita mulai dengan membuat pengguna baru dan menambahkan kunci SSH ke akun mereka. Mari kita mulai dengan menambahkan file sshd_config baru, yang memberi tahu server cara menggunakan ssh.

nano sshd_config

# Ini adalah file konfigurasi sistem SSHD Server di seluruh sistem.  Melihat
# sshd_config (5) untuk informasi lebih lanjut.

# SSHD ini dikompilasi dengan path =/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# Strategi yang digunakan untuk opsi di SSHD_Config default yang dikirimkan bersama
# OpenSsh adalah menentukan opsi dengan nilai default mereka di mana
# mungkin, tetapi biarkan mereka berkomentar.  Opsi yang tidak dikomentasikan menggantikan
# Nilai default.

# Port 22
# Alamat kata -kata apapun
# Daftar Alamat 0.0.0.0
# Dengarkan Adress ::

# Hostkey/etc/ssh/ssh_host_rsa_key
# Hostkey/etc/ssh/ssh_host_ecdsa_key
# Hostkey/etc/ssh/ssh_host_ed25519_key

# Cipher dan kunci
# REKEYLIMIT Default Tidak Ada

# Logging
# Auth Syslogfacility
# Info Loglevel

# Otentikasi:

# LOGRINGRACETIME 2M
# Laras-labuh emperrootlogin
# Strictmodes Ya
# MaxAuthtries 6
# Maxessions 10

PubkeyAuthentication yes

# Harapkan .ssh/otorisasi_keys2 diabaikan secara default di masa depan.
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# OtorisedPrincipsFile tidak ada

# OtorisedKeysCommand tidak ada
# OtorisedKeySCommandUser NOBOHNE

# Agar ini berfungsi, Anda juga akan membutuhkan kunci host di/etc/ssh/ssh_nown_hosts
# HostbasedAuthentication no
# Ubah ke Ya Jika Anda tidak mempercayai ~/.ssh/know_hosts untuk
# HostbasedAuthentication
# IGNUSERNOWNINGHOSTS no
# Jangan membaca file ~/.rhosts dan ~/.shosts pengguna
# Ignorerhosts ya

# Untuk menonaktifkan kata sandi teks yang jelas, ubah menjadi tidak di sini!
PasswordAuthentication no
# Leveremptypasswords no

# Ubah ke YA untuk mengaktifkan kata sandi tantangan-respons (waspadai masalah dengan
# beberapa modul dan utas PAM)
KbdInteractiveAuthentication no

# Opsi Kerberos
# Kerberosauthentication no
# Kerberosorlocalpasswd Ya
# Kerberosticketcleanup Ya
# Kerberoscotot

# Opsi GSSAPI
# GSSAPIAUTIKASI NO
# Gssapicleanupcredentials ya
# Gssapistrictacceptorcheck ya
# Gssapikeyexchange no

# Atur ini ke 'ya' untuk mengaktifkan otentikasi PAM, pemrosesan akun,
# dan pemrosesan sesi. Jika ini diaktifkan, otentikasi PAM akan
# diizinkan melalui KBDinterActiveAuthentication dan
# PasswordAuthentication.  Tergantung pada konfigurasi PAM Anda,
# Otentikasi PAM melalui KBDinterActiveAuthentication dapat mem -bypass
# Pengaturan "permitrootlogin tanpa kata-kata".
# Jika Anda hanya ingin akun PAM dan pemeriksaan sesi berjalan tanpa
# Otentikasi Pam, lalu aktifkan ini tetapi atur kata sandi othentication
# dan KBDinterActiveAuthentication menjadi 'Tidak'.
UsePAM yes

# Allowagentforwarding ya
# Izintcpforwarding ya
# Gatewayports no
X11Forwarding yes
# X11DisplayOffset 10
# X11uselocalhost Ya
# Izin ya
PrintMotd no
# Printlastlog ya
# TCPKEEPLIVE Ya
# Lingkungan permittuen di
# Kompresi tertunda
# Interval ClientAlive 0
# Clientalivecountmax 3
# Digunakan di
# Pidfile /run/sshd.pid
# MaxStartups 10: 30: 100
# Pemittunl no
# Chrootdirectory tidak ada
# Versi Addendum Tidak Ada

# tidak ada jalur spanduk default
Banner /etc/banner

# Izinkan pelanggan untuk lulus variabel variabel lokal
AcceptEnv LANG LC_*

# mengesampingkan default tidak ada subsistem
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Contoh pengaturan utama berdasarkan per pengguna
# Cocokkan ANONCV Pengguna
# X11 untuk no
# Izinkan No
# Allowetty masuk
# Forcecommand CVS Server
PermitRootLogin no
Ingat, Ctrl+X dan Y untuk menyimpan file. Selanjutnya, mari kita tulis skrip dasar yang disebut inisialisasi (semua di direktori home default pengguna kami).

nano initialize
Tambahkan baris ini ke file, gantiDengan kunci SSH Anda yang Anda temukan menggunakan kucing. (.ssh/id_rsa.pub)

# ! / bin / Bash
sudo apt install -y nano git openssh-server
sudo cp sshd_config /etc/ssh/sshd_config
sudo service ssh restart
sudo service sshd restart
echo "/root/.ssh/id_rsa" | sudo su root -c "ssh-keygen -t rsa -N ''"
echo "root ssh key:"
sudo su root -c "cat /root/.ssh/id_rsa.pub"
sudo adduser --disabled-password --gecos "" team
sudo passwd -d team
sudo usermod -aG sudo team
echo "/home/team/.ssh/id_rsa" | su team -c "ssh-keygen -t rsa -N ''"
cat /home/team/.ssh/id_rsa.pub >> /home/team/.ssh/authorized_keys
echo '<key here>' >> /home/team/.ssh/authorized_keys
echo "team ssh key:"
cat /home/team/.ssh/id_rsa.pub
Untuk memandu Anda melalui file ini, mari kita mulai baris demi baris. Baris pertama memberi tahu kompiler bahwa ini adalah skrip bash. Kemudian kami memasang dependensi, menyalin sshd_config ke direktori yang benar, memulai kembali ssh, menghasilkan tombol ssh untuk root, menambahkan 'tim' pengguna (Anda dapat memilih nama yang Anda suka untuk ini, gunakan perintah adduser dengan nama dan kata sandi yang dinonaktifkan untuk Sekarang). Kami juga menambahkan tim ke grup sudo, menghasilkan kunci SSH mereka, menambahkan kunci kami ke kunci resmi dan mereka juga, dan mencetak kunci mereka. Pengguna baru ini akan menjadi cara kami masuk ke Situs. Di terminal baru, silakan dan buka server lagi.

ssh team@XX.XX.XX.XX
Anda seharusnya tidak memerlukan kata sandi kali ini, karena Anda memiliki kunci SSH. Kami juga telah menonaktifkan login dengan kata sandi untuk menjaga situs lebih aman. Sekarang, server ini mulai benar -benar kosong tanpa informasi di atasnya. Mari kita mulai dengan mengkloning proyek kami dari git sehingga kami dapat mengunduh dan menjalankannya di mesin jarak jauh. Di server jarak jauh yang terhubung melalui SSH, cetak pertama kunci SSH Anda:

cat ~/.ssh/id_rsa.pub
Selanjutnya, tempel kunci ini ke dalam pengaturan git seperti yang kami lakukan sebelumnya untuk mengatur repositori git kami. Kami sekarang dapat mengkloning proyek kami langsung ke server. Pastikan Anda telah mendukung proyek secara lokal terlebih dahulu sehingga ada di Git Server untuk diunduh.

git clone git://github.com/you/yourproject.git
Sempurna. Sekarang semua file ada di sini. Kita bisa melihatnya dengan LS

ls
Sekarang, mari kita mulai mengatur server. Pertama, salin direktori proyek Anda ke nama sederhana dan berkesan yang akan kami gunakan untuk proyek ini.

cp -r yourproject whatyoucalledit
Di mana "Whatyoucalledit" adalah nama baru dari proyek Anda. Selanjutnya, kita perlu membangun utilitas dasar untuk mengatur server. Kami akan menyimpan utilitas ini dan menggunakannya di masa depan. Untuk membangun utilitas ini, mari kita buat biner pengguna untuk menentukan bagaimana kita mengedit skrip. Menggunakan bash, edit/usr/bin/askrip

sudo nano /usr/bin/ascript
Pastikan untuk menggunakan sudo di sana sehingga Anda memiliki izin untuk mengedit file. Di file, tambahkan baris ini:

# ! / bin / Bash
if [ ! -f /usr/bin/$1 ]; then
    sudo touch /usr/bin/$1
    echo "# ! / Bin / Bash ">> / usr / bin / $ 1
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
    echo $1 | sudo tee -a /etc/ascripts
else
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
fi
Ingat skrip ini mengambil argumen, nama skrip, sebagai $ 1. Pertama -tama ia memeriksa apakah file tersebut ada, atau membuatnya, menambahkan baris pertama untuk mendeklarasikan skripnya adalah bash, mengubah izinnya, mengeditnya, dan menambahkan namanya ke /etc /Askripsi yang memungkinkan kami menyimpan nama -nama skrip yang kami lakukan membuat. Jika file sudah ada, cukup ubah izin dan edit. Simpan file, dan selanjutnya kita akan mengubah izin. Selama kita menggunakan skrip ini, kita tidak perlu melakukannya lagi.

sudo chmod a+x /usr/bin/ascript
Sempurna. Sekarang mari kita buat skrip yang disebut Pengaturan. Pertama, bukan untuk membanjiri Anda, tetapi lihat seperti apa skrip pengaturan saya. Kami akan berjalan melalui seperti apa skrip ini dalam proyek Anda, Anda tidak akan membutuhkan semua yang ada di skrip saya untuk memulai.

# !/bin/bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
# sudo chmod a+x skrip/useretup
# ./scripts/usersetup
# Ssh-keyen
# Direktori Proyek
DIR="/home/team/femmebabe"
USER="team"
# Perintah log
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# Konfigurasi Nano
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git Config
echo "Git configuration"
sudo git config --global user.email "jasper.camber.holton@gmail.com" && sudo git config --global user.name "Jasper Holton"
git config --global user.email "jasper.camber.holton@gmail.com"
git config --global user.name "Jasper Holton"
git config --global --add safe.directory $"$DIR"
sudo ssh-keyscan -t rsa gitlab.com | sudo tee -a /root/.ssh/known_hosts
sudo ssh-keyscan -t rsa github.com | sudo tee -a /root/.ssh/known_hosts
echo "Mounting setup"
sudo mount -o remount,size=16G,exec /tmp
# Perbarui dan instal
echo "Update and install packages"
sudo apt update && sudo NEEDRESTART_MODE=a apt upgrade -y
sudo apt purge postgresql-client-14 postgresql-client-common postgresql-common postgresql-contrib postgresql -y
echo "postfix postfix/mailname string femmebabe.com" | sudo debconf-set-selections
echo "postfix postfix/main_mailer_type string 'Internet Site'" | sudo debconf-set-selections
sudo NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt install -y postfix
sudo NEEDRESTART_MODE=a apt install -y rkhunter clamav-daemon libx264-dev ffmpeg libapache2-mod-wsgi-py3 apache2 cmake python-is-python3 python3-venv python3-pip python3-django expect tesseract-ocr openjdk-8-jdk redis-server libopencv-dev python3-opencv python3-dev libsasl2-dev opendkim opendkim-tools dovecot-core dovecot-pop3d dovecot-imapd auditd procmail libpq-dev postgresql postgresql-contrib libheif-dev snapd git software-properties-common certbot python3-certbot-apache
echo "-a exit,always -F arch=b64 -F euid=0 -S execve" | sudo tee -a /etc/audit/audit.rules
echo "-a exit,always -F arch=b32 -F euid=0 -S execve" | sudo tee -a /etc/audit/audit.rules
# Aktifkan Antivirus Clamav
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Atur nama host
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Siapkan postgres
echo "Postgres setup"
sudo -u postgres psql -U postgres -c "DROP DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE USER django WITH PASSWORD 'password';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET client_encoding TO 'utf8';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET default_transaction_isolation TO 'read committed';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET timezone TO 'UTC';"
sudo -u postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE database TO django;"
#  Setup database backup
echo "Building database from backup, this may take a while."
cat db.json.?? > db.json
echo "Configuring firewall"
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 'Postfix'
sudo ufw allow 'Postfix SMTPS'
sudo ufw allow 'Postfix Submission'
sudo ufw allow 'Dovecot POP3'
sudo ufw allow 'Dovecot Secure POP3'
sudo ufw allow 110/tcp
sudo ufw allow 25/tcp
echo "y" | sudo ufw enable
# IPatables dinonaktifkan
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Instal Bitdefender
cd $DIR
echo "Runnning BitDefender antivirus installer"
wget https://cloud.gravityzone.bitdefender.com/Packages/NIX/0/7aTSsy/setup_downloader.tar
mkdir bitdefender
tar -xf setup_downloader.tar -C bitdefender
sudo rm setup_downloader.tar
sed -i -e 's/{LOGINPASSWD/z&A*3BPd_qBGUMs/g' bitdefender/installer
sudo chmod a+x bitdefender/installer
sudo ./bitdefender/installer
# Pengaturan postfix
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
# Buat dir
cd $DIR
mkdir media/audio
mkdir media/audio/fingerprints
mkdir media/security
mkdir media/secure
mkdir media/secure/media
mkdir media/secure/video
mkdir media/secure/profile
mkdir media/secure/face
mkdir media/images
mkdir media/live
mkdir media/live/files
mkdir media/live/stills
mkdir media/files
mkdir temp
mkdir temp/data
mkdir temp/gfpgan
mkdir mail/inbox
mkdir mailbox
# Siapkan VirtuealEnv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# Dapatkan dan Bangun Ketergantungan
echo "Getting and building dependencies, this may take a whike"
cd $DIR
git clone https://github.com/sukhitashvili/violence-detection.git
cp config/vd-requirements.txt violence-detection/requirements.txt
cp config/vd-model.py violence-detection/model.py
cd violence-detection
pip3 install -r requirements.txt
cd $DIR
wget https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth -P experiments/pretrained_models
git clone https://github.com/TencentARC/GFPGAN.git
git clone https://github.com/davisking/dlib.git
cd dlib
mkdir build; cd build; cmake ..; cmake --build .
cd ..
source venv/bin/activate
python setup.py install
cd $DIR
source venv/bin/activate
cd $DIR/GFPGAN/
echo "Installing python dependencies"
pip install basicsr
pip install facexlib
pip install -r requirements.txt
python setup.py develop
pip install realesrgan
cd $DIR
sudo chown -R team:users gfpgan
echo "Installing ta-lib"
wget https://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
tar xvzf ta-lib-0.4.0-src.tar.gz
sudo rm ta-lib-*
cd ta-lib
sudo ./configure
sudo make
sudo make install
# Tetapkan aturan firewall
cd $DIR
# Instal dependensi PYPI
echo "Installing remaining python dependencies (this may take a while)"
sudo systemctl mask tmp.mount
cd $DIR
source venv/bin/activate
pip3 install -U "celery[redis]"
pip3 install -r requirements.txt --use-deprecated=legacy-resolver --use-pep517
pip3 install --upgrade opencv-python # == 4.5.4.60
pip3 install --upgrade opencv-contrib-python # == 4.5.4.60
# PIP menginstal opencv-python == 4.5.5.64
# Pip Instal OpenCV-Contrib-Python == 4.5.5.64
pip3 install --upgrade opencv-python-headless
pip3 uninstall channels
pip3 uninstall daphne
pip3 install channels["daphne"]
pip3 install Pillow==9.5.0
pip3 install librosa
pip3 install -U 'Twisted[tls,http2]'
pip3 install --upgrade certifi requests urllib3 numpy oauthlib twisted pyjwt sqlparse cryptography astral webauthn docbarcodes pdf417 deepface --no-cache-dir
pip3 install tensorflow==2.15.1
# Instal Certbot
echo "Installing certificates"
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap install redis
sudo systemctl enable apache2
sudo systemctl start apache2
# Jalankan Certbot
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# Muat Ulang Server Surat
sudo systemctl restart opendkim postfix dovecot
# Salin sertifikat
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privkey.pem
# sudo cp /etc/lettesencrypt/live/femmebabe.com/cert.pem cert.pem
# Tambalan
cp scripts/content.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/pyxb/binding/content.py"
cp scripts/pwa_webpush_forms.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/pwa_webpush/forms.py"
cp scripts/webauth_views.py $"/home/team/femmebabe/venv/lib/python${PYTHON_VERSION}/site-packages/webauth/views.py"
cp scripts/json.py $"venv/lib/python${PYTHON_VERSION}/site-packages/django/core/serializers/json.py"
# Atur Pengaturan Pengguna
sudo gpasswd -a www-data users
# Atur izin
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# tim sudo chown -r: pengguna/var/run/
# Sudo Chown Root: root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
# sudo chmod 664 db.sqlite3
# sudo chown www-data: pengguna db.sqlite3
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
sudo chown -R team:users ./gfpgan/
sudo chown -R team:users ./temp/
sudo chmod a+r team /var/mail/$USER
# Salin konfigurasi dan atur izin
echo "Configuring remaining services"
sudo cp config/apis.json /etc/apis.json
sudo cp config/config.json /etc/config.json
sudo cp config/femmebabe-le-ssl.conf /etc/apache2/sites-available/femmebabe-le-ssl.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_init.d_celery /etc/init.d/celery
sudo cp config/etc_init.d_celerybeat /etc/init.d/celerybeat
sudo cp config/etc_default_celerybeat /etc/default/celerybeat
sudo cp config/etc_default_celery /etc/default/celery
sudo cp config/etc_systemd_system_daphne.service /etc/systemd/system/daphne.service
sudo cp config/etc_systemd_system_celery.service /etc/systemd/system/celery.service
sudo cp config/etc_systemd_system_celerybeat.service /etc/systemd/system/celerybeat.service
sudo chmod a+x /etc/init.d/celery
sudo chmod a+x /etc/init.d/celerybeat
#  Setup database
echo "Running migrations, this should be quick"
python manage.py makemigrations
python manage.py migrate --run-syncdb
echo "Loading data, this may take a while"
python manage.py loaddata db.json
echo "Setup crontab/sudoers configuration"
sudo crontab -l -u root | cat - config/crontab | sudo crontab -u root -
sudo sh -c "cat config/sudoers >> /etc/sudoers"
# Menyuntikkan konfigurasi PAM dan menghapus konfigurasi SSH yang salah
# sudo sed -i '' -e '$ d' /tc/pam.d/sshd
# sudo sed -i '' -e '$ d' /etc /profile
echo "session required pam_exec.so seteuid /home/team/femmebabe/pam.sh" | sudo tee -a /etc/pam.d/sshd
echo "session required pam_exec.so seteuid /home/team/femmebabe/logout.sh" | sudo tee -a /etc/pam.d/sshd
sudo chmod a+x pam.sh
sudo rm /etc/ssh/sshd_config.d/50-cloud-init.conf
# Salin skrip tempat sampah dan atur izin
echo "Copying scripts"
sudo cp scripts/reload /usr/bin/
sudo cp scripts/check /usr/bin/
sudo cp scripts/enagpu /usr/bin/
sudo cp scripts/disgpu /usr/bin/
sudo cp scripts/activate /usr/bin/
sudo cp scripts/backup /usr/bin/
sudo cp scripts/ascript /usr/bin/
sudo cp scripts/setup /usr/bin/
sudo cp scripts/addsetup /usr/bin/
sudo cp scripts/watchlogs /usr/bin/
sudo cp scripts/logs /usr/bin/
sudo cp scripts/cmds /usr/bin/
sudo cp scripts/setup /usr/bin/
sudo cp scripts/pushweb /usr/bin/
sudo cp scripts/purgecache /usr/bin/
sudo cp config/banner /etc/banner
cd /usr/bin/
sudo chmod a+x activate
sudo chmod a+x backup
sudo chmod a+x ascript
# Muat Ulang dan Aktifkan Layanan
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable daphne.service
sudo systemctl enable celery.service
sudo systemctl enable celerybeat.service
sudo systemctl enable clamav-daemon
sudo systemctl start daphne.service
sudo systemctl start celery.service
sudo systemctl start celerybeat.service
sudo systemctl start clamav-daemon
# Aktifkan modul Apache
echo "Enabling apache2"
sudo a2enmod rewrite
sudo a2enmod wsgi
sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_balancer
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
# sudo a2dismod mpm_event
# Sudo a2dismod mpm_worker
# sudo a2enmod mpm_prefork
# Nonaktifkan situs default
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# Aktifkan untuk situs
sudo a2ensite femmebabe-le-ssl
# Muat ulang daemon dan restart apache, postfix dan opendkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# Atur izin
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# Konfigurasi Pertukaran
echo "Allocating swap, this may take a while"
sudo swapoff /swapfile
sudo rm /swapfile
sudo fallocate -l 8G /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1024 count=8388608
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab
sudo swapon --show
# Mesin caption init
echo "Initializing routine caption"
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/routine_caption.py
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/setup_mail.py
#  Setup git
echo "Setting up git"
cd $DIR
sudo rm -r .git
git init --initial-branch=main
echo "Setting user password"
sudo usermod --password $(echo team | openssl passwd -1 -stdin) team
# Tampilkan IPv6 dan OpenDkim untuk Konfigurasi Domain
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
sudo cat /etc/opendkim/keys/femmebabe.com/sendonly.txt | tr -d '\n' | sed 's/\s//g' | sed 's/""//g' | awk -F'[)(]' '{print $2}'
# Pengaturan selesai
echo "Setup completed in"
wc -l scripts/setup
echo "lines of code."
echo "Total time:"
duration=$SECONDS
echo "$((duration / 60)) minutes and $((duration % 60)) seconds elapsed."
echo "TODO:"
echo "- COPY above IPv6 address to domain DNS configuration"
echo "- COPY domain key to domain DNS configuration"
echo "- ADD new git repository with git remote add originlab <repo>."
echo "- OPEN port 25"
echo "- INSTALL antivirus as per reccomendations"
echo "- TEST"
echo "If neccesary,"
echo "- DEBUG"
echo "- FIX setup and backup scripts"
echo "- Fix server"
echo ""
echo "Thank you for using the femmebabe installer. Have a great day!"
echo "Goodbye."
Itu banyak pengaturan! Singkatnya, kode ini mencatat perintah, mengkonfigurasi nano dan git, salinan file, mengunduh dan menginstal paket apt ubuntu, dependensi python, mengkonfigurasi postfix, mengkonfigurasi postgresql (server database) dan memuat database, ufw (firewall yang tidak komplikasi), Menonaktifkan iPables, mengunduh antivirus, membuat direktori, dependensi klon, menginstal sertifikat dan mengatur server, menginstal konfigurasi, memulai dan memungkinkan Sever, mengalokasikan swap, mengatur izin, dan mencetak IP, alamat IPv6, dan kunci OpendKim. Cukup sederhana, tapi sepertinya banyak kode. Kami tidak akan membutuhkan banyak ini karena kami tidak memiliki dependensi, kami tidak menggunakan seledri, selyedbeat atau daphne, tetapi kami akan menginstal beberapa dari mereka untuk memulai. Perhatikan bahwa kode ini memiliki domain yang dinyatakan beberapa kali. Kami juga perlu membeli nama domain (yang merupakan biaya tahunan kecil). Saya merekomendasikan Squarespace untuk membeli domain, tata letaknyaintuitif dan mudah digunakan. Anda dapat membeli domain pilihan Anda, tetapi saya menggunakan domain femmebabe.com dalam contoh ini. Setelah Anda membeli domain, pergilah ke panel konfigurasi Squarespace DNS dan tambahkan catatan yang menunjuk domain Anda ke server dengan alamat IP. Seharusnya terlihat seperti ini: @ A xx.xx.xx.xx Dengan operator @ sebagai host, yang berarti semua subdomain di bawah domain ini dan domain root semuanya akan mengalihkan ke server. Ada lebih banyak catatan untuk dinyatakan, tetapi kami dapat beralih ke ini setelah kami siap mengirim surat. Perlu diingat, mungkin perlu beberapa hari sebelum Anda dapat berhasil mengirim surat dari server. Catatan DNS yang kami pengaturan akan membutuhkan waktu untuk menyebarkan. Ngomong -ngomong, satu -satunya catatan yang perlu kita mulai adalah catatan A. Jadi sekarang kita dapat mengisi skrip di bawah ini sesuai dengan proyek kami dan menjalankannya. Mari kita mulai dengan skrip pengaturan yang lebih kecil untuk hanya menginstal apa yang kita butuhkan untuk kemajuan dasar. Kami tidak akan menggunakan begitu banyak dependensi atau postgresql, kami akan sajaNaik server HTTP dasar dan khawatir tentang sertifikasi ketika itu selesai. Ingat, untuk mendapatkan sertifikat HTTPS dan menjalankan server dengan aman, kita perlu membeli domain bersama dengan sewa server. Untuk saat ini, ganti "tim" dalam file ini dengan nama pengguna Anda, "dir" dengan direktori proyek Anda, dan berikan email dan domain Anda di tag <>. Selain itu, sebelum kita menjalankan kode ini, kita perlu mengubah pengaturan ke firewall dukungan penyedia hosting, jika ada. Biasanya ini ada di tab 'Jaringan' dari penyedia hosting Anda, atau jika Anda hosting sendiri, di bagian 'Port Forwarding' dari router Anda. Anda juga ingin mengatur IP statis melalui router Anda dengan alamat mesin server Anda, jika Anda menggunakan hosting mandiri. Anda perlu membuka port berikut untuk akses baca/tulis. 22 (SSH) 25 (surat) 587 (surat) 110 (klien surat) 80 (http) 443

# ! / bin / Bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
# Perintah log
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# Konfigurasi Nano
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git Config
echo "Git configuration"
sudo git config --global user.email "<youremail>@gmail.com" && sudo git config --global user.name "<yourname>"
git config --global --add safe.directory $"$DIR"
sudo ssh-keyscan -t rsa gitlab.com | sudo tee -a /root/.ssh/known_hosts
sudo ssh-keyscan -t rsa github.com | sudo tee -a /root/.ssh/known_hosts
# Perbarui dan instal
echo "Update and install packages"
sudo apt update && sudo NEEDRESTART_MODE=a apt upgrade -y
sudo apt purge postgresql-client-14 postgresql-client-common postgresql-common postgresql-contrib postgresql -y
echo "postfix postfix/mailname string femmebabe.com" | sudo debconf-set-selections
echo "postfix postfix/main_mailer_type string 'Internet Site'" | sudo debconf-set-selections
sudo NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt install -y postfix
sudo NEEDRESTART_MODE=a apt install -y rkhunter clamav-daemon libx264-dev ffmpeg libapache2-mod-wsgi-py3 apache2 cmake python-is-python3 python3-venv python3-pip python3-django expect tesseract-ocr openjdk-8-jdk redis-server libopencv-dev python3-opencv python3-dev libsasl2-dev opendkim opendkim-tools dovecot-core dovecot-pop3d dovecot-imapd auditd procmail libpq-dev postgresql postgresql-contrib libheif-dev snapd git software-properties-common certbot python3-certbot-apache
# Aktifkan Antivirus Clamav
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Atur nama host
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
#  Setup database backup
echo "Building database from backup, this may take a while."
cat db.json.?? > db.json
echo "Configuring firewall"
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow 22
sudo ufw allow http
sudo ufw allow https
sudo ufw allow 'Postfix'
sudo ufw allow 'Postfix SMTPS'
sudo ufw allow 'Postfix Submission'
sudo ufw allow 'Dovecot POP3'
sudo ufw allow 'Dovecot Secure POP3'
sudo ufw allow 110/tcp
sudo ufw allow 25/tcp
echo "y" | sudo ufw enable
# IPatables dinonaktifkan
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Siapkan VirtuealEnv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
# Instal Certbot
echo "Installing certificates"
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap install redis
sudo systemctl enable apache2
sudo systemctl start apache2
# Jalankan Certbot
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# Atur Pengaturan Pengguna
sudo gpasswd -a www-data users
# Atur izin
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# tim sudo chown -r: pengguna/var/run/
# Sudo Chown Root: root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
# Muat Ulang dan Aktifkan Layanan
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Aktifkan modul Apache
echo "Enabling apache2"
sudo a2enmod rewrite
sudo a2enmod wsgi
sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_balancer
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
# Muat ulang daemon dan restart apache, postfix dan opendkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# Tampilkan IPv6 dan OpenDkim untuk Konfigurasi Domain
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
Sebelum menjalankan kode ini, pastikan domain yang telah Anda beli terhubung ke server. Untuk melakukan ini, buka terminal di mesin lokal Anda, dan jalankan perintah ini dengan domain Anda:

ping femmebabe.com # Masukkan domain Anda di sini, setelah ping
Jika semuanya terlihat baik dan server mengirimkan tanggapan, kami siap untuk menjalankan skrip dan menginstal paket serta memulai, mengaktifkan dan mensertifikasi server Apache kami. Ini bukan semua pengaturan yang diperlukan untuk mengonfigurasi postfix, kita akan melihat pengaturan itu lebih nanti. Untuk saat ini, jalankan kode pengaturan ini dan perlu beberapa menit untuk menginstal dan mensertifikasi server Anda. Sekali lagi, pastikan untuk mengganti nama, email dan nama domain dalam skrip sesuai dengan nama yang Anda beli. Sekarang server disediakan, Anda dapat pergi ke URL di browser web apa pun dan memeriksa untuk memastikan server menjalankan HTTPS. Jika tidak, coba tunggu sebentar untuk catatan DNS untuk mengejar ketinggalan dan kemudian jalankan perintah berikut untuk mencoba kembali sertifikasi Certbot:

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
Selama Anda telah mengonfigurasi semuanya dengan benar, Anda harus dapat mengakses halaman default Apache hanya untuk mengetahui kode Anda berfungsi dan menampilkan halaman web langsung. Selanjutnya, mari edit settings.py untuk mengubah mode debug default kami menjadi produksi. Kami juga akan mengkonfigurasi domain di pengaturan, serta IP internal.

nano yourproject/settings.py
Di pengaturan, ubah/tambahkan baris ini.

DEBUG = False

# Konfigurasi Situs
SITE_NAME = 'Femme Babe'
PROTOCOL = 'https'
DOMAIN = 'femmebabe.com'
SITE_ID = 1
BASE_URL = PROTOCOL + '://' + DOMAIN
ALLOWED_HOSTS = [DOMAIN]

INTERNAL_IPS = [
    'XX.XX.XX.XX',
]
Sekarang, kita perlu mengonfigurasi Apache2. Mari mengedit file konfigurasi yang akan kami gunakan dengan baris ini:

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
File konfigurasi ini harus memiliki nama domain kami di dalamnya, dan nama pengguna dan proyek. Saya menggunakan nama domain femmebabe.com, tim nama pengguna, dan nama proyek femmebabe.

ServerSignature Off
ServerTokens Prod
<IfModule mod_ssl.c>
<VirtualHost *:80> 
	Redirect permanent / https://femmebabe.com/
</VirtualHost>
<VirtualHost *:443>
	ServerName femmebabe.com
	ServerAdmin team@femmebabe.com
	DocumentRoot /var/www/html

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
	
	Alias /static /home/team/femmebabe/static
	<Directory /home/team/femmebabe/static>
		Require all granted
	</Directory>

Alias /media/icons /home/team/femmebabe/media/
<Directory /home/team/femmebabe/media>
Require all granted
</Directory>

	<Directory /home/team/femmebabe/femmebabe>
		<Files wsgi.py>
			Require all granted
		</Files>
	</Directory>

	WSGIScriptAlias / /home/team/femmebabe/femmebabe/wsgi.py
	WSGIDaemonProcess femmebabe python-path=/home/team/femmebabe/ python-home=/home/team/femmebabe/venv header-buffer-size=100000000000 user=team
	WSGIProcessGroup femmebabe
	WSGIApplicationGroup %{GLOBAL}
	
	<Directory /home/team/femmebabe/static>
                Options Indexes FollowSymLinks
                AllowOverride All
	</Directory>

	<IfModule mod_rewrite.c>
		RewriteEngine on
		RewriteCond %{REQUEST_URI} \.(css|webp|webm|gif|png|mp3|wav|jpeg|jpg|svg|webp)$ [NC]
		RewriteCond %{HTTP_REFERER} !^https://femmebabe.com/media/.*$ [NC]
		RewriteRule ^(.+?)/$ /media/$1 [F,L]
	</IfModule>

	Include /etc/letsencrypt/options-ssl-apache.conf
	SSLCertificateFile /etc/letsencrypt/live/femmebabe.com/fullchain.pem
	SSLCertificateKeyFile /etc/letsencrypt/live/femmebabe.com/privkey.pem

	Header set X-Frame-Options: "SAMEORIGIN"
	Header set Access-Control-Allow-Origin "https://femmebabe.com"

	TimeOut 60000
	LimitRequestBody 0

	<FilesMatch ".(ico|pdf|flv|jpg|jpeg|png|gif|webp|JPG|JPEG|wav|mp3|mp4|public|js|css|swf|webp|svg)$">
		Header set Cache-Control "max-age=30, public"
	</FilesMatch>
</VirtualHost>
</IfModule>
<IfModule mod_ssl.c>
<VirtualHost *:80>
	ServerName femmebabe.com
	ServerAdmin team@femmebabe.com
	DocumentRoot /var/www/html

	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined

	RewriteEngine on
	RewriteCond %{SERVER_NAME} =femmebabe.com
	RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
</IfModule>
Pastikan untuk mengganti nama proyek, direktori, dan domain dalam kode contoh ini saat mengkonfigurasi server Anda. Sekarang, kita perlu menonaktifkan situs default. Ini bisa dilakukan dengan menggunakan bash.

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
Selanjutnya, kami dapat mengaktifkan situs default dan memuat ulang Apache2, juga menggunakan Bash. Ingatlah untuk menggantikan femmebabe dengan nama file yang Anda nyatakan saat mengedit di/etc/apache2/situs-tersedia/.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Kembali ke domain Anda di Navbar. Anda akan melihat situs yang Anda konfigurasi di browser web Anda. Selamat! Jika Anda tidak melihatnya, Anda mungkin perlu membuat beberapa perubahan. Tinjau dengan cermat pengaturan dalam proyek Anda, konfigurasi Apache, dan pastikan Anda tidak memiliki kesalahan, dan jalankan perintah berikut untuk memeriksa proyek untuk kesalahan.

cd projectname
source venv/bin/activate
python manage.py check
Jika Anda memiliki kesalahan dalam proyek Python Anda, lacaknya ke tempat mereka berada dan memperbaikinya. Anda mungkin tidak dapat melihat semua kesalahan Anda tergantung di mana mereka berada, jadi jika Anda memiliki kesalahan yang hanya mengatakan "populasikan tidak masuk kembali", edit file berikut di lingkungan virtual, registry.py, untuk mengekspos kesalahan.

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Gulir ke baris 83, di mana kesalahan runtime ini dinaikkan (angkat runtimeError ("populate () bukan reentrant")), dan menambahkan komentar sebelum baris ini, kemudian menambahkan, dengan indentation yang sama, self.app_configs = {}. Ini terlihat seperti ini:

            if self.loading:
                # Mencegah panggilan reentrant untuk menghindari menjalankan appconfig.ready ()
                # metode dua kali.
# Naikkan RuntimeError ("Populate () Not Reentrant")
                self.app_configs = {}
            self.loading = True
Anda kemudian dapat memeriksa proyek lagi dan mengekspos kesalahan.

python manage.py check
Kemudian Anda dapat melihat kesalahan dan memperbaikinya. Saat Anda memperbaikinya dan kode dikompilasi tanpa kesalahan, pastikan untuk mengubah file kembali sehingga terlihat seperti ini:

            if self.loading:
                # Mencegah panggilan reentrant untuk menghindari menjalankan appconfig.ready ()
                # metode dua kali.
                raise RuntimeError("populate() isn't reentrant")
# self.app_configs = {}
            self.loading = True
Asalkan server online, ketika kami membuat perubahan lebih lanjut, kami perlu menggunakan perintah berikut untuk memuat ulang server:

sudo systemctl reload apache2
Luar biasa! Tapi bagaimana dengan mengirim surat? Untuk mulai mengirim email, pertama -tama kita harus memperbarui konfigurasi domain. Ini harus ada di panel DNS Anda di Squarespace, atau pendaftar nama domain apa pun yang Anda pilih. Kami juga perlu menginstal dan menambahkan konfigurasi, dan menjalankan beberapa perintah. Pertama, mari kita dapatkan alamat IPv6 dari server. Kami akan membuka DNS Anda dan menambahkan catatan. Untuk mendapatkan alamat IPv6 server, gunakan perintah ini:

ip -6 addr
Sekarang, kami dapat menambahkan catatan berikut ke pengaturan DNS. Catatan saya terlihat seperti ini. Namun, untuk catatan Anda, Anda harus mengganti alamat IP dengan IP Anda (bukan 75.147.182.214, itu milik saya). Tambahkan juga domain Anda sebagai pengganti femmebabe.com, serta alamat IPv6 Anda yang ditemukan dengan perintah sebelumnya (Anda tidak dapat menggunakan milik saya, Fe80 :: 725a: FFF: FE49: 3E02). Jangan khawatir tentang domainkey untuk saat ini, ini dibuat ketika kami mengatur postfix, server surat, dengan opendkim, dan mencetak kunci. Kami akan mengkonfigurasi ini yang terakhir. @ A N/a 75.147.182.214 @ MX 10 femmebabe.com @ Ptr N/a femmebabe.com @ Txt N/a Txt @ v = spf1 mx ip75.147.182.214ip6: fe80 :: 725a: fff: fe49: 3e02 ~ all default._bimi Txt N/a v = bimi1; l = https: //femmebabe.com/media/static/femmeebabe.svg _DMARC Txt N/a V = DMARC1; p = tidak ada sendonly._domainkey Txt N/aSekarang, kita perlu menambahkan beberapa konfigurasi yang bertahan untuk postfix. Yang perlu kami lakukan adalah memastikan kami mengganti nama domain, femmebabe.com, dengan nama domain yang Anda gunakan. Mari kita lihat semua file konfigurasi satu per satu, dan instal di direktori yang disebut konfigurasi dalam proyek kami, untuk menginstal ke OS.

nano config/etc_postfix_main.cf
Tambahkan teks ini ke file

# Lihat /usr/share/postfix/main.cf.dist untuk versi yang lebih lengkap dan lebih lengkap


# Debian Spesifik: Menentukan nama file akan menyebabkan yang pertama
# baris file yang akan digunakan sebagai namanya.  DEBIAN DEFAULT
# IS /etc /MailName.
# Myorigine = /etc /mailname

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
biff = no

# Menambahkan .Domain adalah pekerjaan MUA.
append_dot_mydomain = no

# Unkomment Baris berikutnya untuk menghasilkan peringatan "tertunda surat"
# delay_warning_time = 4h

readme_directory = no

# Lihat http://www.postfix.org/compatibility_readme.html - default ke 3.6 pada
# instalasi baru.
compatibility_level = 3.6



# Parameter TLS
smtpd_tls_cert_file=/etc/letsencrypt/live/femmebabe.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/femmebabe.com/privkey.pem
smtpd_tls_security_level=may

smtp_tls_CApath=/etc/ssl/certs
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

smtpd_relay_restrictions = permit_sasl_authenticated, defer_unauth_destination
myhostname = femmebabe.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = femmebabe.com, localhost, $myhostname
smtp_helo_name = femmebabe.com
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all

# Konfigurasi Milter
milter_default_action = accept
milter_protocol = 6
smtpd_milters = local:/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

smtp_tls_security_level = encrypt
smtp_tls_loglevel = 1

virtual_transport=lmtp:unix:private/dovecot-lmtp

smtpd_sasl_path = private/auth
Konfigurasi berikutnya!

nano config/etc_postfix_master.cf
Tambahkan baris ini:

# 
# File Konfigurasi Proses Master Postfix.  Untuk detail tentang format
# dari file, lihat halaman manual master (5) (perintah: "man 5 master" atau
# On-line: http://www.postfix.org/master.5.html).
# 
# Jangan lupa untuk mengeksekusi "Reload postfix" setelah mengedit file ini.
# 
# ==================================================== =========================
# Jenis Layanan Private Unpriv Chroot Wakeup MaxProc Command + Args
# (ya) (ya) (tidak) (tidak pernah) (100)
# ==================================================== =========================
smtp      inet  n       -       y       -       -       smtpd
# smtp inet n - y - 1 postscreen
# SMTPD Pass - - Y - - SMTPD
# Dnsblog unix - - y - 0 dnsblog
# tlsproxy unix - - y - 0 tlsproxy
# Pilih satu: Aktifkan pengiriman hanya untuk klien loopback, atau untuk klien mana pun.
# 127.0.0.1:submission inet n - y - - smtpd
submission inet n       -       y       -       -       smtpd
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
# -O syslog_name = postfix/kiriman
# -O smtpd_tls_security_level = enkripsi
# -O smtpd_sasl_auth_enable = ya
# -O smtpd_tls_auth_only = ya
# -O SMTPD_RECT_UNLISTED_RECIPIENT = no
# -O SMTPD_CLIENT_RESTICTIONS = $ MUA_CLIENT_RESTIons
# -O SMTPD_HELO_RESTRICTIONS = $ MUA_HELO_RESTIons
# -O SMTPD_SENDER_RESTIONS = $ MUA_SENDER_RESTRICTIONS
# -O smtpd_recipient_trastrictions =
# -O smtpd_relay_restrictions = empit_sasl_authenticated, tolak
# -O milter_macro_daemon_name = berasal
# Pilih satu: Aktifkan SMTP hanya untuk klien loopback, atau untuk klien mana pun.
# 127.0.0.1:smtps inet n - y - - smtpd
# smtps inet n - y - - smtpd
# -O syslog_name = postfix/smtps
# -O smtpd_tls_wrappermode = ya
# -O smtpd_sasl_auth_enable = ya
# -O SMTPD_RECT_UNLISTED_RECIPIENT = no
# -O SMTPD_CLIENT_RESTICTIONS = $ MUA_CLIENT_RESTIons
# -O SMTPD_HELO_RESTRICTIONS = $ MUA_HELO_RESTIons
# -O SMTPD_SENDER_RESTIONS = $ MUA_SENDER_RESTRICTIONS
# -O smtpd_recipient_trastrictions =
# -O smtpd_relay_restrictions = empit_sasl_authenticated, tolak
# -O milter_macro_daemon_name = berasal
# 628 INET N - Y - - QMQPD
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
# Qmgr unix n - n 300 1 oqmgr
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
# -O smtp_helo_timeout = 5 -o smtp_connect_timeout = 5
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd
# 
# ==================================================== ===================
# Antarmuka ke perangkat lunak non-postfix. Pastikan untuk memeriksa manual
# Halaman dari perangkat lunak non-postfix untuk mengetahui opsi apa yang diinginkannya.
# 
# Banyak layanan berikut menggunakan pengiriman pipa postfix (8)
# agen.  Lihat halaman Pipa (8) Wanita untuk informasi tentang $ {penerima}
# dan opsi amplop pesan lainnya.
# ==================================================== ===================
# 
# Maildrop. Lihat file postfix maildrop_readme untuk detailnya.
# Juga tentukan di main.cf: maildrop_destination_recipient_limit = 1
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# ==================================================== ===================
# 
# Versi Cyrus terbaru dapat menggunakan entri "LMTP" Master.CF yang ada.
# 
# Tentukan dalam cyrus.conf:
# lmtp cmd = "lmtpd -a" listen = "localhost: lmtp" proto = tcp4
# 
# Tentukan di main.cf satu atau lebih dari yang berikut:
# mailbox_transport = lmtp: inet: localhost
# Virtual_transport = lmtp: inet: localhost
# 
# ==================================================== ===================
# 
# Cyrus 2.1.5 (Amos Gouaux)
# Juga tentukan di main.cf: cyrus_destination_recipient_limit = 1
# 
# Cyrus unix - n n - - pipa
# flags = drx user = cyrus arg =/cyrus/bin/pengiriman -e -r $ {pengirim} -m $ {ekstensi} $ {user}
# 
# ==================================================== ===================
# Contoh pengiriman lama melalui Cyrus.
# 
# Old -Cyrus unix - n n - - pipa
# Flags = r user = cyrus argv =/cyrus/bin/pengiriman -e -m $ {ekstensi} $ {user}
# 
# ==================================================== ===================
# 
# Lihat file postfix uucp_readme untuk detail konfigurasi.
# 
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# 
# Metode pengiriman eksternal lainnya.
# 
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FRX user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}
Dan konfigurasi OpenDKIM. Opendkim mengidentifikasi server email dengan kunci domain untuk membuatnya lebih aman. Tanpa itu, surat tidak ditandatangani dan mungkin tidak sampai ke kotak masuk.

nano config/etc_default_opendkim
Tambahkan baris ini:

# Catatan: Ini adalah file konfigurasi warisan. Itu tidak digunakan oleh opendkim
# Layanan Systemd. Harap gunakan parameter konfigurasi yang sesuai di
# /etc/opendkim.conf sebagai gantinya.
# 
# Sebelumnya, orang akan mengedit pengaturan default di sini, dan kemudian mengeksekusi
# /lib/opendkim/opendkim.service.generate untuk menghasilkan file override systemd ke
# /etc/systemd/system/opendkim.service.d/override.conf dan
# /etc/tmpfiles.d/opendkim.conf. Meskipun ini masih mungkin, sekarang
# Direkomendasikan untuk menyesuaikan pengaturan langsung di /etc/opendkim.conf.
# 
# Daemon_opts = ""
# Ubah ke/var/spool/postfix/run/opendkim untuk menggunakan soket unix dengan
# Postfix dalam chroot:
# Rundir =/var/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Tidak berkomentar untuk menentukan soket alternatif
# Perhatikan bahwa pengaturan ini akan mengganti nilai soket apa pun di opendkim.conf
# bawaan:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Dengarkan semua antarmuka di port 54321:
# Soket = inet: 54321
# Dengarkan Loopback di port 12345:
# Soket = inet: 12345@localhost
# Dengarkan adalah 192.0.2.1 adalah port 12345:
# Socket = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

nano config/etc_dovecot_conf.d_10-master.conf
Tambahkan baris ini:

0-master.conf 
# Default_process_limit = 100
# default_client_limit = 1000

# Batas Default VSZ (Ukuran Memori Virtual) untuk proses layanan. Ini terutama
# dimaksudkan untuk menangkap dan membunuh proses bocor itu sebelum mereka makan
# semuanya.
# default_vsz_limit = 256m

# Pengguna login digunakan secara internal oleh proses login. Ini yang paling tidak dipercaya
# Pengguna di Sistem Dovecot. Seharusnya tidak memiliki akses ke apa pun.
# default_login_user = devenull

# Pengguna internal digunakan oleh proses yang tidak mampu. Itu harus terpisah dari
# Pengguna Masuk, sehingga proses login tidak dapat mengganggu proses lain.
# default_internal_user = dovecot

service imap-login {
  inet_listener imap {
    # Port = 143
  }
  inet_listener imaps {
    # Port = 993
    # SSL = ya
  }

  # Jumlah koneksi yang harus ditangani sebelum memulai proses baru. Khas
  # Satu -satunya nilai yang berguna adalah 0 (tidak terbatas) atau 1. 1 lebih aman, tetapi 0
  # lebih cepat. <doc/wiki/loginprocess.txt>
  # service_count = 1

  # Jumlah proses untuk selalu menunggu lebih banyak koneksi.
  # Proses_min_avail = 0

  # Jika Anda mengatur service_count = 0, Anda mungkin perlu menumbuhkan ini.
  # Vsz_limi = $ default_vsz_limit
}

service pop3-login {
  inet_listener pop3 {
    # Port = 110
  }
  inet_listener pop3s {
    # Port = 995
    # SSL = ya
  }
}

service submission-login {
  inet_listener submission {
    # Port = 587
  }
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    group = postfix
    mode = 0666
    user = postfix
  }

  # Buat pendengar Inet hanya jika Anda tidak dapat menggunakan soket UNIX di atas
  # inet_lister lmtp {
    # Hindari membuat LMTP terlihat untuk seluruh internet
    # Alamat =
    # port =
  # }
}

service imap {
  # Sebagian besar memori masuk ke file mmap (). Anda mungkin perlu meningkatkan ini
  # Batasi jika Anda memiliki kotak surat besar.
  # vsz_limit = $ default_vsz_limit

  # Max. Jumlah proses IMAP (koneksi)
  # Proses_limit = 1024
}

service pop3 {
  # Max. Jumlah proses POP3 (koneksi)
  # Proses_limit = 1024
}

service submission {
  # Max. Jumlah proses pengiriman SMTP (koneksi)
  # Proses_limit = 1024
}

service auth {
  # AUTH_SOCKET_PATH menunjuk ke soket userdb ini secara default. Biasanya
  # Digunakan oleh Dovecot-LlA, Doveadm, mungkin proses IMAP, dll. Pengguna yang memiliki
  # Izin lengkap untuk soket ini bisa mendapatkan daftar semua nama pengguna dan
  # Dapatkan hasil pencarian pengguna semua orang.
  # 
  # Mode 0666 default memungkinkan siapa saja untuk terhubung ke soket, tetapi
  # Pencarian UserDB hanya akan berhasil jika UserDB mengembalikan bidang "UID" itu
  # cocok dengan uid proses penelepon. Juga jika UID atau GID penelepon cocok dengan
  # UID atau GID SOCKET Pencarian berhasil. Hal lain menyebabkan kegagalan.
  # 
  # Untuk memberikan izin lengkap penelepon untuk mencari semua pengguna, atur mode ke
  # sesuatu yang lain dari 0666 dan dovecot memungkinkan kernel menegakkan
  # Izin (mis. 0777 memungkinkan semua orang izin penuh).
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # Proses pekerja auth dijalankan sebagai root secara default, sehingga dapat mengakses
  # /etc/shadow. Jika ini tidak perlu, pengguna harus diubah menjadi
  # $ default_interal_user.
  # Pengguna = root
}

service dict {
  # Jika proxy DICT digunakan, proses surat harus memiliki akses ke soketnya.
  # Misalnya: mode = 0660, grup = vmail dan global mail_access_groups = vmail
  unix_listener dict {
    # Mode = 0600
    # Pengguna =
    # grup =
  }
}
Sekali lagi, pastikan untuk mengganti domain di semua file ini, femmebabe.com, dengan domain yang Anda pilih. Edit file berikutnya, konfigurasi dovecot,

nano config/etc_dovecot_dovecot
Dan tambahkan baris ini

## File Konfigurasi Dovecot

# Jika Anda sedang terburu -buru, lihat http://wiki2.dovecot.org/quickconfiguration

# Perintah "Doveconf -n" memberikan output bersih dari pengaturan yang diubah. Gunakan itu
# Alih -alih menyalin & menempelkan file saat memposting ke milis Dovecot.

# '# 'Karakter dan segalanya setelah diperlakukan sebagai komentar. Ruang ekstra
# dan tab diabaikan. Jika Anda ingin menggunakan salah satu dari ini secara eksplisit, letakkan
# value inside quotes, eg.: key = "# char dan trailing whitespace "

# Sebagian besar pengaturan (tetapi tidak semua) dapat ditimpa dengan berbagai protokol dan/atau
# Sumber/tujuan IP dengan menempatkan pengaturan di dalam bagian, misalnya:
# Protocol imap {}, lokal 127.0.0.1 {}, jarak 10.0.0.0/8 {}

# Nilai default ditampilkan untuk setiap pengaturan, itu tidak diperlukan untuk tidak mengkomentasikan
# itu. Ini adalah pengecualian untuk ini: tidak ada bagian (mis. Namespace {})
# atau pengaturan plugin ditambahkan secara default, mereka hanya terdaftar sebagai contoh.
# Jalur juga hanya contoh dengan default nyata yang didasarkan pada konfigurasi
# opsi. Jalur yang tercantum di sini adalah untuk configure --prefix =/usr
# --sysconfdir =/etc ---localstatedir =/var

# Aktifkan protokol yang diinstal
!include_try /usr/share/dovecot/protocols.d/*.protocol

# Daftar IP atau host yang dipisahkan koma tempat mendengarkan untuk koneksi.
# "*" mendengarkan semua antarmuka IPv4, "::" Mendengarkan semua antarmuka IPv6.
# Jika Anda ingin menentukan port non-default atau sesuatu yang lebih kompleks,
# Edit conf.d/master.conf.
# Dengarkan = *, ::

# Direktori dasar tempat menyimpan data runtime.
# base_dir =/var/run/doecot/

# Nama contoh ini. Dalam Multi-Instance Setup Doveadm dan perintah lainnya
# dapat menggunakan -i <stalle_name> untuk memilih instance mana yang digunakan (alternatif
# ke -c <igig_path>). Nama contoh juga ditambahkan ke proses dovecot
# dalam output PS.
# instance_name = dovecot

# Pesan Salam untuk Klien.
# LOGIN_GREETING = DOVECOT SIAP.

# Daftar Rentang Jaringan Tepercaya yang Dipisahkan Ruang. Koneksi dari ini
# IP diizinkan untuk mengesampingkan alamat dan port IP mereka (untuk penebangan dan
# untuk pemeriksaan otentikasi). disable_plaintext_auth juga diabaikan
# jaringan ini. Biasanya Anda akan menentukan server proxy IMAP Anda di sini.
# login_trusted_networks =

# Daftar Soket Pemeriksaan Akses Login yang Dipisahkan (mis. TCPWRAP)
# login_access_sockets =

# Dengan proxy_maybe = ya jika tujuan proxy cocok dengan IP ini, jangan lakukan
# proksi. Ini tidak diperlukan secara normal, tetapi mungkin berguna jika tujuan
# IP adalah mis. IP penyeimbang beban.
# auth_proxy_self =

# Tampilkan lebih banyak judul proses verbose (dalam PS). Saat ini menunjukkan nama pengguna dan
# Alamat IP. Berguna untuk melihat siapa yang sebenarnya menggunakan proses IMAP
# (Misalnya kotak surat bersama atau jika UID yang sama digunakan untuk beberapa akun).
# verbose_proctitle = no

# Jika semua proses dibunuh ketika proses master dovecot dimatikan.
# Mengatur ini ke "tidak" berarti dovecot dapat ditingkatkan tanpa
# memaksa koneksi klien yang ada untuk ditutup (meskipun itu juga bisa
# Masalah jika peningkatannya adalah mis. karena perbaikan keamanan).
# shutdown_clients = ya

# Jika bukan nol, jalankan perintah surat melalui banyak koneksi ke server DOVEADM,
# Alih -alih menjalankannya secara langsung dalam proses yang sama.
# doveadm_worker_count = 0
# Unix Socket atau Host: Port Digunakan untuk Menghubungkan ke Doveadm Server
# doveadm_socket_path = doveadm-server

# Daftar Variabel Lingkungan yang Dipisahkan Ruang yang disimpan di Dovecot
# startup dan diturunkan ke semua proses anaknya. Anda juga bisa memberi
# KEY = pasangan nilai untuk selalu mengatur pengaturan tertentu.
# Import_environment = tz

## 
## Pengaturan Server Kamus
## 

# Kamus dapat digunakan untuk menyimpan kunci = daftar nilai. Ini digunakan oleh beberapa orang
# plugin. Kamus dapat diakses secara langsung atau meskipun a
# Server Kamus. Dict Block Dict Names Dictionary Names to URIS berikut
# Saat server digunakan. Ini kemudian dapat dirujuk menggunakan URI dalam format
# "Proxy :: <name>".

dict {
  # kuota = mysql: /etc/dovecot/dovecot-dict-sql.conf.ext
}

# Sebagian besar konfigurasi yang sebenarnya disertakan di bawah ini. Nama file
# pertama kali diurutkan berdasarkan nilai ASCII mereka dan diuraikan dalam urutan itu. 00-prefix
# Dalam nama file dimaksudkan untuk membuatnya lebih mudah untuk memahami pemesanan.
!include conf.d/*.conf

# File konfigurasi juga dapat mencoba dimasukkan tanpa memberikan kesalahan jika
# itu tidak ditemukan:
!include_try local.conf

passdb {
  driver = passwd-file
  args = /etc/dovecot/passwd
}
userdb {
  driver = passwd
}

protocols = imap pop3

# Mengizinkan Dovecot mendengarkan semua koneksi input (IPv4 / IPv6)

listen = *, ::
Tambahkan kata sandi untuk pengguna dovecot:

nano config/etc_dovecot_passwd
Bagian pertama dari file, sebelum usus besar, adalah nama pengguna. Bagian terakhir, "YourPassword", menunjukkan kata sandi yang ingin Anda berikan kepada server surat Anda.

team:{plain}yourpassword
Selanjutnya, konfigurasi opendkim

nano config/etc_opendkim.conf
Dan tambahkan baris ini:

# Ini adalah konfigurasi dasar untuk menandatangani dan memverifikasi. Itu bisa dengan mudah
# Diadaptasi agar sesuai dengan instalasi dasar. Lihat opendkim.conf (5) dan
# /usr/share/doc/opendkim/examples/opendkim.conf.sample untuk lengkap
# Dokumentasi parameter konfigurasi yang tersedia.

Syslog			yes
SyslogSuccess		yes
# Logenghy tidak

# Parameter Penandatanganan dan Verifikasi Umum. Di Debian, header "dari" adalah
# Division, karena sering kali merupakan kunci identitas yang digunakan oleh sistem reputasi
# dan dengan demikian agak sensitif keamanan.
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# Menandatangani domain, pemilih, dan kunci (diperlukan). Misalnya, lakukan penandatanganan
# untuk domain "example.com" dengan pemilih "2020" (2020._domainkey.example.com),
# Menggunakan kunci pribadi yang disimpan di /etc/dkimkeys/example.private. Lebih granular
# Opsi Pengaturan dapat ditemukan di /usr/share/doc/opendkim/readme.opendkim.
# Domain example.com
# Selector 2020
# Keyfile /etc/dkimkeys/example.private

# Di Debian, Opendkim berjalan sebagai pengguna "Opendkim". Umask 007 diperlukan saat
# Menggunakan soket lokal dengan MTA yang mengakses soket sebagai yang tidak istimewa
# Pengguna (misalnya, postfix). Anda mungkin perlu menambahkan pengguna "postfix" ke grup
# "Opendkim" dalam hal ini.
UserID			opendkim
UMask			007

# Soket untuk koneksi MTA (diperlukan). Jika MTA berada di dalam penjara chroot,
# Harus dipastikan bahwa soket dapat diakses. Di Debian, postfix berjalan
# chroot in/var/spool/postfix, oleh karena itu soket unix harus
# dikonfigurasi seperti yang ditunjukkan pada baris terakhir di bawah ini.
# Socket lokal: /run/opendkim/opendkim.sock
# Socket Inet: 8891@localhost
# Socket Inet: 8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Host untuk menandatangani daripada memverifikasi, default adalah 127.0.0.1. Lihat
# Bagian Operasi Opendkim (8) untuk informasi lebih lanjut.
# Internalhosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# Jangkar Trust memungkinkan DNSSEC. Di Debian, file jangkar trust disediakan
# oleh paket DNS-Root-Data.
TrustAnchorFile		/usr/share/dns/root.key
# Nameserver 127.0.0.1

# Peta domain di dari alamat ke kunci yang digunakan untuk menandatangani pesan
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Satu set host internal yang suratnya harus ditandatangani
InternalHosts       /etc/opendkim/trusted.hosts

nano config/etc_default_opendkim
Dan tambahkan baris ini

# Catatan: Ini adalah file konfigurasi warisan. Itu tidak digunakan oleh opendkim
# Layanan Systemd. Harap gunakan parameter konfigurasi yang sesuai di
# /etc/opendkim.conf sebagai gantinya.
# 
# Sebelumnya, orang akan mengedit pengaturan default di sini, dan kemudian mengeksekusi
# /lib/opendkim/opendkim.service.generate untuk menghasilkan file override systemd ke
# /etc/systemd/system/opendkim.service.d/override.conf dan
# /etc/tmpfiles.d/opendkim.conf. Meskipun ini masih mungkin, sekarang
# Direkomendasikan untuk menyesuaikan pengaturan langsung di /etc/opendkim.conf.
# 
# Daemon_opts = ""
# Ubah ke/var/spool/postfix/run/opendkim untuk menggunakan soket unix dengan
# Postfix dalam chroot:
# Rundir =/var/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Tidak berkomentar untuk menentukan soket alternatif
# Perhatikan bahwa pengaturan ini akan mengganti nilai soket apa pun di opendkim.conf
# bawaan:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Dengarkan semua antarmuka di port 54321:
# Soket = inet: 54321
# Dengarkan Loopback di port 12345:
# Soket = inet: 12345@localhost
# Dengarkan adalah 192.0.2.1 adalah port 12345:
# Socket = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Ketika kami siap mengatur server postfix kami, kami akan menjalankan kode di bawah ini, dengan nama domain yang sesuai tertanam. Mulailah dengan membuat skrip

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
Sekarang, di Nano, editor teks, edit file ini sehingga termasuk nama domain Anda alih -alih femmebabe.com.

# ! / bin / Bash
# Pengaturan postfix
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
sudo cat /etc/opendkim/keys/femmebabe.com/sendonly.txt | tr -d '\n' | sed 's/\s//g' | sed 's/""//g' | awk -F'[)(]' '{print $2}'
Sekarang, jalankan skrip yang sudah selesai untuk mengonfigurasi postfix, opendkim dan dovecot.

./scripts/postfixsetup
Setelah skrip ini berjalan, salin baris terakhir yang dicetak dan tempel ke konfigurasi DNS Anda sebagai nilai untuk sendonly._domainkey. Ini adalah kunci Opendkim yang digunakan untuk mengidentifikasi domain Anda saat mengirim surat yang aman. Luar biasa! Dalam beberapa hari, Anda harus dapat mengirim surat dari server asalkan semuanya dikonfigurasi dengan benar. Jika Anda baru saja mengonfigurasi DNS untuk server email Anda, perlu waktu kurang dari 72 jam untuk diperbarui catatan. Biasanya jauh lebih cepat. Anda dapat memeriksa apakah server Anda berfungsi dengan menggunakan perintah ini, disediakan email Anda:

echo “test” | mail -s “Test Email” youremail@gmail.com
Jika semuanya tampak berfungsi dengan benar, Anda harus dapat mengirim email dengan server Anda. Jika tidak berfungsi, cobalah melihat log untuk melihat apa kesalahannya.

tail –lines 150 /var/log/mail.log
Ini akan menawarkan informasi verbose tentang surat yang dikirim oleh server dan apakah itu berfungsi dengan baik. Anda harus dapat melihat email di kotak masuk Anda juga, jika tidak ada, periksa folder spam Anda. Anda juga perlu mengonfigurasi pengaturan Anda di pengaturan Anda.py sehingga server email Anda dapat berbicara dengan aplikasi Django Anda, proyek. Tambahkan atau ganti baris ini di pengaturan Anda

EMAIL_HOST = DOMAIN
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = 'team@femmebabe.com'
EMAIL_HOST_USER = 'team' # 'Love@mamasheen.com'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
Perhatikan bahwa kami menggunakan file konfigurasi untuk mendapatkan kata sandi. Mari kita muat file ini di pengaturan seperti itu, di awal file.:

import os
import json

# Buka dan Muat Konfigurasi
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Mari kita buat file ini dan tambahkan tombol rahasia untuk itu, serta kata sandi email. Untuk menghasilkan kunci rahasia, gunakan perintah ini, dengan panjang apa pun yang Anda suka di akhir:

openssl rand -base64 64
Sekarang, salin teks yang OpenSSL dihasilkan dan edit /etc/config.json

sudo nano /etc/config.json
Tambahkan baris berikut ke file Anda, dengan kunci yang OpenSSL dihasilkan sebagai kunci rahasia.

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
Format JSON sederhana dan mudah digunakan, kami dapat menyatakan kunci lain yang ingin kami gunakan dalam proyek kami dengan cara ini juga, dan membuat mereka terpisah dari direktori proyek kami sehingga pengguna lain tidak dapat menulis kepada mereka dan sehingga mereka tidak dapat dibaca dari direktori proyek kami saja. Ini adalah praktik yang disarankan untuk kunci API, yang akan kami gunakan lebih dari beberapa di sini. Anda juga ingin mencadangkan proyek Anda untuk memastikan semuanya disimpan dan Anda dapat memulihkan pekerjaan Anda nanti bahkan jika Anda tidak lagi ingin menyewa server.

sudo backup
Sekarang, coba kirim email HTML dari server web, asalkan mengirim satu dari baris perintah berfungsi. Permintaan contoh pengguna Anda di shell, dan kirim email HTML ke pengguna itu melalui Django. Ubah nama saya di kode, Charlotte, menjadi nama pengguna Anda.

python manage.py shell
from django.contrib.auth.models import User
u = User.objects.get(username='Charlotte')
from users.email import send_welcome_email
send_welcome_email(u)
exit()
Jika perintah pertama tidak berfungsi, pastikan untuk digunakan

source venv/bin/activate
Asalkan semuanya diatur dengan benar, sekarang Anda akan mendapatkan email selamat datang di kotak surat Anda yang dikirim oleh aplikasi web Anda. Kerja bagus! Anda sudah jauh. Saya ingin menambahkan, jika Anda pernah berjuang dengan kesalahan sama sekali saat mengerjakan proyek seperti ini, jangan ragu untuk mencari jawaban dan meminta bantuan. Google, di antara mesin pencari lainnya, adalah sumber yang bagus untuk mencari bantuan pemrograman. Cukup cari kesalahan yang Anda dapatkan, dan Anda akan dapat melihat bagaimana orang lain menyelesaikan masalah. Juga, Anda dipersilakan untuk menghubungi saya, pendidik Anda (guru, profesor, tutor), setiap rekan di internet yang tersedia untuk bantuan pemrograman, atau berkonsultasi dengan buku ini lagi atau sumber daya lain untuk menemukan solusi untuk masalah yang Anda alami. Saya mengerti ini tidak mudah, tetapi bahkan jika Anda telah membaca sejauh ini dan tidak menulis kode apa pun, Anda belajar banyak tentang membangun aplikasi web dari awal. Menepuk punggung diri Anda, Anda melakukan yang hebatpekerjaan. Terima kasih telah meluangkan waktu untuk membaca panduan pengembangan web edisi ketiga ini. Dalam edisi mendatang, saya akan memasukkan lebih banyak contoh penting yang dibahas di awal dokumen dan kami akan menyelam lebih dalam ke dunia pengembangan perangkat lunak dan perangkat keras. Tetap disini untuk apa yang akan datang, dan saya berharap dapat mengajari Anda cara membangun perangkat lunak yang luar biasa. Sampai jumpa di berikutnya






Menutup
Halaman 1
Melompat
Lihat artikel lengkap
Lanjutkan membaca

Membeli | Beli dengan crypto



https://glamgirlx.com/id/practical-web-based-deep -


(Klik atau ketuk untuk mengunduh gambar)
Hiburan profesional, foto, video, audio, streaming langsung dan gameplay santai, serta pemindaian ID, pengembangan web dan layanan surrogacy.

Tinggalkan saya tip dalam bitcoin menggunakan alamat ini: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

Ketentuan Layanan