Örnek olarak pratik web tabanlı derin öğrenme ve güvenlik

DaisyProfil fotoğrafı

İle Daisy

Örnek olarak pratik web tabanlı derin öğrenme ve güvenlik Üçüncü baskı Charlotte Harper 3 Temmuz 2024 Önsöz: Web için yazılım oluşturmada güvenlik hususları, herhangi bir Web geliştiricisinin planının ve yürütülmesinin önemli bir parçasıdır, ancak pratik amaçlar için güvenilir, istikrarlı ve kullanışlı bir prototip tasarlar. DOM (Belge Nesne İşaretlemesi), HTML, JavaScript ve CSS'nin yanı sıra Python, C/C ++, Java ve Bash uygulayan arka uç yazılımı, web geliştiricilerine ifade eden çok çeşitli projeler oluşturmak için özgürlük ve güç verir. Yaratıcılık, kullanım kolaylığı ve işlevselliği sağlayın, alçakgönüllülük ve karakteri tasvir edin ve kullanım kolaylığı, hepsi ortalama Joe için cazip olan kolaylık ve önemli hizmetler sağlar, son kullanıcı zaman öldürmek veya internette bir şeyler yapmak isteyen son kullanıcı Genellikle dokunmatik ekranlı bir akıllı telefon cihazında. Çoğu insan sıfırdan bir web sitesi oluşturmak istediklerinde nereden başlayacağını bile bilemezdi,Başka bir kişinin web sitesinde başlama ve zamana basma düğmelerini boşa harcamadan faydalı bir şey inşa etmek için en son güçlü araçlara sahip olabileceklerinde işlevsellik, güvenilirlik, kullanım kolaylığı ve özellikle yaratıcılık açısından sınırlı bir şey inşa etme eğilimindedirler ve Özellikle yazılıma pahalı abonelikler için para harcamak, kullanım kolaylığı ve esneklik sınırlamaları göz önüne alındığında, çok az insan yine de kullanmak istedi. Bu kitabı okumak ve size ne öğretmek istediğimi öğrenmek için birkaç dakikanız varsa, hatta benimle hedefleriniz hakkında kişisel olarak konuşun ve doğru yönde biraz rehberlik edin ve kendi yazılımınızı kodlamayı ve yazmayı öğrenmeye motive iseniz , bu kitabı eve götürün ve bir sonraki etkili, güçlü, aerodinamik ve önemli web uygulamasını oluşturmayı öğrenmek için biraz zaman ayırın, hepsi sizin içinizde olan ve tam olarak istediğiniz şeyi yapan ve kitlenizin ihtiyaçlarını karşılayan bir web sitesi. Benim hakkımda: Ben geniş bir yazılım geliştiricisiyimC/C ++, Java, Python, HTML, CSS ve JavaScript'te deneyim. İnsanların kullanmak, ziyaret etmek ve hatta sadece zaman öğrenmek, yeniden yaratmak ve öldürmek için kullanmaya bağımlı olmak isteyen web siteleri oluşturuyorum ve en önemlisi yazılım satıyorum. Bir web sitesinin nasıl görünmesini ve işlev görmesini istediğine dair bir fikriniz varsa, sizinkiyle tanışırken kendi ihtiyaçlarımı karşılayabilirim, böylece bir web sitesi çalıştırmanın maliyetlerini karşılamaya istekli olursunuz, böylece beni desteklemeye istekliydiniz, Size bir sonraki YouTube, Tiktok, Twitter, Google ve hatta yalnızca erişebileceğiniz bir yüksek teknoloji güvenlik uygulamasını oluştururdum. Size zamanımı satmaya çalışmak yerine, sizinkini satın almaya çalışıyorum: Sizi zaten var olan bilgilerle kendiniz (web sitesi) oluşturmak için konuşmak istiyorum ve bağımsız bir yazılım geliştiricisi olmanız için neye ihtiyacınız olduğunu öğretmek istiyorum, Girişimci, istediğiniz alanda başarılı bir kariyere öncülük ediyor. Ve net olalım, size verdiğim eğitim gayri resmi olacak. Okula gidebilir ve tüm bunları birRmal eğitimi, hatta bu kitabı okulda okuyun, ödevlerinizi tamamlayın ve eğitiminizden çok şey alın, ancak sizi resmen sıcak koltuğa koymayacağım ve ödevleri tamamlamanızı istemeyeceğim. Ben senin profesörün değilim, beni kendi kişisel başarınızla yönlendirilen bir kariyere doğru yönlendirmek isteyen bir arkadaş gibi düşünebilirsiniz. Ve ben de size başarı satmıyorum, zamanınızla satın almanız gerekecek. Kod yapmayı öğrenmenin dik bir öğrenme eğrisi vardır ve asla kolay değildi, hatta olması gerekmiyordu. Mümkün olduğunca çok çalışmanız ve uygulamaları öğrenmek ve oluşturmak için hayal kırıklığına uğradığınızda bile denemeye ve başarısız olmaya devam etmeniz gerekir. Kodun kendisinde. Kod, programcının hata mesajlarını vermek için tasarlanmış bir derleyici tarafından çalıştırılır ve bunlar, hatayı arama motorunuza kopyalayıp diğer kişilerin örneklerini okumuş olsanız bile, nasıl kod yapacağınızı öğretecektir. Ve söylemeliyim ki, son derece zengin, akıllı, başarılı olmanıza gerek yok,tr detay odaklı veya bir uygulama oluşturmak için düzenlenmiş. Bilgisayar sizin için bu kuruluşla ilgileniyor. Sadece deneme yanılma yoluyla ısrar etmeniz, odaklanmanız ve yaptığınız işte çok çalışmanız gerekir ve yaptığınız işin tamamında çok başarılı bir kariyere sahip olacaksınız. Ben kimim: Son bölümün daha çok öğrenme ve bu kitaptan bir yol almanızla ilgili olduğunun farkındayım. Ben tam olarak kimim? Bu karmaşık bir soru. Kendim, kendimi kodlamamı veya yazmamı zorlaştırabilecek tıbbi koşullardan muzdarip olduğum için, kendimi tanıtmak söz konusu olduğunda hayatımı zorlaştıran sosyalleşme ve kimlik sorunları ile ilgili zorluklar sunmayı zorlaştırdığım için belirsizim. . Kısacası, bu kitabı okuyorsanız, onu eve getirdiniz, çünkü bunun içinden geçip yararlı olduğunu düşündünüz, ya da bu kadar uzakta okumuş olsanız bile, size başarılı olduğunuzu görmek isteyen benzer bir insanım Yaptığın her şey. Ben kendim bir mühendisim, bir yazılımGeliştirici ve bir öğrenci ve ben bu kitabı, büyük bir bulmaca gibi bir araya getiren örnekler bir çalışmaya kopyalamak için örnekler vererek hayatlarını kolaylaştıracak bir el kitabına sahip olarak hayatlarını kolaylaştırmak isteyen diğer öğrenciler için yazıyorum. , iş kolu ne olursa olsun başarıyı artırabilecek kullanışlı, büyük, işlevsel, uyumlu ve ilgi çekici bir uygulama. Büyük ölçüde, yaptığım şey bu: Kendime ve diğer insanların başarılı olmasına yardımcı olacak uygulamalar oluşturuyorum. Ben de bir yazarım, ancak bu, portföyümü yararlı bir belgeye koymak için tamamlamayı planladığım ilk yayınım ve ben de bir sanatçıyım. Bunu sana itiraf edeceğim, ben biraz garip bir insanım. Mükemmel değilim, daha başarılı bir şekilde kendim için bir isim yapmaya çalışmak için kolejlerden ve üniversitelerden ayrılmamı ve devletleri terk etmeme bile yönelik yasa ile çalıştım. Ben doğumda bir kadınım, makyaj yapıyorum, kendimi fotoğraf çekiyorum, elbiseler ve diğer kadın kıyafetleri giyiyorum ve kendimi bilinçli kalıyorumdoğası gereği erkek. Geçmişte webapps yazma ve inşa etmekle mücadele eden diğer insanlarla sorun yaşadım ve bu kitabı daha erken elinize alamadığım için özür dilerim: buna ihtiyacınız var. Benim gibi görünen ve benim gibi çalışan ve aynı şeyi yapan kodu okumak ve yazmak isteyeceksiniz, ancak daha da iyisi, çünkü bu kitabınızı kendiniz gibi bir kitap oluşturmak için klavyenizi ezmek yerine satın almayı göze alabiliyorsanız Bunun için, hayatınızda başarılı olmak için ihtiyacınız olan kaynaklara sahipsiniz. Ailenin büyümesi, sağlık koşulları, doktorlar, medya ve yasa ile ilgili her türlü sorunum vardı ve kodum bölünmüş ve sinirli bir dünyada feminizm ve kadın doğası olan mücadeleyi derinden yansıtıyor. Ancak, bu kitap derinden önem verdiğim bir şey, bebeğim, portföyüm ve geçim kaynağım, bu yüzden metni eve götürdüğünüzde ve benden öğrenmek için dikkatlice gözeneklediğinizde düşünmenizi takdir ediyorum. Lütfen mükemmel değilimKitabın hatalar, revizyonlar ve yeni baskılara sahip olacak ve yazımla başarılı bir deneyim yaşamak için mantıklı beyninizle elinizden gelenin en iyisini düşünmeniz gerekecek. Ayrıca, yazarken zorluklarla karşılaşsanız bile sizin için iyi demek istediğimi anlayın. Bunu şöyle düşünün: Dijital alanda hayal edebileceğiniz her şeyi yapmak için bir bilgisayar sistemi kiralayabildiğinizde, karşılaştığınız tüm bilgileri saklayın, #$%! Yze ve organize edin ve anlamaya gelin, Kaçınılmaz olarak yudumladığınız ve hatta yayınladığınız bilgilerle ilgili zorluklarla karşılaşır. Bunu size söylüyorum çünkü aynı zorluklarla karşılaşıyorum. Bu kitabı kendi sorumluluğunuzda kullanın, güvenli bir ortamda yazılım oluşturmak için kullanabileceğiniz topluluğunuz ve topluluklarınızla birlikte çalışın ve başarısız olduğunuzda veya hatta yanlış bir şekilde başarılı olduğunuzda işleri kişisel olarak almayın: ve neden size bu metni getirebilirim ve ayrılan bir delilik yolunda ayrılmadan başarılı olmanıza yardımcı olabilirimBen, çalışacağımız ağın paralelistik küresel ölçeği sayesinde herkesin küresel ölçekte yaptığı sıradan sorunlarla karşılaşırken mahvolmuş, yırtılmış ve yırtılmış. Sadece birkaç kelimeyle kim olduğuma çok aşina olmayabilirsiniz, ancak okumanızı öneririm, işinizi tamamlamak için kendi projelerinizi oluştururken beni okumaya ve anlamaya devam ederken beni tanıyacaksınız. Profesörleriniz veya öğretmenleriniz size atamadığı sürece, bu kitapta ödev olmayacak, ancak okuduğunuz gibi bir proje portföyü oluşturmanızı ve nasıl yapabileceğinizi gösteren bir Capstone projesi oluşturmanızı tavsiye ediyorum. Öğrendiklerinizi uygulayın. Capstone Projem, önceki projelerimden kod, oluşturduğum ve metodik olarak elle yazmayı öğrendiğim kodu ve bana yardımcı olan çok çeşitli fikir ve ipuçlarını içerdiğinden, bu kitapta okuyacağınız şeylerin çoğunun temelidir. basit bir uygulamayı döndürebileceğim noktayı başarmakUlly, arkadaşınızın veya ailenizin internette, size veya haberlerde reklamı kullandığını görebileceğiniz popüler bir uygulama gibi görünür ve davranır. Bu kitap ne: Bu kitap örnek olarak bir öğreticidir. Kodu burada bulabilirsiniz, kodları nasıl öğreneceğinizi, hata ayıklama ve düzeltme hataları hakkında bilgi, sorun giderme adımları, kodunuzu nasıl yedekleyeceğiniz ve kaydedeceğinize dair talimatlar, kodunuzu kırarsa, kodunuzu sabitlerse, dağıtım yapabilirsiniz. Kodunuz, eğlenceli, ilgi çekici ve bağımlılık yapan etkileşimli web siteleri oluşturun ve kim olduğumu, bunun neden önemli olduğunu ve kendinizi, uygulamanızın ve şirket imajınızı nasıl tasvir edeceğinizi ve oluşturduğunuz yazılımın nasıl tasvir edeceğinizi anlayacaksınız. Son kullanıcılarınız, web sitenizin ziyaretçileri için mümkün olduğunca en çekici olmak için mutlak en iyi ışıkta. Bu kitapta, bir platform ve güvenlik olarak web'e odaklanarak bir dizi yazılım tasarımı örneği göstereceğim. Bir temel oluşturarak öğrenme deneyimini başlatacağızYedekleme ve komut dosyası özellikleri ile UNIX ...
Örnek olarak pratik web tabanlı derin öğrenme ve güvenlik

Örnek olarak pratik web tabanlı derin öğrenme ve güvenlik Üçüncü baskı Charlotte Harper 3 Temmuz 2024 Önsöz: Web için yazılım oluşturmada güvenlik hususları, herhangi bir Web geliştiricisinin planının ve yürütülmesinin önemli bir parçasıdır, ancak pratik amaçlar için güvenilir, istikrarlı ve kullanışlı bir prototip tasarlar. DOM (Belge Nesne İşaretlemesi), HTML, JavaScript ve CSS'nin yanı sıra Python, C/C ++, Java ve Bash uygulayan arka uç yazılımı, web geliştiricilerine ifade eden çok çeşitli projeler oluşturmak için özgürlük ve güç verir. Yaratıcılık, kullanım kolaylığı ve işlevselliği sağlayın, alçakgönüllülük ve karakteri tasvir edin ve kullanım kolaylığı ile birlikte ortalama Joe için cazip olan kolaylık ve önemli hizmetler, son kullanıcı İnternette, genellikle dokunmatik ekranlı bir akıllı telefon cihazında zaman öldürün veya bir şeyler yaptırın. Çoğu insan, bir web sitesi oluşturmak istediklerinde nereden başlayacağınızı bile bilemezdi.Scratch, başka bir kişinin web sitesinde başlama ve zamana basmadan yararlı bir şey inşa etmek için en son güçlü araçlara sahip olabileceklerinde işlevsellik, güvenilirlik, kullanım kolaylığı ve özellikle yaratıcılık açısından sınırlı bir şey inşa etme eğiliminde olurlar. ve özellikle kullanım kolaylığı ve esneklik sınırlamaları göz önüne alındığında, birkaç kişi yazılıma pahalı abonelikler için para harcayarak para harcıyor. Bu kitabı okumak ve size ne öğretmek istediğimi öğrenmek için birkaç dakikanız varsa, hatta benimle hedefleriniz hakkında kişisel olarak konuşun ve doğru yönde biraz rehberlik edin ve kendi yazılımınızı kodlamayı ve yazmayı öğrenmeye motive iseniz , bu kitabı eve götürün ve bir sonraki etkili, güçlü, aerodinamik ve önemli web uygulamasını oluşturmayı öğrenmek için biraz zaman ayırın, hepsi sizin içinizde olan ve tam olarak istediğiniz şeyi yapan ve kitlenizin ihtiyaçlarını karşılayan bir web sitesi. Benim hakkımda: Ben bir yazılım geliştiricisiyimC/C ++, Java, Python, HTML, CSS ve JavaScript'te deneyim yelpazesi. İnsanların kullanmak, ziyaret etmek ve hatta sadece zaman öğrenmek, yeniden yaratmak ve öldürmek için kullanmaya bağımlı olmak isteyen web siteleri oluşturuyorum ve en önemlisi yazılım satıyorum. Bir web sitesinin nasıl görünmesini ve işlev görmesini istediğine dair bir fikriniz varsa, sizinkiyle tanışırken kendi ihtiyaçlarımı karşılayabilirim, böylece bir web sitesi çalıştırmanın maliyetlerini karşılamaya istekli olursunuz, böylece beni desteklemeye istekliydiniz, Size bir sonraki YouTube, Tiktok, Twitter, Google ve hatta yalnızca erişebileceğiniz bir yüksek teknoloji güvenlik uygulamasını oluştururdum. Size zamanımı satmaya çalışmak yerine, sizinkini satın almaya çalışıyorum: Sizi zaten var olan bilgilerle kendiniz (web sitesi) oluşturmak için konuşmak istiyorum ve bağımsız bir yazılım geliştiricisi olmanız için neye ihtiyacınız olduğunu öğretmek istiyorum, Girişimci, istediğiniz alanda başarılı bir kariyere öncülük ediyor. Ve net olalım, size verdiğim eğitim gayri resmi olacak. Okula gidebilir ve tüm bunları birresmi eğitim, hatta bu kitabı okulda okuyun, ödevlerinizi tamamlayın ve eğitiminizden çok şey alın, ancak sizi resmen sıcak koltuğa koymaya ve ödevleri tamamlamanızı istemeyeceğim. Ben senin profesörün değilim, beni kendi kişisel başarınızla yönlendirilen bir kariyere doğru yönlendirmek isteyen bir arkadaş gibi düşünebilirsiniz. Ve ben de size başarı satmıyorum, zamanınızla satın almanız gerekecek. Kod yapmayı öğrenmenin dik bir öğrenme eğrisi vardır ve asla kolay değildi, hatta olması gerekmiyordu. Mümkün olduğunca çok çalışmanız ve uygulamaları öğrenmek ve oluşturmak için hayal kırıklığına uğradığınızda bile denemeye ve başarısız olmaya devam etmeniz gerekir. Kodun kendisinde. Kod, programcının hata mesajlarını vermek için tasarlanmış bir derleyici tarafından çalıştırılır ve bunlar, hatayı arama motorunuza kopyalayıp diğer kişilerin örneklerini okumuş olsanız bile, nasıl kod yapacağınızı öğretecektir. Ve söylemeliyim ki, son derece zengin, akıllı olmanıza gerek yok,Bir uygulama oluşturmak için esas, hatta detay odaklı veya düzenli. Bilgisayar sizin için bu kuruluşla ilgileniyor. Sadece deneme yanılma yoluyla ısrar etmeniz, odaklanmanız ve yaptığınız işte çok çalışmanız gerekir ve yaptığınız işin tamamında çok başarılı bir kariyere sahip olacaksınız. Ben kimim: Son bölümün daha çok öğrenme ve bu kitaptan bir yol almanızla ilgili olduğunun farkındayım. Ben tam olarak kimim? Bu karmaşık bir soru. Kendim, kendimi kodlamamı veya yazmamı zorlaştırabilecek tıbbi koşullardan muzdarip olduğum için, kendimi tanıtmak söz konusu olduğunda hayatımı zorlaştıran sosyalleşme ve kimlik sorunları ile ilgili zorluklar sunmayı zorlaştırdığım için belirsizim. . Kısacası, bu kitabı okuyorsanız, onu eve getirdiniz, çünkü bunun içinden geçip yararlı olduğunu düşündünüz, ya da bu kadar uzakta okumuş olsanız bile, size başarılı olduğunuzu görmek isteyen benzer bir insanım Yaptığın her şey. Ben kendim bir mühendisimGeliştirici ve bir öğrenci ve ben bu kitabı, büyük bir bulmaca gibi bir araya getiren örnekler bir çalışmaya kopyalamak için örnekler vererek hayatlarını kolaylaştıracak bir el kitabına sahip olarak hayatlarını kolaylaştırmak isteyen diğer öğrenciler için yazıyorum. , iş kolu ne olursa olsun başarıyı artırabilecek kullanışlı, büyük, işlevsel, uyumlu ve ilgi çekici bir uygulama. Büyük ölçüde, yaptığım şey bu: Kendime ve diğer insanların başarılı olmasına yardımcı olacak uygulamalar oluşturuyorum. Ben de bir yazarım, ancak bu, portföyümü yararlı bir belgeye koymak için tamamlamayı planladığım ilk yayınım ve ben de bir sanatçıyım. Bunu sana itiraf edeceğim, ben biraz garip bir insanım. Mükemmel değilim, daha başarılı bir şekilde kendim için bir isim yapmaya çalışmak için kolejlerden ve üniversitelerden ayrılmamı ve devletleri terk etmeme bile yönelik yasa ile çalıştım. Ben doğumda bir kadınım, makyaj yapıyorum, kendimi fotoğraf çekiyorum, elbiseler ve diğer kadın kıyafetleri giyiyorum ve kendimi bilinçli kalıyorumkadın doğası gereği. Geçmişte webapps yazma ve inşa etmekle mücadele eden diğer insanlarla sorun yaşadım ve bu kitabı daha erken elinize alamadığım için özür dilerim: buna ihtiyacınız var. Benim gibi görünen ve benim gibi çalışan ve aynı şeyi yapan kodu okumak ve yazmak isteyeceksiniz, ancak daha da iyisi, çünkü bu kitabınızı kendiniz gibi bir kitap oluşturmak için klavyenizi ezmek yerine satın almayı göze alabiliyorsanız Bunun için, hayatınızda başarılı olmak için ihtiyacınız olan kaynaklara sahipsiniz. Ailenin büyümesi, sağlık koşulları, doktorlar, medya ve yasa ile ilgili her türlü sorunum vardı ve kodum bölünmüş ve sinirli bir dünyada feminizm ve kadın doğası olan mücadeleyi derinden yansıtıyor. Ancak, bu kitap derinden önem verdiğim bir şey, bebeğim, portföyüm ve geçim kaynağım, bu yüzden metni eve götürdüğünüzde ve benden öğrenmek için dikkatlice gözeneklediğinizde düşünmenizi takdir ediyorum. Lütfen unutmayınECT, bu kitabın hatalar, revizyonlar ve yeni baskılara sahip olacak ve yazımla başarılı bir deneyim yaşamak için mantıksal beyninizle elinizden gelenin en iyisini düşünmeniz gerekecek. Ayrıca, yazarken zorluklarla karşılaşsanız bile sizin için iyi demek istediğimi anlayın. Bunu şöyle düşünün: Dijital alanda hayal edebileceğiniz her şeyi yapmak için bir bilgisayar sistemi kiralayabildiğinizde, karşılaştığınız tüm bilgileri saklayın, #$%! Yze ve organize edin ve anlamaya gelin, Kaçınılmaz olarak yudumladığınız ve hatta yayınladığınız bilgilerle ilgili zorluklarla karşılaşır. Bunu size söylüyorum çünkü aynı zorluklarla karşılaşıyorum. Bu kitabı kendi sorumluluğunuzda kullanın, güvenli bir ortamda yazılım oluşturmak için kullanabileceğiniz topluluğunuz ve topluluklarınızla birlikte çalışın ve başarısız olduğunuzda veya hatta yanlış bir şekilde başarılı olduğunuzda işleri kişisel olarak almayın: ve neden size bu metni getirebilirim ve bir delilik yolunda ayrılmadan başarılı olmanıza yardımcı olabilirimAves Me harap, yırtılmış ve yırtıldı, ben de çalışacağımız ağın paralelistik küresel ölçeği sayesinde herkesin küresel ölçekte yaptığı sıradan sorunlarla karşılaşıyorum. Sadece birkaç kelimeyle kim olduğuma çok aşina olmayabilirsiniz, ancak okumanızı öneririm, işinizi tamamlamak için kendi projelerinizi oluştururken beni okumaya ve anlamaya devam ederken beni tanıyacaksınız. Profesörleriniz veya öğretmenleriniz size atamadığı sürece, bu kitapta ödev olmayacak, ancak okuduğunuz gibi bir proje portföyü oluşturmanızı ve nasıl yapabileceğinizi gösteren bir Capstone projesi oluşturmanızı tavsiye ediyorum. Öğrendiklerinizi uygulayın. Capstone projem, önceki projelerimden kod, oluşturduğum ve metodik olarak elle yazmayı öğrendiğim kod ve bana yardımcı olan çok çeşitli fikir ve ipuçlarını içerdiğinden, bu kitapta okuyacağınız şeylerin çoğunun temelidir. basit bir uygulamayı döndürebileceğim noktayı başarmakTamamen öne çıkıyor ve arkadaşınızın veya ailenizin internette, size reklamı veya haberlerde kullandığını görebileceğiniz popüler bir uygulama gibi görünüyor ve davranıyor. Bu kitap ne: Bu kitap örnek olarak bir öğreticidir. Kodu burada bulabilirsiniz, kodları nasıl öğreneceğinizi, hata ayıklama ve düzeltme hataları hakkında bilgi, sorun giderme adımları, kodunuzu nasıl yedekleyeceğiniz ve kaydedeceğinize dair talimatlar, kodunuzu kırarsa, kodunuzu sabitlerse, dağıtım yapabilirsiniz. Kodunuz, eğlenceli, ilgi çekici ve bağımlılık yapan interaktif web siteleri oluşturun ve kim olduğumu, bunun neden önemli olduğunu ve kendinizi, uygulamanızı ve şirket imajınızı nasıl tasvir edeceğimi anlayacaksınız. Son kullanıcılarınız, web sitenizin ziyaretçileri için mümkün olduğunca en çekici olmak için mutlak en iyi ışıkta oluşturduğunuz yazılım. Bu kitapta, bir platform ve güvenlik olarak web'e odaklanarak bir dizi yazılım tasarımı örneği göstereceğim. Bir temel oluşturarak öğrenme deneyimini başlatacağızYedekleme ve komut dosyası özellikleri ile UNIX kabuğunu kullanarak oject. Ardından, temel bir blog web sitesini inceleyeceğiz, blogumuzu fotoğraf ve video özellikleriyle yükselteceğiz ve bu özellikleri ücretsiz yazılım kullanarak güvenlik çözümlerini kullanmak için kullanacağız ve sunucumuzu takılabilir bir kimlik doğrulama modülü (PAM) kullanarak güvence altına alacağız. Daha sonra diğer kavramların yanı sıra dosya işleme ve işleme, video düzenleme, ses bağışını, barkod tarama ve optik karakter tanımasını inceleyeceğiz. Yol boyunca, yazılımımızı ücretsiz ve ücretli seçeneklerle daha kullanışlı ve güvenli hale getirmemize yardımcı olacak API'leri inceleyeceğiz. Yol boyunca, fıçılar ve tekrarlayıcı tasarımı, taret ve drone tasarımı ve diğer prensipler dahil olmak üzere ateşli silahlar ve mühimmat tasarım ve üretim gibi fiziksel güvenlik ve militan araçları keşfedeceğiz. ve kendini savunma ve esneklik göster. Oyunlar inşa etme yolunda mola vereceğiz, 2D ve 3DEndering motorlar ve vaka çalışmasında gömülü donanımla çalışın, temel boyutsal oluşturma yazılımı ve sırasıyla silikon kauçukta dökülen elektronik titreşimli bir masaj örnekleri. Yol boyunca, yazılımımızı daha iyi güvence altına almak için zaten mevcut olan makine öğrenimi çözümlerini de kullanacağız. Süreci kolaylaştırmak ve güvence altına almak için web için mevcut stok araçları da kullanacağız. Bu kitap, bir web uygulaması oluşturma ve profesyonel bir bilgisayar ve gömülü mekanik sistemler ağı ile entegre etme başarınız için bir rehberdir ve genel olarak arka plan bilgisi veya önceki deneyim olmadan yazılım ve gömülü donanım oluşturmak için bir rehberdir. Bu kitap ne değil: Gerçekten bir web sitesine sahip olmak istiyorsanız, basit bir mağaza kurabilir ve ihtiyacınız olanı satabilir, bir blog yayınlayabilir, fotoğraf veya video yayınlayabilir veya tek bir kod satırı yazmadan başka türlü olabilir. Bu kitap bu değil. Bu kitap size daha kullanışlı, tam olarak nasıl yazılım oluşturacağınızı öğretecekDaha önce bulabileceğiniz herhangi bir yazılımdan özellikli, işlevsel ve güvenli, çünkü hala prototip olan en son yazılımı dağıttığından, eski şirketlerin faaliyet gösterdiği bir ölçekte çalıştırılması pahalı olabilir ve geriye doğru hitap etmez, kıvrımlı şirketler Gerçekten hiçbir şey yapmayan insanlar için para kazanın. Bu kitabı yakından takip ederseniz, kod yazmak, araştırma kodu yazmak, kendi uygulamalarınızı oluşturmak ve yaptığınız işten para kazanacaksınız. Bu kitaptan, erken aşamalarda bile para kazanacağım, çünkü insanların ihtiyaç duydukları ve okumak istedikleri bilgileri içeriyor ve uygulamalarımı satın aldıklarında veya kullandıklarında zaten satın alıyorlar. Bu kitap sizin için bir uygulama oluşturmayacak, ancak sizi doğru yönde gösterecek ve ihtiyacınız olan araçlarla ve web için yazılım oluşturmada kendi başarınızı kolaylaştıracak beceri ve ipuçları ile sizi silahlandıracak, her satırla geliyor. Örnek olarak yazmanız gereken kod, siz ve destekçileriniz, misafirleriniz, müşteriniz yazılıma bir araya getirilmeye hazırdır.Riends, aile, ziyaretçiler, yükleniciler ve internet insanları kullanmak ve desteklemek istiyor. Ne öğreneceksin: Bu kitap size yazılım, gerçekten işlevsel, kullanışlı yazılım, medya kaydı, yüz tanıma, makine okunabilir bölge barkod taraması gibi güvenlik özellikleri, video ve fotoğrafları doğrulamak, kaydetmek ve oluşturmak için Web API'leri nasıl oluşturacağınızı öğretecek ve Bluetooth gibi mesajları değiştirecek ve yakın alan (NFC) iletişimi. Bu kitap size ağa bağlı bir bilgisayarı nasıl kullanacağınızı, Debian Linux'a odaklanacağını, yazılımınızı yüklemeyi ve yedeklemek için BASH kodu nasıl oluşturulacağını öğretecektir, sorunsuz, otomatik bir esinti, Python kodunu dinamik mesajlar, stil sunmak için bir arka uç olarak nasıl oluşturulur Bootstrap ile CSS stillerini güzel bir şekilde kullanmak, ağa bağlı cihazlar aracılığıyla kullanıcı girişleri ve etkileşimi etkinleştirin, doğrulama veya diğerleri için metin mesajları gibi güvenlik özellikleri sunmak için diğer web siteleriyle etkileşimli ortam ve ağ oluşturun amaçlar, kimlik taraması, görüntü ve video denetimi, verilerYazılımınızı güvende tutmak, ödeme işleme, kripto para ticareti, eşzamansız görevler ve daha fazlası. Piller, şarj cihazları, mikrodenetleyiciler, devreler, motorlar ve sensörlerle kendi Bluetooth cihazlarınızı nasıl oluşturacağınızı, lehim, tel ve 3D baskılı ve dökme malzemeler kullanarak nasıl oluşturacağınızı öğreneceksiniz. Katkı üretimi ve aracı ve kalıp yapımına uygulanan 3D tasarım prensiplerini göstereceğim, böylece kendi gömülü, donanım cihazlarınızı entegre piller, şarj cihazları, elektronik devreler ve fonksiyonel çıkışlarla üretebilirsiniz. ve bunları Bluetooth ve Web ile ağ. Özellikle, her ikisi de grafik arayüz veya komut satırı yardımcı programı olarak mevcut olan ve daha hızlı sonuçlar için bir web'e entegre edilebilen OpenSCAD'de programlanmış iki vaka çalışması, titreşimli bir masaj ve ev yapımı bir ateşli silahı inceleyeceğiz. Önceden bir deneyim olmadan bir web sitesini nasıl inşa edeceğinizi ve dağıtacağınızı öğreneceksiniz, işlevsel, güvenli, güzel, kullanışlı ve çoğuMortually Pratik. Bir siteyi güvenli ve daha pratik hale getirmek, web sitenizden video ve ses kaydettirmek, sesinizi bağışlamak, müzik yapın ve yararlı örnekler oluşturmak için ses modüle etmek ve gürültüyü nasıl kıracağınızı nasıl kullanacağınızı öğreneceksiniz. Sunmanız gereken tüm faydalı bilgileri paylaşmak ve daha da önemlisi insanları yazılımınıza ve işinize getirmek için doğrudan kendinize bağlanabileceğiniz mümkün olan en iyi web sitelerini oluşturmak için diğer web sitelerini kullanmak. Bu kitap, en yoğun olarak medya, güvenlik ve makine öğrenimine odaklanacak, bu da doğru kullanıcıları ele alarak ve yanlış olanları gerçekçi, pratik bir şekilde ayırarak web için yararlı yazılımlar oluşturmanıza yardımcı olacak en büyük üç bileşendir. Aynı zamanda otomatik ve sağlamken eller ve ilgi çekici. Bu kitap Unix, özellikle Debian (Ubuntu), Bash Shell, Python, HTML, CSS, JavaScript ve bir dizi yararlı yazılım paketini öğretir.N İsteklerin yanı sıra GIT ve FFMPEG gibi kullanışlı BASH yazılımı. Ayrıca, kripto para birimini otomatik olarak nasıl takas edeceğinizi ve kripto para biriminde veya normal banka kartlarından ödeme almayı öğretirken, ziyaretçilerinize bunu yapmayı seçerseniz gelirinizden bir pay ödeyecek. Reklamcılık yoluyla web sitenizden nasıl para kazanacağınızı, uygulamanızı arama motorlarına nasıl hazırlayacağınızı ve hızlı yapacağınızı, müşterilerinizin sizi bulmak için arayacakları için ilk sıralamada nasıl sıralanacağınızı öğreteceğim olabildiğince arama. Size yazılımınızı nasıl satacağınızı, reklamı yapacağınızı, hizmetlerinizi arayan müşterilere nasıl hitap edeceğinizi ve zaten var olan, ucuz ve iyi çalışan yollarla internette kendiniz için bir isim yapacağımı öğreteceğim. Size verilerinizi sizin için çalışan bulut bilgisayarlarına nasıl kaydedeceğinizi ve verilerinizi ucuz bir şekilde kaydedeceğinizi, kullanıcılarınızın istediklerini ve ne istediğinizi ve kullanıcılarınızı nasıl etkileşim kuracağınızı nasıl planlayacağınızı ve oluşturacağınızı öğreteceğim.Sitenizi, kullanıcılarınızı yalnızca size güvence altına alınan bir düğmenin arkasındaki web sitenize geri getirmek için bildirimler, e -posta, kısa mesajlar, telefon görüşmeleri ve daha fazla yolla telefonlarında bir dokunuş. Bu kitap, metnden fotoğraflara, videolara, sese (müşteriniz) iyi bir izlenim bırakarak ve kendinizi oluşturmak için yaptığınız herhangi bir şekilde satmanın pratikliğine büyük miktarlarda yayınlamanın ve dağıtmanın pratikliğine odaklanacaktır. Bir web sitesi, sadece sizin ve sizden temsil eden bir uygulama ve sizi, yazılımınızı ve şirketinizi mümkün olan en iyi şekilde iyi göstermesini sağlar. Ayrıca, kodlama ipuçlarından, makyaj ve fotoğrafçılık gibi pratik makyaj, modelleme ve oyunculuk ve daha fazlası, kendinizi ve şirketinizi mevcut tüm araçları kullanarak mümkün olan en iyi ışıkta tasvir etmek için önemli olacak birkaç ipucu ve püf noktası öğreneceksiniz. Size getirmek için sağlıklı bir platform dengesi boyunca ihtiyaç duyduğunuz kadar içerik dağıtırken sizeE gerektiğinden daha fazla çaba, iş veya para olmadan meyve vermek. Bu kitaba bir nedenden dolayı “pratik web tabanlı derin öğrenme ve örnek olarak örnek” olarak adlandırılır: özellikle web için, özellikle güvenliğe odaklanarak, pratik bir bakış açısından, hizmet veren çalışma kodu örnekleriyle ilgili olarak adlandırılır. Metinde özetlenen pratik amaçlar. Bu metnin öğrenme bileşeni aynı zamanda makine öğrenimini, bilgisayar vizyonunu, yüz tanıma, görüntü ve video denetimi, görüntü geliştirme, çözünürlük geliştirme, görüntü altyazısı ve diğer görevleri üstlenecek web için nasıl çalışacağımı göstereceğim kodu Görüntünün otantik, bilgisayar tarafından aktarılan bir görüntü veya optik bir kopya (bir görüntünün fotoğrafı veya basılı bir fotoğraf) gibi görüntülerden elde edilen tahmin metrikleri. Web güvenliği ve yazılım güvenliği söz konusu olduğunda makine öğrenimi çok önemlidir, çünkü başka türlü imkansız görevleri önceden şekillendirebilir. BilgisayarınızSizi bir şifre ile oturum açın, ancak yüzünüzle oturum açarsa kullanmak daha güvenli olabilir. Bir sunucu bilgisayarı bu güvenli hale getirebilirsiniz, normalde sizden bir kullanıcı adı ve şifre isteyecek ve sizi giriş yapabilirsiniz, belki de her yeni giriş veya yeni IP adresi için bir onay jetonu ile, ancak büyük ölçekli, kolay, kolay, kolay Kullanın, temelde güvenli ve güçlü bir yazılım, bu yeterli olabilir. Yazılımınızı bir e -posta hizmeti veya kısa mesaj hizmeti gibi başka birinin yazılımına çok yakından bağlamak, yazılımınızı veya herhangi birinin (kullandığınız herhangi bir sitenin) güvenli hale getirmek için yeterli değildir. Kusursuz bir şekilde güvenli olan yazılım oluşturan herkes, bunun ne anlama geldiğine dair bir fikre sahiptir. Yazılım doğal olarak güvensizdir, çünkü ona erişmek için kullandığımız cihazlar ve hesaplar her zaman elimizde değildir, yazılım için kötü niyetli olan herkesin elinde olabilirler ve bu nedenle yazılımın kendisi için bir risk oluşturabilir. Bu kitabın odak noktası. Ağa bağlı bir bilgisayar varsayılan olarakWeb sunucusu, sunucunun kendisinde çalışan açık erişimin yanı sıra açık erişim sağlayan açık erişim sağladığından, SSH veya SSH veya güvenli kabuk tuşu ile aranan uzun bir anahtar belirteci ile sabitlenir ve aksi takdirde en iyi bir web sunucusu ile güvence altına alınır. Web sunucusu, kullanıcının cihazının tartışmasız en güçlü kısmı olan kullanıcının web tarayıcısına erişebilir, çünkü kullanıcının ağa bağlı yazılımlara erişebileceği yerdir. Bu araç seti metin oluşturabilir, gördüğünüz web sayfalarını oluşturabilir ve ayrıca görüntüleri, ses ve videoyu (bir yüzün veya durum kimliğinin fotoğrafı gibi) kaydedebilir, Bluetooth radyo cihazlarına okuyabilir ve yazabilir ve yakın alanda okuyabilir ve yazabilir Transponder etiketleri, ucuz anahtar kartlar, fob'ler, çıkartmalar, halkalar ve hatta web sitesine bağlı bir web sunucusu tarafından oluşturulan ve doğrulanan verilerle okunabilen ve yazılabilen benzersiz seri numaralarına sahip yonga implantları. Emrinizdeki tüm araçları kullanarak, bu kitapla güvenli bir web sitesi oluşturmak için kendinizi bilgi ile donatacaksınız ve genel olarak birSizin için çalışan, teklifinizi yapan ve doğru görünen ve doğru hissettiren URE ağa bağlı bilgisayar sistemi. Nereden başlamalı: Bu kitaba veya herhangi bir bölümle başladığım bölümden geçmeye, özellikle de daha önce kodlama konusunda deneyiminiz varsa veya bu kitapta ayrıntılı olarak açıklayacağım yukarıda belirtilen araçlardan herhangi birinde atlayabilirsiniz. ve kullanım durumlarını ve pratik örneklerini belgelemek. Kodu yazma deneyiminiz yoksa, bu kitabın tümünü okumanızı ve özellikle bu kitabın sizin için doğru olduğundan emin olmak için önceki bölümleri okumanızı tavsiye ederim. Bu kitap sizin için doğru değilse, web gelişimini kendileri öğrenmek isteyebilecek bir arkadaşa veya akraba vermeyi düşünün ve hatta sizi geri ödemeyi ve sizi bir olarak başarısız olduğum boşlukları doldurmak için onlardan öğrenmeyi düşünün. öğretmen veya diğer öğretmenler benden önce yaptı. Nerede olacağınız, bu kitabın her kısmı yararlı bir hale getirmeyi planlıyorsanız yararlı olacaktır.PP ve en iyi uygulamaların son kullanıcı göz önünde bulundurularak oluşturulduğunu düşünün: müşterinizi tanıyın. Şimdi beni biliyorsun, bu kitabı biliyorsun ve başlamaya hazırsın. Başlamak için bir bilgisayar alın (bir kutu mağazasından, Amazon veya eski bir masaüstü işinden en ucuz dizüstü bilgisayar bile ve sizin için çalışan bir şekilde ayarlayın. Bu Kitap Nasıl Okunur: Vurgulanan metin, metnin çalıştırdığınız kodu yazacağınız bir komut istemine ait olduğunu belirtir. Komut istemi büyük ölçüde klavye odaklıdır ve çok az tıklama veya hiç tıklama, iş akışınızı hızlandırma ve sizin için işleri kolaylaştırır. Başlarken: Dalış yapalım. Yerel bir makinede kod oluşturarak başlayacağız ve İnternet'e bağlı bir web sitesi oluşturmadan başlayacağız. Bu başlamak daha güvenlidir, hiçbir maliyeti yoktur ve sizin için kolaydır. İşletim sisteminize bağlı olarak, bir bash kabuğuna girmek biraz farklı olacaktır. Mac OS için, en çok uyumluluğu elde edeceğiniz için bu noktada bir sanal makine kurmanızı öneririm.sanal makine. Virtualbox ve Paralells gibi çeşitli sağlayıcılar sizin için bir sanal makine çalıştırabilir, ancak hızlı, aerodinamik bir deneyim oluşturmak için önerilen yerel bir ortam kullanmayı tercih ediyorsanız, Ubuntu'yu doğrudan makineye yüklemek de mümkündür. Önerdiğim Linux veya Windows kullanıyorsanız, bir proje oluşturmak oldukça kolay olmalıdır. Terminalinizi açın, boyutlandırmayı uygun gördüğünüz gibi ayarlayın ve 2. adımı takip etmeye başlayın. Windows kullanıyorsanız, lütfen 1. adımı izleyin. 1. Adım: - Yalnızca Windows Kullanıcıları Windows'ta yönetici ve tür olarak komut istemini açın WSL – 2. Adım: - Buraya devam edin veya Windows kullanmıyorsanız 1. Adımı buraya atlayın Açık bir terminalde (işletim sisteminize bağlı olarak, Windows'ta Ubuntu, Mac veya Linux'ta Terminal veya benzer bir ad olarak adlandırılır) bir proje oluşturarak başlayın. Bunu bir dizin oluşturan MKDIR komutu ile yapıyoruz. Önerilen projenizi saklamak için bir dizin oluşturmanız gerekiyorsa,CD komutu dizine geçme komutu ve ve CD/PATH/TO/DIALTORY - Yol, hedef dizininizden önce gelen klasörlerdir (dosyalar), varsayılan yolunuz ~ veya/home/kullanıcı adıdır (kullanıcı adı kullanıcı adınızdır). Varsayılan dizin olarak değiştirmek için CD veya CD yazın ~ MKDIR Örneği - “Örnek” i dizinin adıyla değiştirin Şimdi projeniz için bir çalışma dizininiz var. Farklı bir makineye geçmeniz veya yazdığınız kodu dağıtmanız gerektiğinde bu dizinin kaydedilmesinin çok önemli olduğu için, web için hazır olacak şekilde, önümüzdeki birkaç adımda dizininizi yedeklemek için bir komut dosyası oluşturacağız. Ancak bir komut dosyası oluşturmak biraz kod alır ve kodun mümkün olduğunca yararlı olması için otomatikleştirilmesi gerekir. Öyleyse önce senaryolar oluşturmak için bir komut dosyası oluşturalım. Komut dosyasını oluşturarak ve yürütülebilir hale getirerek başlayalım. Bunun için sudo, chmod kullanacağız ve dokunacağız ve senaryoyu arayacağız


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Şimdi komut dosyasını oluşturduk, yürütülebilir hale getirdik ve düzenlemeye hazırız. Nano, tıklamadan metni düzenlemenize izin verecek bir metin düzenleyicisidir, bu da grafik kullanıcı arayüzünü kullanmaktan çok daha kolaydır. Nano ile bir dosya düzenlemek için Nano ve ardından dosyaya giden yolu kullanın. Bir komut dosyası oluşturan bir komut dosyası oluşturmak için, senaryomuzu ilk etapta yapmaya oldukça benzer. "Ascript" komut dosyasının adını bir bağımsız değişken parametresi olan 1 $ ile değiştirerek yukarıdaki ile aynı kodu kullanacağız. Bu, komut dosyasını basitçe sudo asscript Newscript yazarak çağırmamızı sağlar, bu noktada “Newscript” i komut dosyasının adıyla değiştirerek yeni bir komut dosyası oluşturabiliriz. Nano'daki kod:

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
Nano'yu kapatmak için, kontrol tuşunu basılı tutabilir ve X'e basabiliriz, sonra D dosyayı kaydettiğimizi ve geri dönüşü vurduğumuzu belirtmek için Y. Şimdi bir komut dosyasını düzenlemek için bu üç komutu yazmak yerine, komut dosyasını tekrar düzenlemek için sudo ascript ascript yazabiliriz. Bu işe yarıyor! Ve herhangi bir yeni komut dosyası kabukta çağrılarak kolayca çalıştırılabilir. Şimdi çalışmamızı kaydedelim: Yeni komut dosyamızı kaydetmek için bir yedekleme komut dosyası yazalım ve ardından yedek komut dosyasını da yedeklerken proje dizinimizde yedekleyelim.

sudo ascript backup
Şimdi, Nano'da:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Nerede/yol/to/dizin, MKDIR ile oluşturduğunuz projeye giden yoldur. Daha sonra, böyle tekrar yolları daha az kod olan bir döngü ve bir liste ile nasıl kopyalayacağımızı öğreneceğiz, ancak şimdilik basit tutalım ve birkaç satıra sahip olalım. Bu komut dosyasını çalıştırmak ve kodunuzu yedeklemek için dosyayı Nano'da Control+X, Y ile kaydedin ve geri döndürün ve aşağıdakileri kabuğunuza yazın

backup
Bu kitabı okurken ve kabukla takip ederken bir şifre için istenirse, lütfen kullanıcı şifrenizi doğru bir şekilde girin, komutu yeniden çalıştırmanız gerekmeden önce üç denemeniz olacaktır. İki kez bir şey çalıştırmanız gerekirse, komutları yeniden çalıştırmak ve düzenlemek için yukarı ve aşağı okları kullanabilirsiniz. Bir komut seçmek için aralıklı olarak yukarı ve aşağı bastırın, komutu sağa, sol okları ve silme tuşunun yanı sıra klavyeyi de düzenlemeden önce ve geri dönüşle çalıştırın. Tebrikler! Çalışma dizininizde iki önemli kabuk komut dosyasını yedekleyen harika bir yedekleme komut dosyası oluşturmayı başardınız. Proje büyüdükçe işleri daha sonra hareket ettirebiliriz, ancak bu şimdilik çalışıyor. Bulutta yedeklemeye geçelim, bunun için GitHub'ı kullanacağız (yedekleme için çok sayıda başka git çözümü olsa da, hepsi aynı.) Git, düzenlemeleri yedeklemenizi sağlayan bir verisi kontrol yazılımıdır. Onları bir sunucuya yaparken yazılımAyrıca yazılımınızın tüm kopyalarını bir şifre veya anahtarın arkasına indirmenizi sağlar. Yazılımınızı kaydetmede etkilidir, özellikle de tek bir kod satırı başarısız olduğunda bazen kırılan Linux örneklerine geçerken, kodunuz yedekleme şansınız olmasa da kodunuz yedeklenemeyebilirken sizi kilitlemeye devam ettirirken otomatik olarak yukarı, ki biz kapsayacak. Bu noktada zaten bir Ubuntu sanal makinesi kullanmıyorsanız, bu noktada bir Ubuntu sanal makinesini kullanmayı öneriyorum, çünkü çalışan bir web sitesi oluşturmak ve derin öğrenmeyi hazırlamak için gerekli tüm paketleri yüklerken hayatınızı kolaylaştıracaktır. Bilgisayarınızdaki işlemler. Kodu yakın gelecekte bir web sunucusuna taşıyacağız, ancak web sunucumuzun arkasında kimlik avına dirençli en az birkaç güvenlik katmanı olduğundan ve yapmak için bir dizi Linux paketini kullandığından emin olmak istiyoruz. Bu. Hala Mac OS kullanmak istiyorsanız, arayabilir ve yükleyebilirsiniz.E gerekli paketler çevrimiçi, ancak bu kitap veya seri kapsacağı her paket için alternatif olmayabilir. Sudo ascript komutunu çalıştırarak yedek komut dosyası ile çalışmamızı yapmak için birkaç komut ekleyelim

# …
git add –all
git commit -m “backup”
git push -u origin master
Bir kez daha, kaydetmek için X'i kontrol edin. Şimdi bu proje için bir kez yapılandırma yapmamız gerekiyor. Yakında bir GIT projesi olacağı için, bir GIT deposundan her konuşlandırdığımız her komutu yazmamız gerekmez, ancak dağıtım komut dosyalarımızı yazdığımızda bunu asacağız. Başlamak için, doğru dizinde olduğumuzdan ve Git deposunu başlattığımızdan ve SSH tuşlarını oluşturduğumuzdan emin olalım.

cd /path/to/directory
git init
git branch -m master
ssh-keygen
SSH-Keygen'i yazdıktan sonra, yeni anahtar .ssh adlı bir klasör altında ana klasöre kaydedilmelidir. Buna id_rsa.pub denir. Bu anahtarı bulalım ve kopyalayalım. Görmek için

cd ~
cat .ssh/id_rsa.pub
Son komut tarafından döndürülen metni kopyalayın ve hesabınıza SSH tuşunu eklemeden önce GIT sağlayıcınızla (ideal olarak GitHub) bir hesap oluşturun. Bir hesabınız olduğunda, SSH tuşunuzu menüde erişim altında SSH ve GPG anahtarlarına eklemeden önce sağ üst menüyü tıklayın ve ayarları girin. Yeni bir depo oluşturmak için GitHub'a kaydetmeden ve geri dönmeden önce bir SSH tuşu ekleyin ve bir başlık vererek ekleyin. Bu, diğer git sağlayıcılar için benzerdir, belgelerini okumanız gerekecektir. Yeni depo yapılandırmasında, deponuza açıklayıcı bir ad verin ve yayınlamak isteyip istemediğinize karar verin ve henüz dahil edilmek üzere hiçbir dosyayı yapılandırdığınızdan emin olun. Depo oluşturulduktan sonra, klonu SSH URL ile kopyalayın ve aşağıdaki komuta yapıştırın.

git remote add git://… (your remote URL)
Şimdi CD ile deponuza geri dönebilirsiniz, buna aşina olacaksınız. Yedekleme komut dosyasını şimdi yedeklemeyle deneyin Harika! Şimdi gerçekten kodlayabiliriz. Bash ve git üzerinde iyi bir kavrayışa sahip olduğumuza göre Django'yu yükleyelim. Django yazılımımızı otomatik olarak yedeklememize izin verecek, Bash bunu da yapabilir, ancak Django daha basit bir uygulamaya sahip olmalıdır (devre dışı bırakılabilir ve daha kolay yapılandırılabilir). Ubuntu'ya yazılım yüklemek için Sudo Apt-Get komutunu kullanacağız. İlk olarak, zaten sahip olduğumuz yazılımı güncelleyelim ve yükseltelim. Bu, sudo apt-get güncellemesi ve sudo apt-get yükseltme -y ile yapılabilir. Ardından, Python'u ve sanal ortamımızı, kodumuzun evini, aşağıdaki komutla yükleyelim: sudo apt-get Instow Python-is-python3 python3-venv Ubuntu örneğinde yazılım yüklemeleri açısından Django ile gitmek için ihtiyacınız olan tek şey budur. Windows ve Linux için bu oldukça basit olmalı, ancak Mac için sanal bir makine yüklemek isteyebilirsiniz veLinux, VirtualBox veya Paralells masaüstü gibi ücretsiz veya ücretli bir sanal ortam kullanarak ve bir Ubuntu ortamını kurmak için yukarıdaki adımları yeniden oluşturun. Ubuntu bu durumda kritiktir, çünkü web sitelerinin çalıştırdığı yazılımdır ve yukarıda belirtilen tüm yazılımlarla web sitelerini barındırmalarını sağlar. Django'ya girelim. Dizinimizde yine,

python -m venv venv # Kodun depolandığı sanal ortamı oluşturur
source venv/bin/activate # Sanal ortamı etkinleştirir
pip install Django
django-admin startproject mysite . # Mevcut dizinimde başladığım proje MySite.
Django bizi yeni başlıyor, çünkü Django web sunucusuna ev sahipliği yapıyor ve temel bir yerel web sitesini hazırlamak için ihtiyacımız olan her şeyi yapıyor. Artık Django'yu yüklediğimiz için, ihtiyacımız olan nasıl çalışmasını sağlamak için ayarları biraz düzenleyelim. İlk olarak, yeni bir uygulama oluşturalım

python manage.py startapp feed
İlk uygulamanın Feed denildiğini fark edeceksiniz. Uygulama istediğiniz her şey çağrılmalı ve yeni uygulamalar oluşturacağız, ancak her uygulamanın adı, uygulama kodda her referans alındığında tutarlı olmalıdır. Yeni bir uygulama eklemek için, her zaman settings.py'yi düzenleyeceğiz ve bu da AhsteProje, bundan sonra uygulama olarak adlandırılan uygulamanın oluşturulan diğer dizinde düzenleyeceğiz. Nano kullanma,

nano app/settings.py
Ayarlarda, yüklemeli_apps bulun ve [] 'i 3 satıra ayırın. Boş merkez hattında dört boşluk kullanarak 'besleme' ekleyin veya uygulamanızın adı. Settings.py'nin bu bölümü şöyle görünmelidir:

INSTALLED_APPS = [
    'feed',
]
Unutmadan önce Django'nun çalıştığını test edelim. Python Manage.py Runserver 0.0.0.0:8000 komutunu kullanarak, sunucuyu çalıştırabilir ve daha sonra kodu http: // localhost: 8000 olarak çalıştıran bilgisayardaki bir web tarayıcısında gezebiliriz ve örnek bir web sayfası görün (çalışır!) Diğer komutlarla aynı olan Control C ile sunucudan çıkın. Şimdi, bazı Python kodu yazmaya başlayalım. Django'nun hepsi tamamen kod tarafından işletilen üç ana bileşeni var. Bileşenlere model, görünüm ve şablon denir ve web sayfası kullanıcıya teslim edilmeden önce her biri sırasıyla daha yüksek ve daha düşük seviyededir. Model, alım, sıralama ve oluşturma için veritabanında bilgileri depolayan koddur. Görünüm, modelin nasıl oluşturulduğuna, manipüle edildiğine ve değiştirildiğine karar verir, hemen hemen her görünüm doğrudan bir model kullanacaktır. Şablon, şablon dili olarak adlandırılan bazı ekstra çan ve ıslık ile HTML kodudur. Şablon, Python kodu ile doldurulduğu görünümle oluşturulur veGörünümden modeller ve bilgi (usuall dizeleri ve tamsayılar) gibi bağlam. Django'nun başka bileşenleri de var, ancak bunlarla sınırlı değil: Uygulamayı tartıştığımız gibi yapılandıran ayarlar. Web uygulamasının belirli bölümlerine erişmek için kullanıcının izlediği kalıplar olan URL'ler. Sunucuya gönderilen bilgilerin veritabanına ve kullanıcıya nasıl işlendiğini ve işlendiğini tanımlayan formlar. Bunlar, sunucu tarafında bilgilerin işlenmesinin temelidir ve bilgisayarın depolandığı her türlü bilgiyi kabul edebilir, özellikle metin dizeleri, sayıları ve doğru/yanlış boolean (genellikle onay kutuları). HTML kodu ve şablon dili olan ve Python ve HTML arasındaki boşluğu köprüleyen şablonlar, yani Python bilgileri, herkesin erişebileceği ve Python Kodunu Web için erişilebilir hale getirebileceği ve yararlı hale getirebileceği HTML kodu olarak sunulabilir ve Uzak bir cihazda çeşitli amaçlar içinSunucunun yakınında olması. Genellikle JavaScript olan statik dosyalar ve sunucunun hizmet verdiği ve şablonla bağlantılı olan kütüphaneleri. Sunucunun hizmet verdiği veya harici olarak barındırılan veya işlenmeden önce sunucuya yazılı olarak yazılı olarak yazılı olarak yazılan ve barındırma için başka bir sunucuya (bir kova) gönderilen medya dosyaları. Her görünümle aynı zamanda çalışan ve görünümde “dahil” olarak kabul edilen kod parçaları olan ara katman yazılımı. Her bir görünümün bağlamını işleyen ve ekstra bağlam eklemek için kullanılan bağlam işlemcileri. Görünüm oluşturulmadan önce kullanıcının veya talebin belirli gereksinimleri geçtiğini doğrulayan testler. WebSocks'ın iletişimi nasıl ele aldığını ve iletişime nasıl yanıt verdiğini belirleyen tüketiciler. Veritabanının grafik bir arayüz aracılığıyla uygulanabileceği Django yönetici sayfasında ayrıntılı olarak manipüle edilebilecek şekilde modelleri kaydetmek için kullanılan yönetici. Django kodunun eşzamansız görevleri tanımlayan kereviz başlayabilirNing, hemen bir sonraki göreve veya kod satırına geçmeden önce. Django'nun burada ayrıntılı olarak tartışacağımız birçok bileşeni olabilir. Django'yu daha işlevsel hale getirmenin, hızlı, aerodinamik iletişim kanalları, eşzamansız görevleri yerine getiren WebSocks ekleymenin ve Django'yu genişletmek için çok sayıda diğer yazılım parçasını eklemenin birçok yolu vardır, burada özellikle görünüm fonksiyonlarında, çoğunun çoğunun çoğunun kod yürütülür. Görünüm işlevleri anahtardır, çünkü genellikle belirli bir URL modeline veya sunucunun bir bölümüne özgü her kod parçasını bildirirler. İlk olarak, görünüm işlevlerini keşfedelim. Görüntüle İşlevler, görünümde kullanılacak kodu gösteren ve normal işlev tanımları veya sınıfları kullanılarak tanımlanır. En basit görünümler, işlev tanımı DEF ile tanımlanır ve temel bir şablonla bir httpreponse döndürür. “Merhaba Dünya” metnini döndürmek için temel bir görünüm tanımlayarak başlayalım. Her eklediğinizde unutmayınDef gibi bir ifade, eğer, vb. Bunların her birinin yakında ne anlama geldiğine gireceğiz. Sitemizin dizininden, nano kullanarak feed/views.py dosyasını düzenleyin ve aşağıdaki satırları ekleyin.

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
Django'nun HTTPResponse, açılış ve kapanışla gösterilen bir metin dizesi ile yanıt verir '. İstek veya dize gibi bir işleve veya sınıfa her aktardığınızda parantez kullanmanız (, açma ve kapanış) kullanmanız gerekir. Henüz görüşümüzü görmemiz gereken bu değil. Tabii ki, sunucuya görünümün tam olarak nerede olduğunu söylemedik, yine de görünümün oluşturulması gereken bir yolu tanımlamamız gerekiyor. Uygulama/urls.py'de temel bir yol tanımlayarak başlayalım ve daha sonra yol gruplarına gireceğiz. APP/urls.py'de, yeni oluşturduğumuz görünümü içe aktardıktan sonra içe aktarma ifadelerinden sonra bir satır ekleyin.

from feed import views as feed_views
Şimdi görünüm modelini tanımlayalım. Görünüm kalıpları, sunucuda görünümün nerede olduğunu söyleyen yol bileşeni olan üç bileşene sahiptir (kullanıcının web sayfasına girmek için navigasyon çubuğuna yazdığı URL yolu), görünümün belirtildiği görünüm bileşeni ve bir Görünüm için dostça isim, bu nedenle bir şablonla çalışırken desenini almak kolaydır, özellikle başka bir görünüm için yer açmak veya daha mantıklı bir isim almak için gerekirse adı değiştirilebilir ve güncellenebilir. İşleri bu şekilde yapmak ve esnek olmak mantıklıdır, çünkü kod tabanınız değerli ve çalışması kolay olmak için esneklik ve doğaçlama gerektiren sürekli değişen bir ortam olacaktır. Görüşünüz nasıl görünecek, bunu urlpatterns = [uygulama/urls.py bölümüne ekleyebilirsiniz. Görünüm modeli, yukarıda açıklanan üç bileşen ve yol adı verilen bir işlevle tanımlanır. URL kalıplarınız bir listedir, bu nedenle her öğeyi her zaman sonlandırdığınızdan emin olunvirgülle, çünkü bu her birini ayırır. Her öğe, tıpkı settings.py'deki uygulama gibi, bir kez daha önünde dört boşluk olan yeni bir satıra geçmelidir. Web sunucusunun kök dizininde çalışan bir görünüm oluşturmak için görünümün ilk bileşenini boş bir dize işleviyle tanımlayacağız. Urls.py şimdi gibi görünmeli

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Bu, tamamen statik olan Django ile bir web sitesi oluşturmanın temelidir. Görüntüler, videolar, ses ve daha fazlası gibi bilgileri önbelleğe almaya başlayabileceğimiz daha dinamik bir web sitesi yapmak için, bir sonraki keşfedeceğimiz modelleri kullanmamız gerekecek. Şimdilik kodumuzu kontrol edelim ve sunucuyu çalıştıralım. Kodu hatalar için kontrol etmek için:

python manage.py check
Herhangi bir hata mesajı varsa, uygulamanızda yaptığınız değişiklikleri dikkatlice gözden geçirmeli ve yabancı veya eksik alan, ekstra karakter, kaplamayan bir ip, herhangi bir yazım hatası gibi düzeltilmesi gereken bir şey olup olmadığını görmelisiniz. silinmiş karakter veya başka bir şey. Hata mesajını okuyun (eğer varsa), bir satır numarasıyla birlikte oluşturduğunuz veya düzenlediğiniz bir dosyaya giden yolu görebilmelisiniz, bu nedenle bu dosyaya ve satıra bakın ve orada bulunan bir şeyi düzeltip düzeltemeyeceğinizi görün . Sorunu çözdüyseniz, yukarıdaki komutu tekrar çalıştırın. Yazılımınız çalışmaya hazır olduğunda ve çalıştığında, “Sistem kontrolü hiçbir sorun tanımlanmadı” çıktısını göreceksiniz. Şimdi gitmeye hazırsın. Sunucuyu şu şekilde çalıştırın:

python manage.py runserver 0.0.0.0:8000
Şimdi bir web tarayıcısı açın ve http: // localhost: 8000 adresine gidin. HTTPResponse işlevinin parantez ve alıntılarında döndürülen metni görmelisiniz. Bu sadece temel bir örnektir, ancak şimdiye kadar yaptıysanız, Linux, Bash, Python ve Django'nun nasıl çalıştığının temellerini anlıyorsunuz. Bazı veritabanı modellemelerini daha derinlemesine inceleyelim ve bir Python sınıfının bilgi depolamada gücünü keşfedelim. Ardından, sitemizi JavaScript ve makine öğrenimi kullanarak tam özellikli, esnek ve güvenli hale getirmeden önce HTML ve CSS üzerinde bir kavrama almaya başlayacağız. Sınıflar, uygulamanızın Models.py'de saklanır. Nano'yu kullanarak App/Models.py'yi düzenleyin ve yeni bir sınıf ekleyin. Bir sınıf sınıf tanımı ile tanımlanır ve bu durumda modellerde miras aldığı bir üst sınıfın geçirilmesi. Sınıfın adı sınıf tanımından sonra gelir ve sınıf tanımı A: (kolon) kullanıldıktan sonra, sınıfa bağlı özellikler ve işlev tanımları aşağıda belirtilmeden önce. SınıfımızOnu almak ve benzersiz tutmak için kullanabileceğimiz bir kimliğe ihtiyaç duyar ve ayrıca bazı bilgileri saklamak için bir metin alanına ihtiyaç duyar. Daha sonra, modeli günlüğe kaydedilen bir kullanıcıya bağlamak için bir örnek olan bir zaman damgası, dosya, boolean (kodumuzun modelle ne yapacağına yardımcı olabilecek ve bunu sıralamak için kullanılabilen gerçek veya yanlış tanımlar) ekleyebiliriz. sunucuya ve daha fazlası. Kodu açalım

from django.db import models # Sınıfımızı tanımlamak için kullanılan ithalat ve özellikleri

class Post(models.Model): # Sınıfımızın kendisinin tanımı
    id = models.AutoField(primary_key=True) # Modeli sorgulamamıza, benzersiz tutmamıza ve oluşturulduktan sonra modelle etkileşime girmemiz gerektiğinde kullanışlı olan otomatik olarak oluşturulmuş bir anahtar olan modelimizin kimliği.
    text = models.TextField(default='') # Sınıfımızı, bu durumda, bazı metinleri, boş bir dizeyi temerrüde atan nitelendirir.
Dosyayı daha önce bitirmek için yaptığımız gibi kapatın ve kaydedin. Uygulamamız geliştikçe bu sınıfı güncellediğimizde keşfedeceğimiz birçok alan ve seçenek var, ancak bu, bazı metinler göndermek için bir uygulama oluşturmanın temel gereksinimleridir. Ancak, bu model yalnız çalışmayacak. Daha önce açıklandığı gibi, bu modelin çalışması için özel bir görünüm ve özel URL modeline ihtiyacımız olacak ve ayrıca bir şablonla birlikte bir forma ihtiyacımız olacak. Önce formu keşfedelim. Bir form tanımlamak için App/Forms.py'yi Nano ile düzenleyin ve aşağıdaki satırları ekleyin. İki ithalata, form sınıfımıza ve oluşturduğumuz model (feed.models.post), modele benzer bir sınıf tanımı ve formun etkileşime girdiği modeli tanımlayacak bir alt sınıfla birlikte bir alana ihtiyacımız olacak (feed.models.post) ile. Form ayrıca, istek, model veya başka türlü bilgilere göre ayarlayan bir başlatma işlevine de sahip olabilir, bunu daha sonra keşfedeceğiz. Model formları çok kullanışlıdır çünkü bir model oluşturabilir veya bir modeli düzenleyebilirler,Bu yüzden onları her ikisi için de kullanacağız. Birini Forms.py'de tanımlayalım

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',)
Bu, bir form ve modelin neye benzediğinin temelleridir. Bu model formu, içerdiği metni değiştirerek bir yayını başlatmak veya düzenlemek için kullanılabilir. Bu formu bir sonraki manzaraya entegre etmeye bakacağız. İlk olarak, kodumuz çalıştığında modelle etkileşime girebilmesi için geçiş yapalım ve veritabanını taşıyalım. Bunu yapmak için aşağıdaki komutları çalıştırın:

python manage.py makemigrations
python manage.py migrate
Bunun yürütülmesi bir dakika sürecektir, ancak bir kez yapıldıktan sonra, modele görünümlerde, ara katman yazılımı veya yazılımdaki başka bir yerde erişmenize izin verecektir. Modelimizi görebileceğimiz bir görüş yaparak devam edelim. Feed/views.py'yi düzenleyin ve belirtildiği gibi aşağıdaki kodu ekleyin. # İşaretten sonra hiçbir şey eklemeniz gerekmez, bu kod kodla ilgili bilgileri belirtmek için kullanılan yorumlardır. Modelimizi görünümlerde içe aktararak ve bunu bir şablonda ekran için bir liste olarak oluşturabileceğimiz bir bağlama ekleyerek başlayacağız. Ardından, modele dayalı yeni bir nesne oluşturmak ve sunucuya göndermek için formu ve modeli bir düğme ile oluşturabileceğimiz bir şablon ekleyeceğiz. Bu karmaşık geliyor, bu yüzden adım adım atalım. Görünümü bitirmeden önce, sadece modeli oluşturan bir şablon oluşturalım ve kabukta yeni bir yazı oluşturarak görebildiğimizden emin olun. İşte bu görüş nasıl görünmelidir:

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

def feed(request):
    posts = Post.objects.all() # Veritabanındaki tüm yayınları şimdiye kadar sorgulayın
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })
Bu dibe ulaşana kadar hepsi oldukça basit görünüyor. Render, işlev tarafından bir önceki örnek gibi bir HTTP yanıtı yerine döndürülen değer, her zaman ilk giriş olarak bir isteği alır, şimdi şablonda oluşturulabilen bir bağlamı (bu durumda veritabanındaki yayınlar) kabul eder. ve işlevde tanımlanan şablonu döndürür. Şablon, Python bilgisini HTML'ye dönüştüren Jinja2 adlı bir dilin biraz olduğu bir HTML belgesi olacak. Şablon oluşturmaya başlamak için Feed'de iki dizin oluşturun.

mkdir feed/templates
mkdir feed/templates/feed
Ardından, yukarıdaki dizinde bir şablonu düzenleyin, besleme/şablonlar/besleme ve bu örnek için kodu ekleyin. Bu örnek için şablona bakalım.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Bu çok basit bir şablon. HTML etiketlerini açma ve kapatma, bir belge türü etiketi, efsane başlıklı bir gövde etiketi, ekran boyunca küçük bir satır ekleyen bir kırılma etiketi ve her gönderiyi yayınlar listesindeki her gönderiyi bir paragraf olarak oluşturan bir döngü için tanımlar. Şablon. Mesajları oluşturmak için gereken tek şey budur, ancak veritabanında henüz hiçbiri yoktur. Kabukla biraz yaratalım. Kabuğu manage.py ile çalıştırabiliriz

python manage.py shell
Şimdi yazı modelimizi içe aktaralım

from feed.models import Post
Ardından, bir ip içeren basit bir yazı oluşturacağız ve kabuktan çıkacağız. Dize, geçerli metin olduğu sürece herhangi bir şey olabilir.

Post.objects.create(text='hello world')
exit()
Son olarak, beslememize bir URL deseni eklememiz gerekecek. Feed uygulamamız birden fazla URL kullanacağından ve dosya boyutlarını küçük tutmak istediğimiz için, feed uygulamamızda şöyle görünen yerel bir urls.py oluşturalım:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
Ayrıca urls.py'yi temel uygulamada düzenlememiz gerekecek, ne dediğimiz her ne olursa olsun, bu oluşturduğumuz ilk dizinti. App/App.py'yi düzenleyin ve URL modellerine aşağıdakileri ekleyin

from django.urls import include # üstte

urlpatterns = [
    # ... Önceki kod burada
    path('feed/', include(('feed.urls'), namespace='feed')),
]
Şimdi, sunucuyu python manage.py runserver ile çalıştırdığımızda, veritabanındaki öğelerle birlikte model, görünüm ve şablonun yanı sıra URL desenimiz olduğu için oluşturduğumuz sayfayı göreceğiz. Ardından, oluşturduğumuz formu uygulayalım ve kendi yayınlarımızı oluşturmaya başlayalım. Ancak çok fazla kod yazmadan önce, daha önce yazdığımız komut dosyasını kullanarak bir yedekleme yapalım. Bu komut dosyasını kabukta çalıştırın, birkaç dakika bekleyin ve tüm kodlar GIT depomuza yedeklenecektir.

backup
Formun uygulanması nispeten basittir. Formumuzu içe aktaracağız, görünüme bir post isteği işleyicisi ekleyeceğiz ve aynı görünüme yönlendirmeden önce gönderiyi veritabanına kaydedeceğiz. Zaten içe aktardığımız yönlendirme işlevini ve görünüm modeli için URL'yi almak için Ters adını verilen başka bir işlevi kullanabiliriz. Bunu, dahil edilen desenin ad alanı beslenir ve görünüme de besleme olarak da adlandırıldığından 'feed: feed' dizesi ile sorgulayacağız.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Veritabanındaki tüm yayınları şimdiye kadar sorgulayın
    if request.method == 'POST': # Gönderi isteğini ele alalım
        form = PostForm(request.POST) # Formun bir örneğini oluşturun ve verileri ona kaydedin
        if form.is_valid(): # Formu doğrulayın
            form.save() # Yeni Nesneyi Kaydet
        return redirect(reverse('feed:feed')) # Bir GET isteği ile aynı URL'ye yönlendirin
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # Oluşturabilmemiz için formu bağlama geçtiğinizden emin olun.
        'posts': posts,
    })
Şimdi, yeni formu hesaba katmak için şablonu güncellememiz gerekecek. Bunu kullanarak yapabiliriz
HTML'de etiketleyin ve HTML şablonundaki formu bir gönder düğmesi ile oluşturun. Ayrıca, harici sitelerin önce bir sayfa yüklemeden forma göndermesini önleyen bir jetona sahip bir CSRF jetonuna da ihtiyacımız olacak.
 
<!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>
 
Bunu yıkalım. Yeni bir form sınıfı, bir jeton, formun kendisi ve bir gönderme düğmesi var. Oldukça basit, ama ona bir göz attığımızda, daha iyi görünmesini isteyebiliriz. Çalışır, formla yeni yayınlar gönderebiliriz ve şimdi veritabanına kaydedilir. Burada birkaç şey oluyor. Belgenin bir HTML belgesi olduğunu beyan etmek için HTML etiketlerini kullanıyoruz, form için jetonu oluşturmak için bir şablon etiketi ({ %… %}) ve formu oluşturmak için {{…}}. Ayrıca blok etiketleri ve bir şablon etiketi kullanarak metni oluşturmak için bir döngümüz var. Blok etiketleri gerçekten önemlidir, çünkü şablonun bölümlerinin onlarla nasıl oluşturulduğunu tanımlayabiliriz ve şablon etiketleri, değişkenleri kodumuza nasıl koyduğumuzun temelidir. Şimdi uygulamamızı daha iyi göstermemiz gerekiyor, çünkü şimdilik gerçekten temel görünüyor. Bunu, satır içi veya belgedeki her nesneye bağlı sınıflarda CSS kullanarak yapabiliriz. CSS gerçekten güzel çünkü sayfadaki her şeyi nasıl görünmesi gerektiğini anlatıyor,Ve gerçekten iyi görünmesini sağlayabilir. Bunu yapabilen birkaç kütüphane var, ancak kişisel gitmem Bootstrap. Bootstrap web sitelerinden indirilebilir,Getbootstrap.com/. Oraya girdikten sonra, yükleme belgelerini okumak için düğmeye basın ve kodu dahil CDN bölümünden kopyalayın. Bu kodun HTML belgenizin üstünde, Head adlı bir etikette ihtiyacınız olacak. Ayrıca, devam edelim ve bir temel şablon oluşturalım, böylece her bir şablonda bu bağlantıları yeniden oluşturmamız gerekmiyor. MKDIR şablonlarına sahip şablonlar adı verilen yeni bir dizin yapın ve ardından Templates/Base.html düzenleyin. Şöyle görünmeli:
 
<!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>
 
CSS ve JavaScript, .css ve .js dosyalarını kopyaladığınızdan emin olun, çünkü sitemizi gelecekte daha işlevsel hale getirmek için JavaScript'e ihtiyacımız olacak. Şimdi, bash kabuğuna dönelim ve hızlı bir komuta çalıştıralım. Unutmayın, sanal ortama erişmeniz gerekiyorsa, kaynak Venv/bin/aktivite yazın. Bu, Python paketlerini yerel olarak Django'nun onlara erişmesine izin verecek şekilde kurmanıza izin verecektir. Django Bootstrap sınıfları tarafından oluşturulan formlarımızı vermek için Crispy Forms adlı bir Python paketi kullanacağız. Bunu aşağıdaki komutla indirebiliriz

pip install django-crispy-forms
Bu yüklendikten sonra, settings.py'ye ekleyin

INSTALLED_APPS = [
    # … Önceki kod burada
    'crispy_forms',
]
Şimdi, yem şablonumuzda bazı şeyleri kaldırabiliriz. Belgenin başlangıcını ve sonunu kaldıralım ve genişletme ve blok tanımını kullanarak temel şablonumuzdan miras ile değiştirelim. Ayrıca, yük ve bir şablon filtresi ile bir şablon filtresi içe aktarma ekleyeceğiz. Son olarak, daha çok bir düğmeye benzemesi için formdaki düğmeye bir bootstrap sınıfı ekleyelim. Bu şöyle görünmeli:
 
{% 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 %}
 
Güzel! Bu zaten biraz kod. Sonra, test etmeliyiz ve her şeyin güzel göründüğünü görebildiğimizden ve her şeyin düzgün çalıştığından emin olmalıyız. Sunucuyu önceki talimatlara göre çalıştırın ve sitenin iyi göründüğünden ve çalıştığından emin olun. Harika iş! Benzer URL'leri, formları, görünümleri ve şablonları kullanarak kullanıcı giriş işlevselliği ekleyeceğimiz bir sonraki adıma geçmeye hazırsınız. Temel şablon önemlidir ve onu değiştirmeye ve gerektiğinde değişiklik yapmaya devam edeceğiz, ancak şimdilik kullanıcıların bir kullanıcı adı ve kısıtlama ile giriş yapmalarını sağlayarak sitemizi daha güvenli hale getirmeye odaklanalım ve sonunda daha önemli bilgiler Uygulamanızı ve kendi hesabınıza yalnızca sizin tarafınızdan erişilebilir kalmanıza yardımcı olacaktır. Bunu yapmak için Django'da yerleşik kullanıcı modelini kullanmamız gerekecek. Kullanıcı modeli, bir kullanıcıyı web sitesine kaydetmek için oluşturulabilen bir veritabanı modelidir. Gelecekte, siteyi internete dağıtmadan önce,Bu modeli kendisine atfedilen diğer modellerle genişletin ve kimlik avına dirençli giriş için ek güvenlik önlemleri oluşturun. Django'nun sağladığı bazı yerleşik giriş formlarını kullanarak başlayacağız. İlk olarak, temel giriş sayfası için şablonları ve görünümleri oluşturmak için kullanacağımız yeni bir uygulama oluşturalım. Ayrıca, bir pinkod, yüz tanıma, yakın alan iletişimi, harici cihazlar, çok faktörlü kimlik doğrulama ve parmak izi tanıma da dahil olmak üzere uygulamayı güvence altına almak için devam eden giriş zorluklarını temsil etmek için başka uygulamalar da oluşturacağız. Zaten bir uygulama başlatma hakkında konuştuk. Dizinimizden, sanal ortamın içinde, bunları yönetin.

python manage.py startapp users
Şimdi, yeni uygulama için bir dizinimiz olmalı. Bu dizinde kullanıcı girişine karşılık gelen bir görünüm oluşturarak başlayalım. Django, kullanıcı girişleri için görünümler geliştirdi, ancak bunlar bizim için uygun olmayacak çünkü tercihen bir tanımla yapılan özel bir görünüme ihtiyacımız var. Bu görüşe göre, bir yayın isteği kontrol ederek başlayacağız, Pass isteği. Kullanıcılar/Views.py'de aşağıdaki kodu ekleyin

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'] # Kullanıcı Adı ve Şifreyi Gönderi Gönderiden Alın
        password = request.POST['password'] # Kullanıcıyı doğrulayın
        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()})
Temel bir oturum açma görünümü için ihtiyacınız olan tek şey budur. Şimdi, temel şablonu genişleterek görünüm için bir form oluşturalım. Kullanıcılar klasöründeki şablonlar için yeni bir dizin oluşturarak başlayacağız.

mkdir users/templates
mkdir users/templates/users
Şimdi, kullanıcıları/şablonları/kullanıcıları/login.html'yi düzenleyebilmeliyiz. Biz oradayken, kullanıcının da kaydolmasına izin vermek için bir şablon oluşturacağız.

nano users/templates/users/login.html
Şimdi, şablonda,
 
{% 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 %}
 
Bu bir giriş şablonunun temelleridir. Gerçekten yapıdaki diğer şablon gibi, ancak işlendiğinde biraz farklı görünüyor. Bu kodu, Register.html adlı çok benzer bir şablon oluşturmak için kopyalayabiliriz, burada ifadeleri değiştirir ve oluşturduğumuz yeni bir form kullanacağız. Önce şablonu yapalım. Kullanıcıları/Şablonları/Kullanıcıları/Register.html'i düzenleyin ve aşağıdaki kodu ekleyin:
 
{% 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 %}
 
Şimdi, kullanıcı kaydımız için bir form oluşturalım ve kullanıcı girişlerimizi bir modelle yükseltmeden önce görünümlere geri dönelim. Bu formu başlamak için temel hale getireceğiz, ancak gelecekte anlaşmalar ve captcha gibi daha fazla ayrıntı ve güvenlik özellikleri dahil edeceğiz. Nano kullanıcıları/forms.py ile formları düzenleyin ve aşağıdaki kodu ekleyin.

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']
Bu yüzden burada oldukça basit bir şekilde çalışan başka bir formumuz var. Kullanıcı adı, e -posta ve şifre ile bir şifre alanı olan bir kullanıcı kaydı formudur. Bu formun normal formları genişletmediğini unutmayın. Form sınıfı, bir meta olduğu anlamına gelen bir model formudur. Bir alan aynı şekilde tanımlanır ve sınıf meta, formun formda yazılacak bilgilerin geri kalanına karşılık gelen modeli tanımlar. Bunların çoğu zaten Django'nun yerleşik userCreationForm'da mevcuttur, bu yüzden bunu sınıfın temeli olarak kullanacağız (parantez içinde geçer). Ardından, bir formumuz ve bir şablonumuz olduğu için bir kullanıcıyı kaydetme görünümünü inceleyeceğiz. Bu, tıpkı yeni Post görünümündeki gibi bir modelform. Kullanıcılar/views.py düzenleyin ve aşağıdaki kodu ekleyin:

# … İthalat
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})
Bir kullanıcıyı kaydetmek için ihtiyacımız olan tek şey bu, ancak daha fazla bilgiye sahip olmalıyız. Kullanıcının kaydedildiği zamanı, sitede en son ne zaman olduklarını, bir biyografi, saat dilimi vb. Gibi bazı bilgileri bilmek istiyoruz. Ayrıca, kullanıcıyı hesaba katmak için yayın modelimizi güncellememiz gerekecek Her kullanıcıya yayınları modelleyin ve ilişkilendirin. Bunu yapmak için Models.py'yi her iki uygulamada güncelleyeceğiz. Besleme modelini düzenleyerek başlayalım. Şimdi böyle görünmeli:

from django.db import models # … Miktarlar
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') # Bu satıra ekle
    text = models.TextField(default='')
Dosyaya eklenen ikinci satıra dikkat edin. Bu, her gönderiyi yazı başına tek bir kullanıcıya atfetecek yabancı bir anahtardır, böylece yayınları kullanıcı başına kullanıcı bazında kaydettiğimizden ve bir kullanıcıya atfetmeden hiçbir yayın yapılamayacağından emin olabiliriz. Bu yabancı anahtarı temsil ettiği sınıfla tanımlıyoruz, gönderilerin kullanıcılarla silinmesini sağlamak için bir silme argümanı, gerektiğinde kullanıcıyı kaldırabileceğimizden emin olmak ve zaten bir kullanıcının eksikliği için uyum sağlamak için zaten bir kullanıcının eksikliği oluşturulan ve kullanıcının oluşturduğu yayın nesnelerine başvurmak için kullanabileceğimiz ilgili bir ad. Bu ilgili isim, Post'un yazarı olan Post.author'un aksine, gönderiyi gönderen kullanıcıya veriyor. Artık bir kullanıcının user.posts.all () veya work.posts.all () çalıştırmasıyla yapılan yayınları alabiliriz. Şimdi, girişlerimizi daha esnek hale getirelim. Sitemizi zaten, sadece bir oturum açmasına izin vereceğimizi sınırlandırarak derecelendirerek kimlik avına çok daha az savunmasız hale getirebiliriz.Site, bu oldukça kolay. Uygulamamızı geliştirmeye devam ederken daha önce her kullanıcı hakkında bazı bilgileri saklamaya başlayalım. Kullanıcılar/Models.py düzenleme, aşağıdakileri ekleyin

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='')
Bu modelin post modeline oldukça benzediğini unutmayın. DateTime alanlarında varsayılanlar ayarlamamıza izin verecek ek bir içe aktarma, Timezone'umuz var ve ayrıca yazı gibi bir karaktere ve metin alanımız var. Bu zaman damgalarını kullanmak, siteyi güvence altına almamıza ve kullanımını anlamamıza yardımcı olur ve metin alanları, web sitesinde her kullanıcı veya yazar hakkında bilgi vermemize izin verir. Onetoonefield tek küçük husus olmalıdır, öngörü ile tamamen aynı davranır, ancak sonraki model başına sadece bir tane vardır. Bu şekilde, kullanıcının yalnızca bir profili vardır, ancak birçok yayın olabilir. Şimdi, girişimizi geliştirelim ve profili hesaba katmak için görünümleri kaydedelim. İlk olarak, kullanıcılar/views.py düzenleyin ve kayıt görünümüne odaklanın:

# … Miktarlar
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) # Kullanıcı için bir profil oluşturmak için bu satırı eklediğinizden emin olun
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Bu, herhangi bir bilgiyi doldurmadan kullanıcı için bir profil oluşturur. Şimdi, kullanıcı hesabının çok sık oturum açılamayacağından emin olmak istiyoruz veya en azından şifreler çok sık denenemeyeceğinden emin olmak istiyoruz, bu yüzden giriş görünümünü güncelleyelim.

# … Miktarlar
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(): # Şimdi kullanıcının giriş yapıp yapamayacağını kontrol ettiğimizi unutmayın.
            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: # Giriş başarılı değilse,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Bu, kullanıcıların profilini güncellediğimiz kısım
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Bu yüzden birkaç saniye tekrar giriş yapamazlar
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Bu, güvenliğin temel temeldir. Sitenin, olası her şifre kombinasyonunu, hatta bunlardan birkaçını aynı anda deneyen birine karşı savunmasız olmadığından emin olun. Bu, şifrelerini bilen ve sadece birkaç cihazda oturum açan sıradan kullanıcı için sinir bozucu olmayacak, ancak çok sayıda kimlik avı robotunu uygulamadan uzak tutacaktır. Geçmişte bir zaman olması gereken bir değişken olan Can_login ile bir IF ifadesi eklediğimizi ve aynı kullanıcı adını kullanarak her başarısız girişle güncellediğimizi unutmayın. Bu şekilde, kötü niyetli bir kullanıcı, bir şifreyi hızlı bir şekilde tahmin edemez. DateTime.timedelta () 'deki saniye sayısı da güncellenebilir ve web sitesi daha esnek ancak biraz daha az kullanılabilir olacaktır. 15 ile başlamayı tavsiye ederim. Unutmayın, işimizi kaydetmek için bir yedekleme komut dosyası oluşturduk, bu yüzden devam edelim ve her şeyin kaydedildiğinden emin olmak için şimdiye kadar sahip olduğumuzu yedekleyelim. Komutu çalıştırın:

sudo backup
Bir kez daha, bu işinizi şimdiye kadar kurtaracak. Çalışmanızı kaydetmek için sık yedeklemeler yapmanızı öneririm ve hatta otomatik olarak bir yedekleme işi çalıştırmak isteyebilirsiniz. Bunu Cron adlı bir UNIX yardımcı programı kullanarak yapabilirsiniz. Bu yardımcı programı etkinleştirmek için aşağıdaki komutu çalıştırın ve şifrenizi girin:

sudo crontab -e
Zaten aşina olmanız gereken Metin Düzenleyicisi için zaten Seçenek 1'i seçmediyseniz ve ok tuşlarını kullanarak dosyanın altına kaydırın. Aşağıdaki satırı ekleyin:

0 * * * * sudo backup
CRON, A * veya bir sayı komutu ne zaman çalıştıracağını temsil eden dakika, saat, ay, ay, haftanın gününü kullanır. Dakika için 0 ve * seçeneklerin geri kalanı için *, dakikanın başında her saatin ilk dakikasında bir komut çalıştırabiliriz. Bu, kodu otomatik olarak yedeklememizi sağlar. Sudo ile yürütüldüğünde Cron'un tüm işleri kök olarak çalıştırılır, bu yüzden her saat bir şifre yazmamız gerekmez. Parola kullanmadan kodumuzu yedeklemeyi kolaylaştırmak için yedekleme komutumuzun parolasını devre dışı bırakalım. Bunu aşağıdaki komutu yürüterek ve bir şifre girerek yapacağız:

sudo visudo
Şimdi, dosyanın altına kaydıralım ve başka bir satır ekleyelim:

ALL ALL=NOPASSWD: /bin/backup
Bu, herhangi bir kullanıcı olarak “yedekleme” komutunu şifre olmadan çalıştırmamızı sağlar. Bunun biçimi kolaydır, sadece “tümü = nopasswd:/bin/” ile satır önek ve örneğin/usr/bin/içinde bulunan komut/bin/yedekleme komutu ile biter. Şimdi e -posta ile çalışmaya başlayalım. E -posta web siteleri için gerçekten önemlidir, çünkü bir web sitesini daha güvenli tutmanın, kullanıcıların gerçek insanlar olduğunu ve hatta müşterilere pazar ürünleri veya hizmetleri olduğunu doğrulamanın bir yoludur. İnternette sık sık e -postalarını kontrol eden birçok kişi, ilgilendikleri ürün ve hizmetler hakkında her türlü pazarlama e -postasını alır. Bir Django web sitesinde e -posta etkinleştirme söz konusu olduğunda birkaç seçenek vardır ve seçebilirsiniz. Hangisi sizin için en iyi şekilde çalışırsa. İlk olarak, alan adınızdan e -posta göndermenizi sağlayacak ve minimum kod gerektirecek bir e -posta hizmeti için ödeme yapabilirsiniz. Bunu sunan Google Workspace, SendminBlue, MailGun ve daha fazlası gibi birçok hizmet var. Aksi takdirde, bina dışısınızSeyirden sunucunuzdaki kendi e -posta hizmetiniz. Daha fazla kod olmasına ve özel barındırma gerektirmesine rağmen bu seçeneği tavsiye ederim. Büyük olasılıkla ev bilgisayarınızdan bir posta sunucusu başlatamazsınız, bu yüzden bulutta bir sunucu başlatmadan ve içinde kendi posta sunucumuzu oluşturmadan önce e -posta göndermek için yapılandırmayı ve kodu inceleyelim. İlk olarak, Settings.py'yi aşağıdakilerle düzenleyin

nano app/settings.py
Uygulama, StartApp ile oluşturduğunuz uygulamanın adıdır. Aşağıdaki satırları ekleyin:

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)
Uygulamanızı dağıtmaya hazır olduğunuzda bunları değiştirdiğinizden emin olun, bunu daha sonra tekrar ziyaret edeceğiz. E -posta_address ayarı göndermek istediğiniz e -posta olmalı ve sunucu için oluşturduğunuz şifreye parola (e -posta_host_password) ayarlanmalıdır. Parolayı, aşağıdaki mantığı kullanarak koddan uzak tutmak için bir yapılandırma dosyasından yüklüyorum, bu satırların üstünde Settings.py:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Daha sonra, nano'yu aşağıdaki gibi kullanarak yapılandıran bir JSON dosyası ayarladım. Dosyayı düzenlemek için:

sudo nano /etc/config.json
Aşağıdaki satırları ekleyin:

{
	“EMAIL_HOST_PASSWORD”: “<some password here>”
}
Yapılandırma dosyasını düzenlemeye ve uygulamada kullanacağımız tüm şifreleri ve anahtarları eklemeye devam edeceğiz. Şimdilik, Python kullanarak nasıl e -posta göndereceğinizi hızlı bir şekilde inceleyelim. İlk olarak, kullanıcılarımıza gönderebileceğimiz bir doğrulama e -postası için bir şablon oluşturalım ve kullanıcı şablonları dizinine koyalım. Bu şablon HTML'de yazılacaktır.

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>
 
Bu e -posta oldukça basit. Bir kullanıcının bağlamı, site için temel URL ve kullanıcının e -postasını doğrulamak için kullanılan bir kullanıcı kimliği ve jetonu alır. Şablonu oluşturmak için bazı Python kodu yazmadan önce Settings.py'de temel URL'yi tanımladığınızdan emin olun. Devam edin ve başlangıçta APP/settings.py'ye aşağıdaki satırları ekleyin.

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

BASE_URL = PROTOCOL + '://' + DOMAIN
Sonunda, siteniz internet için hazır olduğunda ve dağıttığınızda, alan adınızı siteyi temsil etmek için satın aldığınız alan adı olarak tanımlamak istersiniz. Sitenize erişmek için NAVBAR'a yazacağınız ad budur. Şimdilik, etki alanını boş bırakabilir veya bir yer tutucu kullanabilirsiniz. Ayrıca site_name'i seçtiğiniz sitenize vermek istediğiniz bir adla değiştirmek isteyeceksiniz. E -posta göndermeden önce, asla sona ermeyen bir hesap etkinleştirme jetonuna sahip olabilmemiz için bir jeton jeneratörü oluşturalım. Bunu, aşağıdakilere benzeyen bir hesap etkinleştirme jetonu oluşturarak ve içe aktararak yapabiliriz. Dosyayı düzenleyin:

nano users/tokens.py
Aşağıdaki kodu ekleyin:

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()
Bu temel jeton jeneratörü, kullanıcıyı bir URL'ye gönderebileceğimiz bir jeton oluşturur ve kullanıcı e -postalarını doğrulamak ve hesaplarını etkinleştirmek için kullanabilir. Ardından, nasıl bir e -posta göndereceğinizi görelim. Nano'yu kullanarak, kullanıcıları/e -posta.py'yi düzenleyin.

nano users/email.py
Doğrulama HTML e -postasının gönderilmesi şöyle görünecektir:

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)
Bu oldukça basit. E -postayı göndermek, e -postayı şablonlarla ve ayarlarımızı oluşturmak için ihtiyacımız olan işlevleri içe aktarıyoruz ve daha sonra e -postayı şablon adına göre tanımlıyoruz ve bir işlev kullanarak kullanıcıya gönderiyoruz. Send_html_email gönderme işlevini tanımlamadığımızı fark edeceksiniz, ancak bunu zaten kullanıcılar/e -posta.py'ye eklediğimiz kodun altına yazalım

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()
Bu biraz daha karmaşık ve henüz tüm bu kodu çalıştırmaya hazır değiliz. Bir UNSub_Link tanımladığımıza dikkat edin, kullanıcının e -postalarımızdan iptal etmek için kullanabileceği bağlantı. Bu önemlidir, çünkü kullanıcıların herhangi bir zamanda görmek istemedikçe e -postalarımızdan çıkabilmeleri gerekecektir. Ayrıca, HTML etiketlerinden çıkarılmış HTML mesajı olan mesajımıza bir metin alternatifi de ekliyoruz. Son olarak, e -postanın gönderilip gönderilmeyeceğini kontrol ediyoruz ve eğer yapmadıysa, kullanıcının profilinde e -postalarının geçerli olmadığını işaretliyoruz. Tüm bunları işe yarayabilmemiz için kullanıcı modellerine geri dönelim. Abonelikten çıkma bağlantısı oluşturmak için bir işlev tanımlamamız ve kullanıcının e -postasının geçerli olmadığını işaretlemek için bir Boolean alanı tanımlamamız gerekir. İlk olarak, kullanıcıların/modellerin en üstüne aşağıdaki içe aktarma ekleyin.

nano users/models.py

# …
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
Ardından, jetonu yapmak için kullanıcı modeline işlevler ekleyelim ve e -postayı etkinleştirmek için kullanılan jetonun yanı sıra kullanıcının postalarını başarıyla alıp almadığını kaydetmek için alanı kontrol edelim. Kullanıcılar/Models.py'de tekrar, modelin sonuna aşağıdaki kodu ekleyin (girintili kod)

# …
    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) # 30 gün boyunca geçerli
        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,})
Bu oldukça basittir, belirli bir süre sonra sona erecek bir jeton oluşturmak için temel bir kriptografi aracı olan bir zaman damgası kullanıyoruz ve geçerli olup olmadığını kontrol etmek için başka bir işlevi de kullanıyoruz. Bu jetonları iki kez, bir kez e -postayı doğrulamak için ve bir kez abonelikten çıkma bağlantısı için kullanıyoruz. Artık bunlara sahip olduğumuza göre, yapmamız gereken son iş görüşlerinde. Kullanıcılar/Views.py içinde, e -posta adresini doğrulamak ve abonelikten iptal etmek için görünümler ekleyelim.

nano users/views.py
İlk olarak, aşağıdaki ithalatı ekleyin. Birkaç ekstra attım, böylece daha sonra tekrar daha fazla ürün içe aktarmak zorunda kalmayacağız.

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 # Doğrulama e -posta gönderme işlevini içe aktardığınızdan emin olun
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
Bu ithalatlardan bazılarına zaten sahip olabilirsiniz, ancak bunları tekrarlamak zarar vermez. Diğer ithalatların yanı sıra, kullanıcılar.tokens'ten doğrulama e -posta gönderme işlevini ve hesap_activation_token'i aktarmanız gerekecektir. Şimdi, dosyanın altına aşağıdaki kodu ekleyin:

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)):
        # abonelikten çıkın
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    # Aksi takdirde giriş sayfasına yönlendirin
    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()
# SendWelomeMail (istek, kullanıcı)
        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})
Bu çok fazla kod. Hadi parçalayalım. Temiz ve basit ilk işlev, kullanıcıyı posta listesinden çıkarır. İkinci işlev e -postalarını etkinleştirir ve yorumlanan bir işlev olan SendWelomeMail eklediğimi fark edeceksiniz. Bir karşılama e -postası göndermek için bir e -posta şablonu ve işlev tanımı kullanabilirsiniz, henüz yapmadım. Etkinleştirme e -postalarının süresi dolduğundan, attığım son işlev önemlidir. Bu nedenle, aktivasyon e -postasını bir süre önce yeniden göndermemiz gerekecek. Bunun için temel bir form kullanabilir ve doğrulama e -postasını göndermek için işlevi arayabiliriz. Bunu yapmadan önce, kayıt görünümüne bir işlev çağrısı ekleyerek ilk etapta gönderildiğinden emin olalım. Bu satırı, Kayıt görünümünde, DEF Register'daki yönlendirmeden hemen önce kullanıcılar/views.py ekleyin.

nano users/views.py

# … (Sonra) Def Register (istek):
            send_verification_email(user)
# … (Daha önce) yönlendirme (
Bu kod snippet'ine ilk ve son satırları eklemenize gerek yoktur, sadece kayıt görünümünün doğrulama e -postasını kullanıcıya gönderdiğinden emin olun. Şöyle görünmeli:

# … Miktarlar
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) # Bu çizgiyi eklediğinizden emin olun!
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Şimdi, etkinleştirme e -postasını yeniden göndermek için bir form eklememiz gerekecek. Kullanıcılar/forms.py'de aşağıdaki formu ekleyin:

# … (Miktarlar)
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)
Ayrıca, bu yeniden e -posta etkinleştirme formuna karşılık gelen bir şablona ihtiyacımız olacak. Bu şablonu ekleyelim. Dosyayı düzenleyin:

nano users/templates/users/resend_activation.html
Ardından, dosyaya aşağıdaki kodu ekleyin.

{% 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 %}
Vay canına, bu çok! Şimdi, kodu sunucumuza dağıttığımızda, html e -posta gönderebilir ve e -postayı tıklayarak kullanıcı hesaplarını etkinleştirebiliriz. Ayrıca basit bir karşılama e -postası göndermek isteyebiliriz, bu yüzden bunu nasıl yapacağımızı görelim. Kullanıcılara/E -posta.py'ye geri dönün, aşağıdaki kodu ekleyin:

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)
Ayrıca, tüm bu bilgileri oluşturmak için bir şablona ihtiyacımız olacak. Web sitemde, şablon aşağıdaki gibi görünüyor, ancak istediğiniz gibi biçimlendirebilirsiniz.
 
<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>
 
Kapanış gövdesi veya HTML etiketlerimiz olmadığını unutmayın, çünkü bunları HTML abonelikten çıkma bağlantısını eklediğimizde ekliyoruz. Bunlar önemlidir, ancak onları iki kez tanımlamak istemiyoruz. Peki sırada ne var? Uzun bir yol kat ettik. Gerçekten, siteyi bir sunucuya dağıtmaya hazır olmalıyız. @Login_required dekoratörünü ekleyebilir ve görüşlerimizi güvende edebilir, kullanıcı kayıtları alabilir, uyumlu e -posta gönderebilir ve bir web sitesinin alakalı kalmak için ne yapması gerektiğinin temeli olan önbellek bilgileri yapabiliriz. Birkaç daha kullanışlı özellik ekleyeceğiz ve ardından sitemizi güvenli ve uygun hale getirmek için kodumuzu uzak bir sunucuya dağıtmak, bir posta sunucusu, etki alanı yapılandırması ve filtreler ayarlamak için bir temel oluşturacağız. Ayrıca bir şifre sıfırlama görünümüne ihtiyacımız var, bu yüzden bunu gerçekten hızlı bir şekilde ekleyelim. Django'nun yerleşik şifre sıfırlama görünümü bazı işlevlerde bozulur, ancak kendi görünümümüzü, e -posta şablonumuzu, formlarımızı ve URL modellerimizi nasıl yazacağımıza bakacağız. İşte kullanıcılar/views.py'de görünüm nasıl görünüyor

# ... Miktarlar
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)
Bu form Django'da yerleşiktir, ancak şifre sıfırlamasını, kullanıcıları/şablonları/kullanıcıları/parolayı/parolayı_reset_confirm.html'yi onaylamak için bir şablona ihtiyacımız olacak
 
{% 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 %}
 
Ayrıca, kullanıcılar/şablonlarda/kullanıcılar/parola_reset.html'de basit bir formla bir şifre sıfırlama e -postası göndermek için bir şablonumuz var
 
{% 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 %}
 
E -postanın kendisi için şablon basittir, kullanıcılar/şablonlar/kullanıcılar/parola_reset_email.html'de şifreyi sıfırlamak için bir bağlantı oluşturan temel bir HTML dosyasıdır. Django bu dosyayı otomatik olarak yorumlayacaktır.
 
<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>
 
Ayrıca iki şablon daha da ihtiyacımız olacak. Birincisi, e -postanın gönderildiğini doğrulamaktır. Bunların görüntüleri zaten Django'da, bu yüzden sadece urls.py'de ele almamız gerekiyor. Bu şablon kullanıcılar/şablonlar/kullanıcılar/parola_reset_done.html'de bulunur
 
{% 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 %}
 
Ve son olarak, şifre sıfırlamanın tamamlandığını doğrulamak için kullanıcılar/şablonlar/kullanıcılar/parola_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 %}
 
Şimdi, bu görüşler için URL modellerine ihtiyacımız var. Kullanıcılar/urls.py'de aşağıdaki URL modellerini ekleyin:

urlpatterns = [
    # ... Önceki URL'ler burada
    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'),
]
Dört şablon, bu çok! Ancak şimdi, tüm web tarayıcısından ihtiyacımız olan her zaman kullanıcının şifresini sıfırlayabildiğimizden emin olabiliriz. Bunun çok fazla kod olduğunu anlıyorum. Biraz kafanın üzerinde görünüyorsa, sorun değil. Gelişeceksiniz, anlayışınız iyileşecek ve çok yakında kodla çok daha yetkin hale geleceksiniz. Tamamen kaybolursanız, kendi hızında çalıştıktan sonra bu yazılıma daha sonra geri dönmenizi tavsiye ederim. Bunlar genellikle başlamak için ücretsizdir ve bu projeye geri döndüğünüzde başarılı olmanız gereken her şeyde size rehberlik edecektir. Devam etmeye hazır olduğunuzu düşünüyorsanız, okumaya devam edin, daha sonra, kodunuzu uzak bir sunucuya dağıtmayı ve bir posta sunucusunu kurmayı ve BASH kullanarak dağıtımınızı otomatikleştireceğiz, böylece her zaman yeni bir proje ayarlayabilirsiniz. Birkaç basit komut. Uzak bir sunucuya dağıtmadan önce yapmamız gereken son şey, sitemizi biraz daha güvenli hale getirmektir. SenOturum açma görünümünün yalnızca bir kullanıcı adı ve şifre aldığına ve çok faktörlü bir kimlik doğrulama veya bir zaman kodu olmadığına dikkat edin. Bu kolay bir düzeltmedir ve aynı kodla, sitemizin metin mesajları göndermesini ve hatta sunucuya gönderilen metin mesajlarına yanıt vermesini sağlayabiliriz. Başlamak için, kullanıcı modellerine geri döneceğiz ve her bir girişi temsil edecek bir zaman damgası imzalayan ekleyeceğiz. Ayrıca, girişimize ekstra güvenlik eklemek için kullanılacak kullanıcı modeline benzersiz, dönen bir tanımlayıcı ekleyeceğiz. Kullanıcı modellerini, kullanıcıları/modelleri düzenleme, aşağıdakileri ekleyin

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# UUID, zaman damgası imzalayan ve URL jeneratörünü (ters) içe aktardığınızdan emin olun.
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='')
    # Bu kodu buraya ekle
    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)

    # Ve bu işlevi ekle
    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) # 3 dakika geçerli
        except (BadSignature, SignatureExpired):
            return False
        return True
Yorumların yanı sıra kullanıcılarınızın/modellerinizin böyle göründüğünden emin olun ( #ile satırlarda kod). Bunu kırmak, basit. Birkaç ithalatımız var, güvenli bir kod oluşturabilen ve geçerli olduğundan emin olmak için, sadece bir kez kullanıldığından ve belirli sayıda saniyeden daha eski olmayan bir kriptografik yardımcı program olan bir zaman damgası var. Ayrıca, jetonun imzalanmasında ve jetonun kullanıcıya gönderildiği URL'de kullanıcılarımızı tanımlayan benzersiz bir tanımlayıcı olan bir UUID kullanıyoruz. Bu temel şifrelemeyi iki faktörlü bir kimlik doğrulama görünümü oluşturmak için kullanacağız. Başka bir şey yapmadan önce, kullanıcı modellerimiz güncellenmesi için geçişleri çalıştıralım. Manage.py ile dizinde, geçiş yapmak ve tamamlamak için aşağıdaki komutları çalıştırın.

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Bu önemlidir, çünkü modellerde her değişiklik yaptığımızda, modelleri gerçekten kullanmadan önce tabloları oluşturmamız ve veritabanını varsayılanlarla güncellememiz gerekecektir. Ardından, ikincil bir kimlik doğrulama görünümüne yönlendirmek için giriş görünümümüzü doğaçlama yapalım. Kullanıcılar/Views.py'de oturum açma işlevini kaldırın ve kullanıcı modellerinde yeni oluşturduğumuz URL'ye yönlendirin.

# … Miktarlar

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(): # Şimdi kullanıcının giriş yapıp yapamayacağını kontrol ettiğimizi unutmayın.
            # Burada bulunan Auth_login işlevini kaldırın
            messages.success(request, 'Your password was accepted. Please continue.')
            if user.profile.mfa_enabled:
                return redirect(user.profile.create_auth_url()) # Not burada yeni bir URL'ye yönlendiriyoruz
            else: # Kullanıcı çok faktörlü kimlik doğrulama kullanmıyorsa, bunları giriş yapın.
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # Giriş başarılı değilse,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Bu, kullanıcıların profilini güncellediğimiz kısım
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Bu yüzden birkaç saniye tekrar giriş yapamazlar
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Yani bu oldukça basit, şimdi oluşturduğumuzda iki faktörlü kimlik doğrulama görünümüne yönlendirmenin bir yolu var. Ayrıca kullanıcının bir telefon numarası eklememesi durumunda bir geri dönüşümüz var. Yakında bir telefon numarası eklemek için temel bir görünüm ekleyeceğiz ve yakında bir kısa mesajla oturum açacağız. İlk olarak, kodumuzdan kısa mesaj göndermenin kolay bir yoluna ihtiyacımız var. Bunu yapmak için bir dizi API arasından seçim yapabiliriz, ancak bence en kolay olan Twilio. Ayrıca daha küçük projeler için iyi fiyatlandırma ve toplu indirimler sunarlar. Twilio.com'da bir hesap oluşturun, projenizle ilgili bazı ayrıntıları doldurun, bir telefon numarası satın alın ve API anahtarlarınızı settings.py'nize kopyalayın. Ardından, bu kodu yeni bir dosya, kullanıcılar/sms.py altına ekleyin.

nano users/sms.py

# Gerekli tüm paketleri içe aktarın
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

# Bu kod metni Twilio ile gönderir
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())

# Bu kadar basamaklı bir sayı elde etmek için bir yardımcı işlev
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# Kullanıcıyı doğrulamak için metni gönderin
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)))

# Bir kullanıcıya bu işlevle herhangi bir metin gönderin
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# Kodu bu işlevle doğrulayın
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

# Zamanı doğrulayın
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
Bu satırları anahtarlarınızla ekleyerek ayarlarınızı uygun şekilde değiştirdiğinizden emin olun:

# Bunları Twilio Gösterge Tablonuzdan Kopyaladığınızdan Emin Olun
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 # TFA sayfasının somutlaştırıldıktan sonra etkin olduğu dakika sayısı
İlk olarak, iki faktörlü kimlik doğrulama görünümümüz için formlara ihtiyacımız olacak. Kullanıcılar/forms.py düzenleme, aşağıdaki kodu ekleyin.

# … Miktarlar
from django import forms

# Telefon numaramıza girmek için bir form
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

# Kimlik doğrulaması için bir form
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.'
    }
Ardından, kullanıcılar/views.py'de görünümleri oluşturalım

# … Miktarlar
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})
Bu görüşlerin her ikisi için de şablonlara ihtiyacımız olacak. Önce MFA şablonunu ekleyelim.

nano users/templates/users/mfa.html
Bu HTML kodunu şablona ekleyin
 
{% 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 %}
 
Bu oldukça açıklayıcı. Form bir kod veya boş bir kod gönderir ve boş bir kod alırsak kodu gönderdiğimizi fark edersiniz. Sonra sadece iki gönderme düğmemiz var ve bu şekilde kodu her iki düğmeyle gönderebiliriz. Ardından, bir telefon numarası eklemek için basit bir form ekleyeceğiz.

nano users/templates/users/mfa_onboarding.html
Aşağıdaki HTML'yi ekleyin:
 
{% 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 %}
 
Bu form çok daha basittir, sadece oluşturduğumuz telefon numarası formunu oluşturur ve kullanıcının bir telefon numarası eklemesini sağlar. Bu gerçekten iyi görünüyor! Her şey düzgün bir şekilde ayarlandığı sürece, mesaj gönderebilmeli ve URL kalıplarını eklediğimiz anda kullanıcıyı telefon numaralarıyla birlikte günlüğe kaydedebilmeliyiz. Kurmamız gereken son şey bir profil görünümüdür, böylece kullanıcının oturum açmadan telefon numaralarını değiştirebileceğinden emin olabiliriz. Ayrıca, sonunda bir "Çıkmak için Durun" seçeneği eklemek isteyeceğiz, böylece kullanıcı metin yazabilir Gelecekteki metin mesajlarından vazgeçmek için “Dur”. Kullanıcılara/views.py'ye bir profil görünümü ekleyelim. Bu görünüm, kullanıcının biyografisini, e -postasını, kullanıcı adı ve telefon numarasını güncelleyecek ve çok faktörlü kimlik doğrulamasını etkinleştirmemize izin verecektir. İlk olarak, kullanıcılar/forms.py'de iki forma daha ihtiyacımız olacak

# ... Miktarlar
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']
Ardından, bu formların her ikisini de kullanmak için bir görünüm oluşturabiliriz. Kullanıcılar/views.py düzenleyin ve görünümü ekleyin.

# Bu ithalatı ekleyin
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)
Ayrıca bu görüş için bir şablona ihtiyacımız olacak.

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 %}
 
Bunun oldukça basit bir form olduğunu fark edeceksiniz, ancak içinde formun içeriğini güncellenirken otomatik olarak gönderen bazı JavaScript var. Bu, her seferinde göndermek zorunda kalmadan düzenlemeler yapabilirsiniz. Daha sonra, kullanıcıların URL modellerinde tüm bu görünümleri temsil eden URL'lere ihtiyacımız var. Kullanıcıları/urls.py'yi düzenleyin ve bu kodu ekleyin:

# … Önceki kod, içe aktarma
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
# … Daha önce girdiğimiz URL desenleri, sonraki üç satırı ekleyin
    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'),
]
Şimdi projemizi test etmek için iyi bir zaman. Ama önce, başka bir yedekleme yapalım.

backup
Ve sunucuyu çalıştırın. Bir Linux sunucusuna dağıtmadan önce, hesapta iki faktörlü kimlik doğrulamasını etkinleştirmek iyi bir fikirdir. Bunu profil URL'mize,/kullanıcılar/profil//telefon numaramıza girdikten sonra kimlik doğrulamayı etkinleştirmek için kutuyu kontrol edip formu göndereceğiz.

python manage.py runserver localhost:8000
Web tarayıcınıza giderek web sayfasını ziyaret edin, bu örnekte Google Chrome kullanıyorum ve https: // localhost: 8000/hesaplar/profil/ Gerekirse oturum açabilir ve iki faktörlü kimlik doğrulamasını etkinleştirebilirsiniz. Bu projenin çalışması için bir sunucuya ihtiyacı var, böylece gerçekten posta gönderebilir. Ama önce, hataları görmek için bir yola ihtiyacımız var. Sunucuyu Hata Ayıklama Modunda çalıştırırsanız, Settings.Debug'a eşit olarak çalışırsanız, sunucunun hataları otomatik olarak gösterdiğini fark edeceksiniz. Bir üretim sunucusunda güvensiz olan hata ayıklama modu kullanmadan hataları göstermek için bunun için bir görünüm eklemeliyiz. İşleyebilmemiz gereken en önemli hatalar: Hata 500 - Kodumuzla ilgili bir sorun Hata 404 - Bulunamayan Bir Sayfa (Kırık URL) Hata 403 - İzin reddedilen hata Hatalar adı verilen bu hataları işlemek için yeni bir uygulama ekleyelim.

python manage.py startapp errors
Bunu daha önce yaptığımız gibi Settings.py'ye ekleyin, Installed_Apps ayarında ve uygulama Django projenizin adı olduğu App/urls.py'deki bazı görünümlere referans ekleyerek başlayın.

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
Hata görünümleri, şablonlar ve biraz ara katman yazılımı dışında ihtiyacımız olan tek şey bu. Bunları şöyle tanımlayalım:

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

# Görüşlerinizi burada oluşturun.
@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.'})
Ardından, bu hataları ele almak için ara katman yazılımı tanımlayalım. Bunu önce Middleware_Classes'e Acections.py'de, ara katman yazılımımızın adıyla ekleyerek yapacağız.

MIDDLEWARE_CLASSES = [
    # ... önceki ara katman yazılımı
    'errors.middleware.ExceptionVerboseMiddleware,
]
Ardından, ara katman yazılımı ekleyelim.

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.')
Kodumuzdaki hataları izlememize yardımcı olan bir iş parçacığı yerel kullanarak mevcut istisnayı almak için bir işlev ekliyoruz. Şablonlar açısından, sadece bir tanesine ihtiyacımız var, çünkü görünümdeki başlığı dinamik olarak tanımlıyoruz. Şablonun sadece başlık ve “izleme”, bağlamdaki hatamız izlemesi gerekiyor.

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
Bu bizim en basit şablonumuz, ancak projemizdeki hataları görmek bu kadar kolay. Ardından, ayarlarda hata ayıklamayı devre dışı bırakalım.

nano app/settings.py
Bu satırı doğru olarak ayarlayın ve yanlış olarak değiştirin

DEBUG = False
Devam edin ve uygulamayı şimdi yedekleyin. Uzak bir Linux sunucusuna konuşlandırılmaya ve oradan özellikler eklemeye hazırız.

sudo backup
Bu kodu bir sunucuya göndermeden önce, kodla ilgili bazı sorunlar olabileceğini düşünmeliyiz. Davaya bağlı olarak, kendilerine gönderilen bilgileri kabul eden siteler, spam yayınlanmasıyla ilgili sorunlar ve spam'i kaldırmada zorluk yaşayacaktır. Bu hemen gerçekleşmemeli, ancak eğer gerçekleşiyorsa, daha sonra sitedeki spam'i otomatik olarak ılımlı bir şekilde nasıl denetleyeceğinizi ve robotların siteye erişmesini daha zor hale getirip kullanıcı hesaplarını nasıl devre dışı bırakacağınızı ve bir kullanıcının kimliğini nasıl doğrulayacağını inceleyeceğiz. Bir parmak izi veya yüz tanıma gibi kimliklerinin veya biyometrik taramalarının taranması. Üretimde incelediğimiz çok faktörlü kimlik doğrulama örneğine bakıldığında, işler farklı olabilir. Nasıl oran sınırlama girişleri ve süresi dolmuş jetonlar olduğumuza dikkat edin. Robotlar bir siteye erişiyorsa, kullanıcının aynı anda kodlar girebileceği için iki faktörlü kimlik doğrulaması daha zor olabilir. Bununla mücadele etmek için, kullanıcı modellerinde bir model kullanalım, site ile nasıl etkileşim kurduğumuzu beyan etelim.Bir telefon numarası ile çok faktörlü kimlik doğrulama kullanarak kimlik doğrulama. Ayrıca e -posta ile kimlik doğrulaması yapmak için bir seçenek ekleyeceğiz. Kullanıcı modellerini düzenleyerek başlayın

nano users/models.py
Eklediğimiz model böyle görünmeli. Herhangi bir yönteme ihtiyacımız yok, sadece bir kimlik, kullanıcı, zaman damgası, son kullanma, uzunluk ve herhangi bir çok faktörlü kimlik doğrulamasına karşı denemeler (bir telefon veya e -postaya gönderilen 123456 gibi bir kod).

# Web sitesine giriş yapmak için kullanılan temel bir jeton
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)
Ayrıca kullanıcımıza bir ayrıcalık ekleyelim ve sonunda ayrıcalıklı kullanıcıları otomatik olarak kaydolmaya geçmeden önce bunu manuel olarak ayarlayacağız. Kullanıcı modellerinde bu satırı profile ekleyin:

    vendor = models.BooleanField(default=False)
Veritabanındaki değişikliklerde olduğu gibi, Django'da bir Models.py dosyasını her düzenlediğimizde geçiş yapmamız ve veritabanını taşımamız gerekir. Unutmayın, bunu yapmak için önce kaynağı kullanırız (terminal açık olduğundan beri zaten kullanılmamışsa) ve daha sonra göçü yapmak ve göç etmek için python manage.py.

cd project-directory-you-named # (Gerekirse)
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Şimdilik, kabuğu kullanarak satıcı olarak oluşturduğunuz hesapları askere alabilirsiniz.

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
Şimdi, bu jetonu kullanmak için çok faktörlü kimlik doğrulama görünümümüzü geliştirelim. İlk olarak, MFA yardımcı programlarımızı değiştirmemiz gerekiyor. Nano kullanma,

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

# E -posta veya telefon numaralarını kullanarak kullanıcıyı doğrulayın
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() # Jetonu URL'den geçirilen değerle filtreleyin (bir 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)) # Bu oturum oluşturulmadıysa, yaratın
    user = User.objects.filter(id=token.user.id).first() # Kullanıcıyı jetondan alın
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # Zaten doğrulanmışlarsa, bunları giriş yapın
    if not user: raise PermissionDenied() # Kullanıcı bulunmadıysa inkar edin
    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): # Auth belirtecini kontrol edin
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Halihazırda giriş yapmadılarsa kullanıcıya giriş yapın
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # Çok faktörlü kimlik doğrulamaları hakkında bir son kullanma
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # Kullanıcıyı bir sonraki sayfaya yönlendirin
    if not user.profile.mfa_enabled: # MFA'nın etkin olup olmadığını kontrol edin
        if not check_verification_time(user, token): # Zamanı kontrol edin
            user.profile.mfa_enabled = False # Telefon numarasını temizle
            user.profile.enable_two_factor_authentication = True # MFA'yı etkinleştir
            user.profile.phone_number = '+1' # Telefon numarasını devre dışı bırakın
            user.profile.save() # Profili Kaydet
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # MFA'ları etkin değilse kullanıcıyı kaydedin
            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): # İstek bir yayın isteği ise
        form = TfaForm(request.POST) # Formu somutlaştır
        code = str(form.data.get('code', None)) # Kodu alın
        if code and code != '' and code != None: # Boş olmadığından emin olun
            token_validated = user.profile.check_auth_token(usertoken) # Auth belirtecini kontrol edin
            p = user.profile
            is_verified = check_verification_code(user, token, code) # Kodu kontrol edin
            p.mfa_authenticated = is_verified
            if token_validated: # Eğer her şey
                if is_verified: # Sırayla
                    user.profile.mfa_enabled = True # MFA'yı etkinleştirin (henüz etkinleştirilmezse)
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Kullanıcıya giriş yapın
                    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(): # Bir sonraki parametre için bir sorgulama oluşturun (varsa)
                        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) # Yeniden yönlendirmek
                    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: # Jeton geçersizse
                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: # Çok fazla girişim olsaydı
                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): # E -postayı (veya metni) gönderin
                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('/'))
    # Formu oluşturun (istekler almak için)
    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'})
Bu kodu eklerken, bir e -posta göndermek için işlevi içe aktardığınızdan emin olun. Dosyanın en üstünde, kullanıcı görünümleri (diğer ithalatlarla), ekleyin

from .mfa import send_verification_email as send_mfa_verification_email
Şimdi, bunlardan herhangi biri işe yaramadan önce bu işlevi yazmamız gerekiyor. E -posta işlevimizi genişletmeli ve doğrulama koduyla kullanıcıya bir e -posta göndermelidir.

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))
Yani bunların hepsi harika çalışıyor, şimdi oturum açmak için bir telefon numarasına veya e -postaya bağlı çok faktörlü bir kimlik doğrulama sistemimiz var. Ancak, kaldırmak veya en azından şartlarımızla işbirliği yapmayan kullanıcıları gizlemek için bir yola ihtiyacımız var. Bunlar spam gönderenler, robotlar veya işimiz için iyi bir anlamı olmayan herkes olabilir. Web sitemdeki kullanıcıları izlemek için sahip olduğum bir manzaraya bir göz atın:

# tutarlar
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor # Bu testi oluşturmamız gerekecek

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # Kullanıcıların Listesini Alın
    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', { # Kullanıcıları bir şablonda iade edin
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
Bu kodun bir test kullandığını unutmayın, bu testi bir Tests.py dosyasında bildirmemiz ve içe aktarmamız gerekecektir. Kullanıcıları Düzenleme/Tests.py, Testi oluşturalım.

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
Bu, kullanıcılar/kullanıcılar. Html şablonu ile birlikte, şöyle bir şey görünen:
 
{% 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 %}
 
Şablonun başka bir şablon, kullanıcılar/_user.html içerdiğini unutmayın. Bir alt bölüme sahip ve genişlemeleri kullanmayan bir şablon kullanırken, şablonları ayırt etmek için dosyanın adından önce bir alt çizgiyi (_) eklemek için iyi bir fikir. Bunun bir sürü Jinja olduğunu unutmayın, bu değişkenlerin tümünü tanımlamayabilir. Ama kodum böyle görünüyor.
 
{% 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>
 
Ayrıca başka bir alt dönem, toggle_active.html'ye ihtiyacımız var. Bu şablon, bir kullanıcının etkin olup olmadığını değiştirmemizi sağlayan bir form olmalıdır.
 
<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>
 
Ayrıca, kullanıcı etkinliğini ve uygun URL kalıplarını değiştirmek için bir görünüm eklememiz gerekecek. Biz oradayken, buna ihtiyacımız olması durumunda bir kullanıcıyı silmek için bir görünüm ekleyelim.

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>')


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

class UserDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = User
    success_url = '/' # Başarı URL'sinde Yönlendirme
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return context

    def test_func(self): # Kullanıcının süper kullanıcı olup olmadığını test edin ve silme iznine sahip
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
Bu gerektiğinde pratik olsa da, bir kullanıcının silinmesi çoğu zaman gerekli olmamalıdır, sadece onları reddetmemiz gerekirse siteyi ziyaret eden kullanıcıların görünürlüğünü değiştirebiliriz. Eklediğimiz URL kalıpları böyle görünüyor. Nano ile kullanıcıları/urls.py'yi düzenleyin ve şu satırları ekleyin:

nano users/urls.py
Satırlar, “]” sonundan önce, ancak başlangıçtan sonra kullanıcı görünümlerindeki yollar listesine girmelidir.

# …
    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'),
# …
Şimdi, üzerinde çalışmaya devam edeceğimiz web sunucusuna indirebilmeniz için siteyi yedeklediğinizden emin olun. Komut satırından,

sudo backup
Şimdi sitemiz yedeklendi. Şimdi birkaç daha kullanışlı özelliğimiz var. Peki ya buradaki büyük resim? Bu kod hala internetten erişilemiyor, henüz posta sunucumuz yok ve uygulamamızı kapsamlı doğrulama sürecini ve siteyi keşfetmemize yardımcı olmak için pürüzsüz düzenleri ve ayrıcalıklı kullanıcıları kimlik doğrulamak için güvenli protokoller içerecek şekilde genişletmemiz gerekiyor. . Tüm bunlara ulaşacağız. Şimdilik en önemli şey, bir Ubuntu sunucusunda sadece birkaç satır Bash ile yapabileceğimiz bu kodu çevrimiçi alacak. Evde bir sunucunuz ve bağlantı noktalarını açmanıza izin veren bir işletme internet aboneliğiniz yoksa bunun için bir sunucu kiralamanız gerekecektir. Web sitemi kişisel olarak daireme yüklü bir HP Z440 üzerinde çalıştırıyorum, ancak temel ihtiyaçların sanal bir özel sunucu (VPS) kiralaması genellikle çok daha ucuz. Şimdi çalıştırdığımız kodun nispeten ince olduğunu, biz olmadan önce korunması ve geliştirilmesi gerektiğini unutmayın.Bir ürün oluşturmak için sahip olduğumuz şeyi kullanmaya hazır. İnternet ile ne yaptığınıza dikkat ettiğinizden emin olun, bu siteyi bir Linux sunucusunda web'e herkese açık olarak dağıttığınızdan emin olun, web sitenizle istenmeyen etkileşimleri engellemek için bir planınız olduğundan emin olun. Bu muhtemelen ilk başta bir sorun olmayacak, ancak bununla mücadele etmek için makine öğrenimi, yapay zeka ve bilgisayar vizyonu da dahil olmak üzere çeşitli çözümlere bakacağız. Sorun haline geldiğinde, bir çözüm için bu metne daha fazla bakın. Bir VPS kiralama açısından, gidebileceğiniz birçok yer var. Google Cloud, VPS sunucuları, Ionos, Kamatera, Amazon AWS ve daha fazla sağlayıcı, ihtiyaçlarımıza uygun bulut sunucusu çözümleri sunuyor. Formlarını tıklamanız ve başlamak için bir plan seçmeniz gerekir. Herhangi bir sağlayıcıyla temel bir planla gidebilirsiniz, ancak sağlayıcının e -posta göndermek için bağlantı noktası posta sunucusu bağlantı noktalarını açmanıza izin verdiğinden emin olun (bu, 587 ve bağlantı noktası 25 olmalıdır), bazı sağlayıcılar bu bağlantı noktalarını engeller. Şimdiye kadar vardıIonos ve Kamatera ile EST deneyimi, her ikisi de sınırsız e -posta göndermeme izin verecek ve fiyatlandırmaları oldukça ucuz. Yeni sunucunuza, kişisel bilgisayarınızdan, kişisel bilgisayarınız gibi sunucuyla uzaktan arayüz oluşturmanızı sağlayan SSH veya Secure Shell adlı bir protokol üzerinden bağlanacaksınız. Sunucuyu ayarladığınızda, barındırma sağlayıcısı muhtemelen bir SSH anahtarı eklemenizi isteyecektir veya size bir kullanıcı adı ve şifre verecektir. SSH anahtarı, kodu düzenlemek için komut satırından sunucuya nasıl giriş yapacağınızdır. SSH oluşturmak için aşağıdaki SSH-Keygen seçeneklerini kullanın

ssh-keygen
Dosyayı kaydedin ve gerektiğinde üzerine yazın, henüz yapmadıysanız SSH anahtarlarınızı döndürmek iyidir. Şimdi, SSH anahtarınızı görmek için aşağıdaki komutu kullanabilirsiniz. Kimliği doğrulamak için kullanabilmeniz için uzak sunucunuza kopyalamak isteyeceksiniz.

cat ~/.ssh/id_rsa.pub
Bu komutu yazarken bir SSH anahtarı göremediyseniz (“SSH-RSA AAA” ile başlayan uzun bir dizi basamak ve harf dizisi), bir RSA anahtarı oluşturmayı deneyin (daha güvenlidirler, bu yüzden bunları kullanmayı tavsiye ederim .) Aşağıdaki kod 4096 bit RSA SSH tuşu oluşturacaktır.

ssh-keygen -t rsa -b 4096
Ubuntu çalıştıran bir VPS oluşturun, ancak bunu yapmayı planlıyorsunuz. Sağlayıcılar web sitesindeki formları (Kamatera.com, Ionos.com veya benzeri) tıklayarak bir VPS oluşturduktan sonra, oturum açmak istersiniz. Bunu yapmak için SSH komutunu IP adresinizle kullanın (adresiniz (adresiniz Bu xx.xx.xx.xx gibi görünüyor). Ayrıca, örneğin Ubuntu gibi oluşturduğumuz sunucudaki varsayılan kullanıcı adına duyarlı olmanız gerekir.

ssh ubuntu@XX.XX.XX.XX
Bir şifre istenebilir, eğer bir şifre istenirse, girin. Varsayılan kullanıcı adını kullanmayacağız, bu yüzden yeni bir kullanıcı oluşturarak ve hesaplarına bir SSH anahtarı ekleyerek başlayalım. Sunucuya SSH'yi nasıl kullanacağını anlatan yeni bir SSHD_CONFIG dosyası ekleyerek başlayalım.

nano sshd_config

# Bu, SSHD sunucusu sistem çapında yapılandırma dosyasıdır.  Görmek
# Daha fazla bilgi için sshd_config (5).

# Bu SSHD,/usr/local/sbin:/usr/local/bin ile derlendi:/usr/sbin:/usr/bin:/sbin:/bin:/usr/oyunlar

# Varsayılan SSHD_CONFIG'deki seçenekler için kullanılan strateji
# OpenSsh, nerede varsayılan değerleri ile seçenekleri belirlemektir.
# Mümkün, ama onları yorum bırak.  Seçkin seçenekler geçersiz kılın
# Varsayılan değer.

# Port 22
# Adres family
# Liste Adresi 0.0.0.0
# Dinle Adres ::

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

# Sipherler ve anahtarlama
# Rekeylimit varsayılan yok

# Günlüğe kaydetme
# Syslogfacility auth
# Loglevel Bilgisi

# Kimlik Doğrulama:

# Logringracetime 2m
# Permitrootlogin Yasak-Password
# StrictModes Evet
# Maxauthtries 6
# Maxesses 10

PubkeyAuthentication yes

# .SSH/JUTSISTION_KEYS2'nin gelecekte varsayılan olarak göz ardı edilmesini bekleyin.
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# YetkiliPrincipalsFile Yok

# Yetkili Tekscommand Yok
# Yetkili Tekscommanduser Kimse

# Bunun çalışması için/etc/ssh/ssh_kning_hosts içindeki ana anahtarlara da ihtiyacınız olacak
# HostbaseTauthentication Hayır
# Güvenmiyorsanız ~/.ssh/bilinen_hosts için evet olarak değiştirin
# Hostbaseauthentication
# Ignoreuser Binekler Hayır
# Kullanıcının ~/.rhosts ve ~/.Shosts dosyalarını okumayın
# Cahiller evet

# Tünelli açık metin şifrelerini devre dışı bırakmak için burada hayır olarak değiştirin!
PasswordAuthentication no
# İzmitemptypasswords no

# Challenge-yanıt şifrelerini etkinleştirmek için evet olarak değiştirin (
# bazı PAM modülleri ve iş parçacıkları)
KbdInteractiveAuthentication no

# Kerberos Seçenekleri
# Kerberosauthentiction no
# KerberosorlocalPasswd evet
# KerberosticketCleanup evet
# Kerberoskotlu çubuk no

# GSSAPI Seçenekleri
# GSSAPIATHECTICATION NO
# Gssapicleanupcredials evet
# GSSAPISTRICTACECTORCHECK EVET
# Gssapikeyexchange hayır

# Pam kimlik doğrulamasını, hesap işlemeyi etkinleştirmek için bunu 'evet' olarak ayarlayın,
# ve oturum işlemesi. Bu etkinleştirilirse, PAM kimlik doğrulaması
# KBDinteractiveAuthentication'a izin verilebilir ve
# Parola.  Pam yapılandırmanıza bağlı olarak,
# KbdinteractiveAuthentication aracılığıyla PAM kimlik doğrulaması atlayabilir
# "Password Olmadan Permitrootlogin" ayarı.
# Pam hesabının ve oturum kontrollerinin olmadan çalışmasını istiyorsanız
# PAM kimlik doğrulaması, ardından bunu etkinleştir, ancak parola ayarını ayarlayın
# ve 'hayır' için kbdinteractiveauthentiction.
UsePAM yes

# AlactAntforwarding EVET
# Veriltcporwarding EVET
# Gatewayports Hayır
X11Forwarding yes
# X11displayoffet 10
# X11uselocalhost evet
# PERSITTY EVET
PrintMotd no
# Printlastlog evet
# Tcpkeepalive evet
# PermittuEnvolment
# Sıkıştırma gecikti
# Müşterial aralık 0
# ClientaliveNountMax 3
# Kullanılır
# Pidfile /run/sshd.pid
# MaxStartups 10: 30: 100
# Pemittunl Hayır
# ChrootDirectory yok
# Sürüm Ek Yok

# Varsayılan banner yolu yok
Banner /etc/banner

# Müşterinin yerel değişken değişkenlerini geçmesine izin verin
AcceptEnv LANG LC_*

# Alt Sistemlerin Varsayılanını Geçersiz Kesinlikle
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Kullanıcı başına temelde geçersiz kılma örneği
# Kullanıcı anoncvs eşleştirin
# X11 HAYIR HAYIR
# İzin verilen hayır
# İzin
# Forcecommand CVS Sunucusu
PermitRootLogin no
Dosyayı kaydetmek için Ctrl+X ve Y'yi unutmayın. Ardından, başlatma (hepsi kullanıcımızın varsayılan ana dizininde) adlı temel bir komut dosyası yazalım.

nano initialize
Bu satırları değiştirerek dosyaya ekleyinSSH anahtarınızla Cat'i kullanarak buldunuz. (.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
Sizi bu dosyada yönlendirmek için satır satır başlayalım. İlk satır derleyiciye bunun bir Bash komut dosyası olduğunu söyler. Ardından bağımlılıkları yüklüyoruz, SSHD_CONFIG'yi doğru dizine kopyalıyor, SSH'yi yeniden başlatıyoruz, kök için SSH tuşları üretiyor, kullanıcı ekibini ekleyerek (bunun için beğendiğiniz bir ad seçebilirsiniz, adlarıyla ve devre dışı bırakılmış şifreyi kullanabilirsiniz. Şimdi). Ayrıca Sudo Grubuna ekip ekliyoruz, SSH anahtarlarını oluşturuyoruz, anahtarımızı yetkili anahtarlara ve onlarınkine ekliyoruz ve anahtarlarını yazdırıyoruz. Bu yeni kullanıcı, siteye nasıl giriş yapacağımız olacaktır. Yeni bir terminalde devam edin ve sunucuyu tekrar açın.

ssh team@XX.XX.XX.XX
Bir SSH anahtarınız olduğu gibi, bu sefer bir şifreye ihtiyacınız olmamalıdır. Ayrıca siteyi daha güvenli tutmak için girişimi şifre ile devre dışı bıraktık. Şimdi, bu sunucu hakkında hiçbir bilgi olmadan tamamen boş başlıyor. Uzak makineyi indirip çalıştırabilmemiz için projemizi GIT'den klonlayarak başlayalım. SSH'ye bağlı uzak sunucuda, önce SSH anahtarınızı yazdırın:

cat ~/.ssh/id_rsa.pub
Ardından, bu anahtarı git depomuzu ayarlamak için daha önce yaptığımız gibi git ayarlarına yapıştırın. Şimdi projemizi doğrudan sunucuya klonlayabiliriz. İndirmek için GIT sunucusunda olacak şekilde projeyi yerel olarak yedeklediğinizden emin olun.

git clone git://github.com/you/yourproject.git
Mükemmel. Şimdi tüm dosyalar burada. Onları LS ile görebiliriz

ls
Şimdi sunucuyu kurmaya başlayalım. İlk olarak, proje dizininizi proje için kullanacağımız basit, unutulmaz bir ada kopyalayın.

cp -r yourproject whatyoucalledit
“WhatoUnalledit” projenizin yeni adıdır. Ardından, sunucuyu kurmak için temel bir yardımcı program oluşturmamız gerekecek. Bu yardımcı programı kaydedeceğiz ve gelecekte kullanacağız. Bu yardımcı programı oluşturmak için, bir komut dosyasını nasıl düzenlediğimizi tanımlamak için bir kullanıcı ikili oluşturalım. Bash, Düzenle/USR/BIN/Ascript kullanma

sudo nano /usr/bin/ascript
Dosyayı düzenlemek için izinleriniz olması için orada sudo kullandığınızdan emin olun. Dosyaya şu satırları ekleyin:

# / 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
Unutmayın, bu senaryo bir argüman, senaryo adı, 1 $ olarak. İlk olarak, dosyanın var olup olmadığını veya başka şekilde oluşturup oluşturmadığını kontrol eder, betiğin bash olduğunu bildirmek için ilk satırı ekler, izinlerini değiştirir, düzenler ve adını /etc /asripts'e ekler, bu da komut dosyalarının adlarını depolamamıza izin verir yaratıyor. Dosya zaten varsa, izinleri değiştirin ve düzenleyin. Dosyayı kaydedin ve sonra izinlerini değiştireceğiz. Bu komut dosyasını kullandığımız sürece, bunu bir daha yapmak zorunda kalmayacağız.

sudo chmod a+x /usr/bin/ascript
Mükemmel. Şimdi Setup adlı bir komut dosyası oluşturalım. İlk olarak, sizi boğmak değil, ama kurulum betiğimin neye benzediğine bir göz atın. Projenizde bu senaryo nasıl görünmesi gerektiği arasında dolaşacağız, başlamak için senaryomdaki her şeye ihtiyacınız olmayacak.

# / Bin / Bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
# sudo chmod a+x komut dosyaları/usersetup
# ./scripts/usersetup
# SSH-Keyen
# Proje dizin
DIR="/home/team/femmebabe"
USER="team"
# Günlük komutları
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
# Nano Config
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git yapılandırma
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
# Güncelle ve yükle
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
# Clamav antivirüsünü etkinleştirin
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Ana bilgisayar adını ayarla
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Postgres kurulum
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;"
# Yedekleme veritabanını kurulum
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
# Engelli Ipatables
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Bitdefender'ı yükleyin
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
# Kurulum 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
# Dirs Oluştur
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
# Kurulum virtuealenv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# Bağımlılıklar al ve oluşturun
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
# Güvenlik duvarı kurallarını ayarlayın
cd $DIR
# PYPI bağımlılıklarını yükleyin
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 yükleme OpenCV-Python == 4.5.5.64
# PIP Kurulumu OpenCV-Contib-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
# Sertifika kurun
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
# Sertifika çalıştırın
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# Posta Sunucusunu Yeniden Yükle
sudo systemctl restart opendkim postfix dovecot
# Kopyala sertifikası
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privey.pem
# sudo cp /etc/lettesencrypt/live/femmebabe.com/cert.pem cert.pem
# Yama
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"
# Kullanıcı ayarlarını ayarlayın
sudo gpasswd -a www-data users
# İzinler Ayarla
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# Sudo Chown -r Takımı: Kullanıcılar/Var/Run/
# Sudo Chown Kök: Kök/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: kullanıcılar 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
# Yapılandırma kopyala ve izinleri ayarlayın
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
# Veritabanı kurulumu
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"
# Pam yapılandırmasını enjekte edin ve hatalı SSH yapılandırmasını kaldır
# sudo sed -i '' -e '$ d' /tc/pam.d/sshd
# Sudo sed -i '' -and $ d ' /etc /profil
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
# Bin komut dosyalarını kopyalayın ve izinleri ayarlayın
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
# Hizmetleri yeniden yükleyin ve etkinleştirin
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
# Apache modüllerini etkinleştir
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
# Varsayılan siteyi devre dışı bırakın
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# Site için etkinleştir
sudo a2ensite femmebabe-le-ssl
# Daemon'u yeniden yükleyin ve Apache, Postfix ve OpendKim'i yeniden başlatın
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# İzinler Ayarla
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# Takas Yapılandırması
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
# İnit altyazı motoru
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
# Kurulum 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
# Etki alanı yapılandırması için IPv6 ve OpendKIM'i gösterin
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}'
# Kurulum tamamlandı
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."
Bu çok fazla kurulum! Kısacası, bu kod günlükleri günlüğe kaydetti, nano ve git yapılandırır, dosyaları kopyalar, ubuntu apt paketlerini indirir ve yükler, python bağımlılıkları, postfix yapılandırır, postgresql (veritabanı sunucusu) yapılandırır ve veritabanını yükler, UFW'yi (karmaşık olmayan bir ateşli deri) yapılandırır, yapılandırır. İptables'ı devre dışı bırakır, bir antivirüs indirir, dizinler yapar, klonlara bağımlılık yapar, sertifikalar yükler ve Sunucuyu ayarlar, yapılandırmayı yükler, başlatır ve sevgiyi etkinleştirir, takas ayırır, izinleri ayarlar ve IP, IPv6 adresini ve OpendKim tuşunu yazdırır. Oldukça basit, ama çok fazla kod gibi görünüyor. Buna çok ihtiyacımız olmayacak çünkü bağımlılıklarımız yok, kereviz, celererybeat veya daphne kullanmıyoruz, ancak başlamak için bazılarını yine de yükleyeceğiz. Bu kodun birkaç kez beyan edilen bir alan adına sahip olduğuna dikkat edin. Ayrıca bir alan adı satın almamız gerekecek (bu da yıllık küçük bir ücrettir). Bir alan adı satın almak için Squarespace'i tavsiye ederim, düzenleriSezgisel ve kullanımı kolay. Seçtiğiniz herhangi bir etki alanını satın alabilirsiniz, ancak bu örnekte femmebabe.com alanını kullanıyorum. Bir etki alanı satın aldıktan sonra, Squarespace DNS yapılandırma paneline gidin ve etki alanınızı IP adresi ile sunucuya işaret eden bir kayıt ekleyin. Şöyle görünmeli: @ A xx.xx.xx.xx Ana bilgisayar olarak @ operatör ile, bu etki alanı ve kök etki alanı altındaki tüm alt alanların tümü sunucuya yönlendirilir. Beyan edilecek daha fazla kayıt var, ancak posta göndermeye hazır olduğumuzda bunlara geçebiliriz. Unutmayın, sunucudan başarılı bir şekilde posta gönderebilmeniz birkaç gün sürebilir. Belirlediğimiz DNS kayıtları yayılması zaman alacak. Her neyse, başlamamız gereken tek kayıt A Record. Şimdi projemize göre aşağıdaki komut dosyasını doldurabilir ve çalıştırabiliriz. Temel bir ilerleme için ihtiyacımız olanı yüklemek için daha küçük bir kurulum komut dosyasıyla başlayalım. Henüz çok fazla bağımlılık veya postgresql kullanmayacağız, sadeceTemel bir HTTP sunucusunu hazırlayın ve bittiğinde onaylama konusunda endişelenin. Bir HTTPS sertifikası almak ve sunucuyu güvenli bir şekilde çalıştırmak için, Rent A Sunucu ile birlikte bir alan adı satın almamız gerekecek. Şimdilik, bu dosyadaki “Team” i kullanıcınızın adıyla “DIR”, projenizin dizini ile değiştirin ve e -postanızı ve etki alanınızı <> etiketlerde sağlayın. Buna ek olarak, bu kodu çalıştırmadan önce, eğer varsa barındırma sağlayıcının desteklediği güvenlik duvarına ayarları değiştirmemiz gerekir. Genellikle bu, barındırma sağlayıcınızın 'ağlar' sekmesinde veya kendi kendine barındırıyorsanız, yönlendiricinizin 'bağlantı noktası yönlendirme' bölümünde. Ayrıca, kendi kendine barındırma kullanıyorsanız, sunucu makinenizin adresi ile yönlendiriciniz aracılığıyla statik bir IP kurmak isteyeceksiniz. Okuma/yazma erişimi için aşağıdaki bağlantı noktalarını açmanız gerekir. 22 (SSH) 25 (posta) 587 (posta) 110 (posta istemcisi) 80 (HTTP) 443

# / Bin / Bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
# Günlük komutları
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
# Nano Config
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git yapılandırma
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
# Güncelle ve yükle
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
# Clamav antivirüsünü etkinleştirin
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Ana bilgisayar adını ayarla
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
# Yedekleme veritabanını kurulum
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
# İptables'ı devre dışı bırak
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Kurulum virtuealenv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
# Sertifika kurun
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
# Sertifika çalıştırın
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# Kullanıcı ayarlarını ayarlayın
sudo gpasswd -a www-data users
# İzinler Ayarla
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# Sudo Chown -r Takımı: Kullanıcılar/Var/Run/
# Sudo Chown Kök: Kök/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 ./
# Hizmetleri yeniden yükleyin ve etkinleştirin
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Apache modüllerini etkinleştir
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
# Daemon'u yeniden yükleyin ve Apache, Postfix ve OpendKim'i yeniden başlatın
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# Etki alanı yapılandırması için IPv6 ve OpendKIM'i gösterin
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
Bu kodu çalıştırmadan önce, satın aldığınız etki alanının sunucuya bağlı olduğundan emin olun. Bunu yapmak için, yerel makinenizde bir terminal açın ve bu komutu alan adınızla çalıştırın:

ping femmebabe.com # Ping'den sonra alan adınızı buraya ekleyin
Her şey yolunda görünüyorsa ve sunucu yanıt gönderiyorsa, komut dosyasını çalıştırmaya ve paketleri yüklemeye ve Apache sunucumuzu başlatmaya, etkinleştirmeye ve onaylamaya hazırız. Postfix'i yapılandırmak için gereken tüm kurulum değil, bu kuruluma daha sonra bakacağız. Şimdilik, bu kurulum kodunu çalıştırın ve sunucunuzu yüklemek ve onaylamak birkaç dakika sürmelidir. Bir kez daha, satın aldığınız ada göre komut dosyasındaki ad, e -posta ve alan adını değiştirdiğinizden emin olun. Sunucunun sağlandığına göre, herhangi bir web tarayıcısında URL'ye gidebilir ve sunucunun HTTPS çalıştırdığından emin olmak için kontrol edebilirsiniz. Değilse, DNS kayıtlarının yakalanmasını ve ardından sertifika sertifikasını yeniden denemek için aşağıdaki komutu çalıştırmasını beklemeyi deneyin:

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
Her şeyi doğru yapılandırdığınız sürece, kodunuzun çalıştığını ve canlı bir web sayfası görüntülediğini bilmek için Apache'nin varsayılan sayfasına erişebilmeniz gerekir. Ardından, varsayılan hata ayıklama modumuzu üretime dönüştürmek için settings.py'yi düzenleyelim. Ayrıca Dahili IP'lerin yanı sıra ayarlarda da etki alanını yapılandıracağız.

nano yourproject/settings.py
Ayarlarda, bu satırları değiştirin/ekleyin.

DEBUG = False

# Site Yapılandırması
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',
]
Şimdi Apache2'yi yapılandırmamız gerekecek. Bu satırla dağıtacağımız yapılandırma dosyasını düzenleyelim:

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
Bu yapılandırma dosyasında etki alanı adımız ve kullanıcı ve projenin adı olmalıdır. Femmebabe.com alan adını, kullanıcı adı ekibini ve femmebabe proje adı kullanıyorum.

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>
Sunucunuzu yapılandırırken bu örnek koddaki projenin, dizinlerin ve etki alanının adını değiştirdiğinizden emin olun. Şimdi, varsayılan siteyi devre dışı bırakmamız gerekecek. Bu BASH kullanılarak yapılabilir.

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
Ardından, Varsayılan Siteyi etkinleştirebilir ve BASH'ı kullanarak Apache2'yi yeniden yükleyebiliriz. Femmebabe'yi/etc/apache2/sites-üileable/düzenlerken bildirdiğiniz dosyanın adıyla değiştirmeyi unutmayın.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Navbar'daki alan adınıza geri dönün. Web tarayıcınızda yapılandırdığınız siteyi görmelisiniz. Tebrikler! Eğer görmüyorsanız, bazı değişiklikler yapmanız gerekebilir. Projenizdeki ayarları, Apache yapılandırmasını dikkatlice inceleyin ve hatalarınız olmadığından emin olun ve projeyi hatalar için kontrol etmek için aşağıdaki komutları çalıştırın.

cd projectname
source venv/bin/activate
python manage.py check
Python projenizde hatalarınız varsa, onları bulundukları yere kadar takip edin ve düzeltin. Tüm hatalarınızı nerede olduklarına bağlı olarak göremeyebilirsiniz, bu nedenle basitçe “Populate yeniden giriş yapmaz” diyen bir hatanız varsa, sanal ortamda aşağıdaki dosyayı düzenleyin, kayıt defteri.py, açıklamak için hata.

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Bu çalışma zamanı hatasının yükseltildiği 83. satıra kaydırın (RuntimeError (“Populate () yeniden giriş yapmaz”)) ve bu satırdan önce bir yorum ekleyin, ardından aynı girinti ekleyerek self.app_configs = {}. Bu şuna benziyor:

            if self.loading:
                # AppConfig.Ready () çalıştırmaktan kaçınmak için yeniden giriş çağrılarını önleyin
                # yöntemler iki kez.
# RuntimeRor ("Populate () yeniden giriş yapmıyor") yükseltme
                self.app_configs = {}
            self.loading = True
Daha sonra projeyi tekrar kontrol edebilir ve hatayı ortaya çıkarabilirsiniz.

python manage.py check
Sonra hatayı görebilir ve düzeltebilirsiniz. Düzelttiğiniz ve kod hatasız derlendiğinde, dosyayı şöyle görünecek şekilde değiştirdiğinizden emin olun:

            if self.loading:
                # AppConfig.Ready () çalıştırmaktan kaçınmak için yeniden giriş çağrılarını önleyin
                # yöntemler iki kez.
                raise RuntimeError("populate() isn't reentrant")
# self.app_configs = {}
            self.loading = True
Sunucunun çevrimiçi olması koşuluyla, daha fazla değişiklik yaptığımızda, sunucuyu yeniden yüklemek için aşağıdaki komutu kullanmamız gerekir:

sudo systemctl reload apache2
Mükemmel! Peki ya posta göndermeye ne dersiniz? E -posta göndermeye başlamak için önce etki alanı yapılandırmasını güncellememiz gerekecektir. Bu, Squarespace'deki DNS panelinizde veya seçtiğiniz alan adı kayıt şirketinde olmalıdır. Ayrıca yapılandırma yüklemeli ve eklememiz ve birkaç komut çalıştırmamız gerekecek. İlk olarak, sunucunun IPv6 adresini alalım. Daha sonra DN'lerinizi açacağız ve kayıtları ekleyeceğiz. Sunucunun IPv6 adresini almak için şu komutu kullanın:

ip -6 addr
Şimdi, aşağıdaki kayıtları DNS ayarlarına ekleyebiliriz. Kayıtlarım böyle görünüyor. Ancak, kayıtlarınız için IP adresini IP'nizle değiştirmelisiniz (75.147.182.214 değil, bu benim). Ayrıca alan adınızı femmebabe.com'un yanı sıra önceki komutla bulunan IPv6 adresinizi de ekleyin (Mayın, Fe80 :: 725a: FFF: FE49: 3E02) kullanamazsınız). Şimdilik Domainkey için endişelenmeyin, bu, Postfix, posta sunucusu, OpendKim ile ayarladığımızda ve tuşu yazdırdığımızda oluşturulur. Bunu en son yapılandıracağız. @ 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 ~ Tüm varsayılan._bimi TXT N/A v = bimi1; l = https: //femmebabe.com/media/static/femmebabe.svg _dmarc TXT N/A V = DMARC1; P = yok sendonly._domainkey TXT N/AŞimdi, Postfix için bazı kalıcı yapılandırma eklememiz gerekecek. Tek yapmamız gereken alan adını Femmebabe.com, kullandığınız alan adıyla değiştirdiğimizden emin olmaktır. Tüm yapılandırma dosyalarına tek tek bakalım ve işletim sistemine yüklemek için bunları projemizde yapılandıran bir dizine yükleyelim.

nano config/etc_postfix_main.cf
Bu metni dosyaya ekle

# Yorumlanan, daha eksiksiz bir sürüm için bkz. /Usr/share/postfix/main.cf.dist


# Debian Spesifik: Bir dosya adı belirlemek ilkine neden olur
# Bu dosyanın satırı adı olarak kullanılacak.  Debian Varsayılan
# IS /etc /mailname.
# Myorigin = /etc /mailname

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

# Ekleme.
append_dot_mydomain = no

# "Gecikmeli Posta" uyarıları oluşturmak için bir sonraki satırın
# DELAK_WARNING_TIME = 4H

readme_directory = no

# Bkz.
# Taze kurulumlar.
compatibility_level = 3.6



# TLS parametreleri
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

# Milter yapılandırması
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
Sonraki Yapılandırma!

nano config/etc_postfix_master.cf
Bu satırları ekleyin:

# 
# Postfix ana işlem yapılandırma dosyası.  Biçim hakkında ayrıntılar için
# Dosyadan Master (5) manuel sayfasına bakın (komut: "Man 5 Master" veya
# On-line: http://www.postfix.org/master.5.html).
# 
# Bu dosyayı düzenledikten sonra "Postfix Reload" i yürütmeyi unutmayın.
# 
# ============================================== ======================
# Servis Türü Özel İncil Chroot Wakeup Maxproc Command + Args
#                (yes)   (yes)   (no)    (never) (100)
# ============================================== ======================
smtp      inet  n       -       y       -       -       smtpd
# SMTP INET N - Y - 1 PORTREEN
# Smtpd geçişi - - y - - smtpd
# Dnsblog unix - - y - 0 dnsblog
# Tlsproxy unix - - y - 0 tlsproxy
# Birini seçin: Yalnızca Loopback istemcileri veya herhangi bir istemci için gönderimi etkinleştirin.
# 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/gönderim
# -O smtpd_tls_security_level = şifreleme
# -O SMTPD_SASL_AUTH_ENABLE = EVET
# -O smtpd_tls_auth_only = evet
# -O smtpd_reject_unlisted_recipient = hayır
# -O smtpd_client_restrictions = $ mua_client_restrtions
# -O smtpd_helo_restrictions = $ mua_helo_restrictions
# -O smtpd_sender_restrictions = $ mua_sender_restrictions
# -O smtpd_recipient_trival =
# -O smtpd_relay_restrictions = permit_sasl_authenticated, reddet
# -O milter_macro_daemon_name = kökenli
# Birini seçin: Yalnızca geri döngü istemcileri veya herhangi bir istemci için SMTPS'yi etkinleştirin.
# 127.0.0.1:smtps inet n - y - - smtpd
# smtps inet n - y - - smtpd
# -O syslog_name = postfix/smtps
# -O smtpd_tls_wrappermode = evet
# -O SMTPD_SASL_AUTH_ENABLE = EVET
# -O smtpd_reject_unlisted_recipient = hayır
# -O smtpd_client_restrictions = $ mua_client_restrtions
# -O smtpd_helo_restrictions = $ mua_helo_restrictions
# -O smtpd_sender_restrictions = $ mua_sender_restrictions
# -O smtpd_recipient_trival =
# -O smtpd_relay_restrictions = permit_sasl_authenticated, reddet
# -O milter_macro_daemon_name = kökenli
# 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 OQMG
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
# 
# ============================================== ================
# PostFix olmayan yazılım arayüzleri. Kılavuzu incelediğinizden emin olun
# Hangi seçenekleri istediğini öğrenmek için PostFix yazılımının sayfaları.
# 
# Aşağıdaki hizmetlerin birçoğu Postfix borusu (8) teslimatını kullanıyor
# ajan.  $ {Alıcı} hakkında bilgi için boru (8) kadın sayfasına bakın
# ve diğer mesaj zarf seçenekleri.
# ============================================== ================
# 
# Maildrop. Ayrıntılar için postfix maildrop_readme dosyasına bakın.
# Ayrıca main.cf'de belirtin: maildrop_destination_recipient_limit = 1
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# ============================================== ================
# 
# Son Cyrus sürümleri mevcut "LMTP" master.cf girişini kullanabilir.
# 
# Cyrus.conf'da belirtin:
# Lmtp cmd = "lmtpd -a" dinleme = "localhost: lmtp" proto = tcp4
# 
# Main.cf'de aşağıdakilerden bir veya daha fazlasını belirtin:
# mailbox_transport = lmtp: inet: localhost
# virtual_transport = lmtp: inet: localhost
# 
# ============================================== ================
# 
# Cyrus 2.1.5 (Amos Gouaux)
# Ayrıca Main.cf'de belirtin: cyrus_destination_recipient_limit = 1
# 
# Cyrus unix - n n - - boru
# Flags = DRX USER = Cyrus arg =/cyrus/bin/teslim -e -r $ {gönderen} -m $ {extension} $ {user}
# 
# ============================================== ================
# Cyrus üzerinden teslimat örneği.
# 
# Eski -Corus unix - n - - boru
# Flags = R USER = Cyrus argv =/cyrus/bin/teslim -e -m $ {extension} $ {user}
# 
# ============================================== ================
# 
# Yapılandırma detayları için Postfix UUCP_README dosyasına bakın.
# 
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# 
# Diğer harici dağıtım yöntemleri.
# 
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}
Ve OpendKim yapılandırması. OpendKim, e -posta sunucularını daha güvenli hale getirmek için etki alanı anahtarlarıyla tanımlar. Onsuz, posta imzalanmaz ve bir gelen kutusuna girmeyebilir.

nano config/etc_default_opendkim
Bu satırları ekleyin:

# Not: Bu, eski bir yapılandırma dosyasıdır. Opendkim tarafından kullanılmıyor
# Systemd hizmeti. Lütfen ilgili yapılandırma parametrelerini kullanın
# bunun yerine /etc/opendkim.conf.
# 
# Daha önce, burada varsayılan ayarları düzenler ve ardından yürütür
# /lib/opendkim/opendkim.service.Generasyon Systemd geçersiz kılma dosyalarını oluşturmak için
# /etc/systemd/system/opendkim.service.d/override.conf ve
# /etc/tmpfiles.d/opendkim.conf. Bu hala mümkün olsa da, şimdi
# Ayarları doğrudan /etc/opendkim.conf adresinde ayarlamanız önerilir.
# 
# Daemon_opts = ""
# /Var/makara/postfix/run/opendKim olarak değiştirin,
# Postfix bir chroot:
# RunDir =/var/makar/postfix/run/opendKim
RUNDIR=/run/opendkim
# 
# Alternatif bir soket belirtmek için
# Bunu ayarlamanın opendkim.conf'daki herhangi bir soket değerini geçersiz kılacağını unutmayın.
# varsayılan:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# 54321 bağlantı noktasındaki tüm arayüzleri dinleyin:
# Soket = inet: 54321
# 12345 numaralı bağlantı noktasında döngü dinleyin:
# Soket = inet: 12345@localhost
# Dinle 192.0.2.1 bağlantı noktası 12345:
# Soket = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

nano config/etc_dovecot_conf.d_10-master.conf
Bu satırları ekleyin:

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

# Hizmet işlemleri için varsayılan VSZ (sanal bellek boyutu) sınırı. Bu esas olarak
# Yemeden önce hafızayı sızdıran süreçleri yakalamayı ve öldürmeyi amaçladı
# her şey.
# varsayılan_vsz_limit = 256m

# Oturum açıcı kullanıcı, giriş işlemleri tarafından dahili olarak kullanılır. Bu en güvenilmeyen şey
# Dovecot sisteminde kullanıcı. Hiçbir şeye erişememelidir.
# default_login_user = dovenull

# Dahili kullanıcı, ayrıcalıklı işlemler tarafından kullanılır. Ayrı olmalı
# Giriş kullanıcısı, böylece oturum açma işlemleri diğer işlemleri bozamaz.
# default_internal_user = Dovecot

service imap-login {
  inet_listener imap {
    # Port = 143
  }
  inet_listener imaps {
    # Port = 993
    # ssl = yes
  }

  # Yeni bir sürece başlamadan önce işlenecek bağlantı sayısı. Tipik olarak
  # Tek yararlı değerler 0 (sınırsız) veya 1. 1 daha güvenlidir, ancak 0
  # daha hızlı. <doc/wiki/loginprocess.txt>
  # Service_count = 1

  # Her zaman daha fazla bağlantı beklemeye devam edecek süreç sayısı.
  # Process_min_avail = 0

  # Service_count = 0 ayarlarsanız, muhtemelen bunu büyütmeniz gerekir.
  # vsz_limit = $ default_vsz_limit
}

service pop3-login {
  inet_listener pop3 {
    # Port = 110
  }
  inet_listener pop3s {
    # Port = 995
    # ssl = evet
  }
}

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

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

  # Yalnızca yukarıdaki UNIX soketini kullanamıyorsanız, Inet dinleyici oluşturun
  # INET_LISTER LMTP {
    # LMTP'yi tüm internet için görünür kılmaktan kaçının
    # adres =
    # bağlantı noktası =
  # }
}

service imap {
  # Belleğin çoğu mmap () ing dosyalarına gider. Bunu artırmanız gerekebilir
  # Büyük posta kutularınız varsa sınırlayın.
  # vsz_limit = $ default_vsz_limit

  # Maks. IMAP işlemlerinin sayısı (bağlantılar)
  # Process_limit = 1024
}

service pop3 {
  # Maks. POP3 işlemlerinin sayısı (bağlantılar)
  # Process_limit = 1024
}

service submission {
  # Maks. SMTP Gönderme Süreçlerinin Sayısı (Bağlantılar)
  # Process_limit = 1024
}

service auth {
  # Auth_socket_path varsayılan olarak bu UserDB soketine işaret eder. Tipik olarak
  # Dovecot-Lda, Doveadm, muhtemelen IMAP işlemi vb. Tarafından kullanılır. Sahip olan kullanıcılar
  # Bu sokete tam izinler, tüm kullanıcı adlarının bir listesini alabilir ve
  # Herkesin UserDB aramalarının sonuçlarını alın.
  # 
  # Varsayılan 0666 modu, herkesin sokete bağlanmasına izin verir, ancak
  # Userdb aramaları, yalnızca userdb bir "uid" alanı döndürürse başarılı olur
  # Arayan işleminin UID'siyle eşleşir. Ayrıca arayanın UID veya GID'si eşleşirse
  # Soket UID veya GID Arama başarılı. Başka bir şey başarısızlığa neden olur.
  # 
  # Arayana tüm kullanıcıları aramaya tam izin vermek için modu ayarlayın
  # 0666'dan başka bir şey ve Dovecot, çekirdeğin uygulanmasını sağlar.
  # izinler (örneğin 0777 herkese tam izin verir).
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # Yetkilendirme işçisi süreci varsayılan olarak kök olarak çalıştırılır, böylece erişebilir
  # /etc/shadow. Bu gerekli değilse, kullanıcı
  # $ default_interal_user.
  # Kullanıcı = kök
}

service dict {
  # Dict proxy kullanılırsa, posta işlemlerinin soketine erişimi olmalıdır.
  # Örneğin: Mod = 0660, Grup = Vmail ve Global Mail_access_groups = Vmail
  unix_listener dict {
    # Mod = 0600
    # Kullanıcı =
    # grup =
  }
}
Bir kez daha, bu dosyalardaki alan adını femmebabe.com'da seçtiğiniz alan adıyla değiştirdiğinizden emin olun. Bir sonraki dosyayı düzenleyin, Dovecot'un Config,

nano config/etc_dovecot_dovecot
Ve bu çizgileri ekle

## Dovecot yapılandırma dosyası

# Eğer acele ediyorsanız, http://wiki2.dovecot.org/quickconfiguration bkz.

# "Doveconf -n" komutu, değiştirilen ayarların temiz bir çıkışını verir. Kullanın
# Dovecot posta listesine gönderirken dosyaları kopyalamak ve yapıştırmak yerine.

# '# 'Karakter ve ondan sonraki her şey yorum olarak değerlendirilir. Ekstra Mekanlar
# ve sekmeler göz ardı edilir. Bunlardan birini açıkça kullanmak istiyorsanız,
# value inside quotes, eg.: key = "# Char ve son boşluk "

# Çoğu (hepsi değil) ayarlar farklı protokoller tarafından geçersiz kılınabilir ve/veya
# Örneğin, ayarları bölümlerin içine yerleştirerek kaynak/hedef IPS:
# Protokol IMAP {}, Yerel 127.0.0.1 {}, uzaktan 10.0.0.0/8 {}

# Her ayar için varsayılan değerler gösterilir, çözülmesi gerekmez
# onlar. Bunlar bunun istisnalarıdır: Bölüm yok (örneğin ad alanı {})
# Veya eklenti ayarları varsayılan olarak eklenir, bunlar yalnızca örnek olarak listelenir.
# Yollar ayrıca sadece gerçek varsayılanların yapılandırmaya dayalı örnekleridir
# seçenekler. Burada listelenen yollar yapılandırma içindir ---prefix =/usr
# ---sysconfdir =/etc --localstatedir =/var

# Yüklü protokolleri etkinleştirin
!include_try /usr/share/dovecot/protocols.d/*.protocol

# Bağlantı için nerede dinleneceğiniz IP'lerin veya ana bilgisayarların virgül ayrılmış bir listesi.
# "*" Tüm IPv4 arabirimlerini dinler, "::" Tüm IPv6 arabirimlerini dinler.
# Varış dışı bağlantı noktaları veya daha karmaşık bir şey belirtmek istiyorsanız,
# Conf.d/master.conf'u düzenleyin.
# Dinle = *, ::

# Temel dizin çalışma zamanı verilerini nerede saklayabiliriz.
# base_dir =/var/run/doecot/

# Bu örneğin adı. Çoklu kurulum Doveadm ve diğer komutlarda
# hangi örneğin kullanıldığını seçmek için -i <cruct_name> kullanabilir (alternatif
# -c <config_path>). Örnek adı Dovecot işlemlerine de eklenir
# PS çıkışında.
# instance_name = Dovecot

# Müşteriler için selamlama mesajı.
# login_greeting = Dovecot hazır.

# Güvenilir ağ aralıklarının uzay ayrılmış listesi. Bunlardan bağlantılar
# IP'lerin IP adreslerini ve bağlantı noktalarını geçersiz kılmalarına izin verilir (günlük kaydı ve
# kimlik doğrulama kontrolleri için). disable_plaintext_auth da göz ardı edilir
# Bu ağlar. Genellikle IMAP proxy sunucularınızı buradan belirlersiniz.
# login_trusted_networks =

# Alandan Ayrılmış Oturum Açma Erişim Kontrolü Soketleri (örn. TCPWRAP)
# login_access_sockets =

# Proxy_Maybe ile = EVET Bu IP'lerden herhangi biriyle eşleşiyorsa, yapmayın
# Proxy. Bu normalde gerekli değildir, ancak hedef varsa yararlı olabilir
# IP, örn. bir yük dengeleyicisinin IP'si.
# auth_proxy_felf =

# Daha ayrıntılı işlem başlıklarını (PS'de) gösterin. Şu anda kullanıcı adını gösteriyor ve
# IP adresi. IMAP işlemlerini kimin kullandığını görmek için kullanışlı
# (Örneğin paylaşılan posta kutuları veya birden çok hesap için aynı UID kullanılıyorsa).
# VerBose_proctitle = hayır

# Dovecot Master işlemi kapandığında tüm süreçler öldürülürse.
# Bunu "hayır" olarak ayarlamak, Dovecot'un onsuz yükseltilebileceği anlamına gelir
# Mevcut müşteri bağlantılarını kapmaya zorlamak (bu da olabilir
# Yükseltme, örn. bir güvenlik düzeltmesi nedeniyle).
# shutdown_clients = evet

# Sıfır değilse, bu birçok bağlantı aracılığıyla posta komutlarını Doveadm sunucusuna çalıştırın,
# bunları doğrudan aynı süreçte çalıştırmak yerine.
# Doveadm_worker_count = 0
# Unix Socket veya Ana Bilgisayar: Doveadm Server'a bağlanmak için kullanılan bağlantı noktası
# Doveadm_socket_path = doveadm sunucusu

# Dovecot'ta korunan ortam değişkenlerinin uzaydan ayrılmış listesi
# başlangıç ​​ve tüm çocuk süreçlerine geçti. Ayrıca verebilirsin
# Key = Her zaman belirli ayarları ayarlamak için değer çiftleri.
# Import_environment = TZ

## 
## Sözlük Sunucu Ayarları
## 

# Sözlük, anahtar = değer listelerini depolamak için kullanılabilir. Bu birkaç kişi tarafından kullanılır
# Eklentiler. Sözlüğe doğrudan veya bir
# sözlük sunucusu. Aşağıdaki Dict Block Haritalar Sözlük Adları URIS
# Sunucu kullanıldığında. Bunlar daha sonra URI'ler kullanılarak formatta referans verilebilir
# "Proxy :: <nam>".

dict {
  # kota = mysql: /andc/dovecot/dovecot-dic-sql.conf.ext
}

# Gerçek yapılandırmanın çoğu aşağıda dahil edilir. Dosya adları
# İlk olarak ASCII değerine göre sıralanır ve bu sırayla ayrıştırılır. 00-PREFIXES
# Dosya adlarında, siparişi anlamayı kolaylaştırmayı amaçlamaktadır.
!include conf.d/*.conf

# Bir yapılandırma dosyası, hata vermeden de dahil edilmeye çalışabilir.
# bulunamadı:
!include_try local.conf

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

protocols = imap pop3

# Dovecot'un tüm giriş bağlantılarını dinlemesine izin verir (IPv4 / IPv6)

listen = *, ::
Dovecot kullanıcısı için bir şifre ekleyin:

nano config/etc_dovecot_passwd
Dosyanın ilk kısmı, kolondan önceki kullanıcı adıdır. Son bölümü olan “YourPsword”, posta sunucunuza vermek istediğiniz şifreyi belirtir.

team:{plain}yourpassword
Sonra, OpendKim Config

nano config/etc_opendkim.conf
Ve şu satırları ekleyin:

# Bu, imzalama ve doğrulama için temel bir yapılandırmadır. Kolayca olabilir
# temel bir kuruluma uyacak şekilde uyarlanmıştır. Bkz. OpendKim.conf (5) ve
# /usr/share/doc/opendkim/examples/opendkim.conf.sample için
# Mevcut yapılandırma parametrelerinin dokümantasyonu.

Syslog			yes
SyslogSuccess		yes
# Yok

# Ortak İmzalama ve Doğrulama Parametreleri. Debian'da "from" başlık
# Söz konusu, çünkü genellikle itibar sistemleri tarafından kullanılan kimlik anahtarıdır
# Ve böylece biraz güvenliğe duyarlı.
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# Etki alanı, seçici ve anahtar imzalama (gerekli). Örneğin, imzalama yapın
# "2020" seçicisi ile "örnek.com" alan adı için (2020._domainkey.example.com),
# /etc/dkiimkeys/example.private içinde depolanan özel anahtarı kullanarak. Daha ayrıntılı
# Kurulum seçenekleri /usr/share/doc/opendkim/readme.opendkim adresinde bulunabilir.
# Domain Örnek.com
# Seçici 2020
# Keyfile /etc/dkiimkeys/example.prive

# Debian'da Opendkim kullanıcı "opendkim" olarak çalışır. Ne zaman
# Sokete ayrıcalıksız olarak erişen MTA'larla yerel bir soket kullanmak
# kullanıcı (örneğin, postfix). Grup için kullanıcı "postfix" eklemeniz gerekebilir
# "Opendkim" bu durumda.
UserID			opendkim
UMask			007

# MTA bağlantısı için soket (gerekli). MTA bir chroot hapishanesinin içindeyse,
# Soketin erişilebilir olması sağlanmalıdır. Debian'da Postfix
# /var/makara/postfix'te bir chroot, bu nedenle bir UNIX soketinin olması gerekir
# Aşağıdaki son satırda gösterildiği gibi yapılandırılmıştır.
# Socket Yerel: /run/opendkim/opendkim.sock
# Soket inet: 8891@localhost
# Soket Inet: 8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Doğrulamak yerine imzalayacak olan ana bilgisayarlar, varsayılan 127.0.0.1'dir. Gör
# Daha fazla bilgi için OpendKim (8) Operasyon Bölümü.
# Dahili Dövme 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# Güven çapası DNSSEC'i etkinleştirir. Debian'da, Trust Anchor dosyası sağlanır
# DNS-Root-Data paketi ile.
TrustAnchorFile		/usr/share/dns/root.key
# Nameerers 127.0.0.1

# Harita alanlarını adreslerden mesajları imzalamak için kullanılan anahtarlara kadar harita
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Postası imzalanması gereken bir dizi dahili ana bilgisayar
InternalHosts       /etc/opendkim/trusted.hosts

nano config/etc_default_opendkim
Ve bu çizgileri ekle

# Not: Bu, eski bir yapılandırma dosyasıdır. Opendkim tarafından kullanılmıyor
# Systemd hizmeti. Lütfen ilgili yapılandırma parametrelerini kullanın
# bunun yerine /etc/opendkim.conf.
# 
# Daha önce, burada varsayılan ayarları düzenler ve ardından yürütür
# /lib/opendkim/opendkim.service.Generasyon Systemd geçersiz kılma dosyalarını oluşturmak için
# /etc/systemd/system/opendkim.service.d/override.conf ve
# /etc/tmpfiles.d/opendkim.conf. Bu hala mümkün olsa da, şimdi
# Ayarları doğrudan /etc/opendkim.conf adresinde ayarlamanız önerilir.
# 
# Daemon_opts = ""
# /Var/makara/postfix/run/opendKim olarak değiştirin,
# Postfix bir chroot:
# RunDir =/was/scool/postfix/run/opendKim
RUNDIR=/run/opendkim
# 
# Alternatif bir soket belirtmek için
# Bunu ayarlamanın opendkim.conf'daki herhangi bir soket değerini geçersiz kılacağını unutmayın.
# varsayılan:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# 54321 bağlantı noktasındaki tüm arayüzleri dinleyin:
# Soket = inet: 54321
# 12345 numaralı bağlantı noktasında döngü dinleyin:
# Soket = inet: 12345@localhost
# Dinle 192.0.2.1 bağlantı noktası 12345:
# Soket = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Postfix sunucumuzu kurmaya hazır olduğumuzda, uygun alan adı gömülü olan aşağıdaki kodu çalıştıracağız. Bir senaryo oluşturarak başlayın

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
Şimdi, Nano'da metin düzenleyicisi, bu dosyayı femmebabe.com yerine alan adınızı içerecek şekilde düzenleyin.

# !/Bin/Bash
# Kurulum 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}'
Şimdi, Postfix, OpendKim ve Dovecot'u yapılandırmak için tamamlanmış komut dosyasını çalıştırın.

./scripts/postfixsetup
Bu komut dosyası çalıştırıldıktan sonra, yazdırdığı son satırı kopyalayın ve sendonly._domainkey değeri olarak DNS yapılandırmanıza yapıştırın. Bu, güvenli posta gönderirken etki alanınızı tanımlamak için kullanılan OpendKim anahtarıdır. Mükemmel! Birkaç gün içinde, her şeyin doğru yapılandırılması koşuluyla sunucudan posta gönderebilmeniz gerekir. DNS'yi posta sunucunuz için yapılandırdıysanız, kayıtların güncellenmesi 72 saatten az sürmelidir. Genellikle çok daha hızlıdır. Sunucunuzun bu komutu kullanarak çalışıp çalışmadığını, e -postanızı sağlayarak kontrol edebilirsiniz:

echo “test” | mail -s “Test Email” youremail@gmail.com
Her şey doğru çalışıyor gibi görünüyorsa, sunucunuzla e -posta gönderebilmelisiniz. Çalışmıyorsa, hatanın ne olabileceğini görmek için günlüklere bakmayı deneyin.

tail –lines 150 /var/log/mail.log
Bu, sunucu tarafından gönderilen posta hakkında ve düzgün çalışıp çalışmadığı hakkında ayrıntılı bilgi sunacaktır. Gelen kutunuzdaki e -postayı da görebilmelisiniz, eğer orada değilse, spam klasörünüzü kontrol edin. Ayrıca, e -posta sunucunuzun Django uygulamanızla projeyle konuşabilmesi için ayarlarınızı settings.py'de yapılandırmanız gerekecektir. Ayarlarınızda bu satırları ekleyin veya değiştirin

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)
Parolayı almak için bir yapılandırma dosyası kullandığımıza dikkat edin. Bu dosyayı, dosyanın en başında böyle ayarlara yükleyelim.:

import os
import json

# Yapılandırmayı açın ve yükleyin
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Bu dosyayı oluşturalım ve posta parolasının yanı sıra gizli bir anahtar ekleyelim. Gizli bir anahtar oluşturmak için, sonunda istediğiniz uzunlukta bu komutu kullanın:

openssl rand -base64 64
Şimdi, OpenSSL'nin oluşturulduğu metni kopyalayın ve /etc/config.json'u düzenleyin

sudo nano /etc/config.json
OpenSSL'nin gizli anahtar olarak oluşturulduğu anahtarla dosyanıza aşağıdaki satırları ekleyin.

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
JSON Formatı basit ve kullanımı kolaydır, projemizde kullanmak istediğimiz diğer anahtarları da bu şekilde bildirebilir ve bunları proje dizinimizden ayrı tutabiliriz, böylece diğer kullanıcılar onlara yazamazlar ve böylece okunamazlar Sadece proje dizinimizden. Bu, burada birkaç taneden daha fazlasını kullanacağımız API Keys için önerilen uygulama. Ayrıca, her şeyin kaydedildiğinden emin olmak için projenizi yedeklemek isteyeceksiniz ve artık bir sunucu kiralamak istemeseniz bile işinizi daha sonra kurtarabileceksiniz.

sudo backup
Şimdi, komut satırından bir tane göndermenin sağladığı Web sunucusundan bir HTML e -postası göndermeyi deneyin. Kabuktaki kullanıcı örneğinizi sorgulayın ve Django aracılığıyla o kullanıcıya bir HTML e -postası gönderin. Koddaki adımı Charlotte, kullanıcı adınıza değiştirin.

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()
İlk komut çalışmıyorsa, kullandığınızdan emin olun

source venv/bin/activate
Her şey doğru ayarlanmış olması koşuluyla, şimdi web uygulamanız tarafından gönderilen posta kutunuza hoş geldiniz e -postası alacaksınız. Aferin! Uzun bir yol kat ettin. Eklemek istedim, eğer böyle bir proje üzerinde çalışırken herhangi bir hata ile hiç mücadele ediyorsanız, cevap aramak ve yardım istemekten çekinmeyin. Google, diğer arama motorlarının yanı sıra, programlama yardımı aramak için harika kaynaklardır. Aldığınız hatayı arayın ve diğer insanların sorunu nasıl çözdüğünü görebilirsiniz. Ayrıca, benimle, eğitimcileriniz (öğretmenler, profesörler, öğretmenler), internette programlama yardımı için mevcut olan akranlarınızla iletişime geçebilir veya yaşadığınız sorunlara çözüm bulmak için bu kitaba tekrar veya diğer kaynaklara başvurabilirsiniz. Bunun kolay olmadığını anlıyorum, ancak bu kadar okuduğunuzda ve herhangi bir kod yazmasanız bile, bir web uygulaması oluşturma hakkında çok şey öğreniyorsunuz. Kendini arkada patlat, harika bir şey yapıyorsuniş. Bu üçüncü baskı web geliştirme kılavuzunu okumak için zaman ayırdığınız için teşekkür ederiz. Gelecek baskılarda, belgenin başlangıcında tartışılan önemli örneklerden daha fazlasını ekleyeceğim ve yazılım ve donanım geliştirme dünyasına çok daha derinlemesine dalacağız. Gelecekler için bizi izlemeye devam edin ve size inanılmaz bir yazılım oluşturmayı öğretmeyi dört gözle bekliyorum. Sonraki görüşürüz






Kapalı
Sayfa 1
Zıplamak
Makalenin tamamını görün
Okumaya devam et

Satın almak | Kripto ile satın al



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


(Resmi indirmek için tıklayın veya dokunun)
Profesyonel eğlence, fotoğraflar, videolar, ses, canlı yayın ve gündelik oyunun yanı sıra kimlik taraması, web geliştirme ve taşıyıcılık hizmetleri.

Bu adresi kullanarak bana Bitcoin ile ilgili bir ipucu bırakın: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

Hizmet Şartları