Praktisches webbasiertes Deep Learning und Sicherheit anhand von Beispielen

DaisyProfilfoto

Von Daisy

Praktisches webbasiertes tiefes Lernen und Sicherheit durch Beispiel Dritte Ausgabe Charlotte Harper 3. Juli 2024 Vorwort: Sicherheitsüberlegungen im Aufbau von Software für das Web sind ein wichtiger Bestandteil des Plans und der Ausführung eines Webentwicklers, während ein Prototyp für praktische Zwecke zuverlässig, stabil und nützlich ist. Das DOM (Dokumentobjektmarkup) mit der Implementierung von HTML, JavaScript und CSS sowie Backend -Software, die Python, C/C ++, Java und Bash implementiert, geben Webentwicklern die Freiheit und die Möglichkeit, eine Vielzahl von Projekten zu erstellen, die ausdrücken, die ausdrücken Kreativität, Benutzerfreundlichkeit und Funktionalität. Normalerweise auf einem Touchscreen -Smartphone -Gerät. Die meisten Menschen würden nicht einmal wissen, wo sie anfangen sollen, wenn sie eine Website von Grund auf neu erstellen möchten.Sie würden tendenziell auf der Website einer anderen Person beginnen und etwas Begrenztes in Bezug Besonders das Geld verschwenden, um teure Abonnements für Software zu bezahlen, die nur wenige Menschen aufgrund seiner Einschränkungen in Bezug auf Benutzerfreundlichkeit und Flexibilität verwenden wollten. Wenn Sie ein paar Minuten Zeit haben, um dieses Buch durchzulesen und zu lernen, was ich Ihnen beibringen möchte, oder sogar mit mir persönlich über Ihre Ziele sprechen und eine Anleitung in die richtige Richtung erhalten und motiviert sind, zu lernen, Ihre eigene Software zu codieren und zu schreiben Nehmen Sie dieses Buch mit nach Hause und nutzen Sie einige Zeit, um zu lernen, die nächste einflussreiche, leistungsstarke, optimierte und wichtige Webanwendung zu erstellen, eine Website, die genau das ist, was Sie wollen, und erfüllt die Anforderungen Ihres Publikums. Über mich: Ich bin ein Softwareentwickler mit einer breitenErfahrung in C/C ++, Java, Python, HTML, CSS und JavaScript. Ich baue Websites auf, die die Leute nutzen, besuchen und sogar süchtig machen wollen, um nur Zeit zu lernen, nachzubilden und zu töten, und vor allem verkaufe ich Software. Wenn Sie eine Idee hatten, wie Sie eine Website aussehen und funktionieren wollten, waren Sie bereit, mich zu unterstützen, damit ich meine eigenen Bedürfnisse erfüllen kann, während ich Ihre begegne, und Sie sind bereit, die Kosten für die Ausführung einer Website selbst zu decken. Ich würde Ihnen das nächste YouTube, Tiktok, Twitter, Google oder sogar eine High-Tech-Sicherheits-App aufbauen, auf die Sie zugreifen können. Anstatt zu versuchen, Ihnen meine Zeit zu verkaufen, versuche ich, Ihre zu kaufen: Ich möchte Sie über das Erstellen einer App (Website) mit den bereits vorhandenen Informationen sprechen und Ihnen beibringen, was Sie benötigen, um ein unabhängiger Softwareentwickler zu sein. Unternehmer, der eine erfolgreiche Karriere in dem gewünschten Bereich leitet. Und lassen Sie mich klar sein, die Ausbildung, die ich Ihnen gebe, wird informell sein. Sie könnten zur Schule gehen und all dies mit einem lernenRMAL Education oder sogar dieses Buch in der Schule lesen, vervollständigen Sie Ihre Aufgaben und nehmen Sie viel von Ihrer Ausbildung ab, aber ich werde Sie nicht offiziell in den heißen Sitz bringen und Sie bitten, Aufgaben abzuschließen. Ich bin nicht Ihr Professor, Sie können mich wie einen Freund vorstellen, der Sie zu einer Karriere führen möchte, die von Ihrem persönlichen Erfolg getrieben wird. Und ich verkaufe Ihnen auch keinen Erfolg, Sie müssen es mit Ihrer Zeit kaufen. Das Lernen des Codes hat eine steile Lernkurve und war nie einfach oder sollte es auch sein. Sie müssen so hart wie möglich arbeiten und weiterhin versuchen, zu scheitern und es erneut zu versuchen, selbst wenn Sie frustriert sind, um Apps selbst zu lernen und zu erstellen. Das liegt in der Natur des Code selbst. Der Code wird von einem Compiler ausgeführt, der die Programmiererfehlermeldungen angibt. Diese können Sie beibringen, wie Sie codieren, auch wenn Sie den Fehler einfach in Ihre Suchmaschine kopieren und die Beispiele anderer Personen lesen. Und ich muss sagen, Sie müssen nicht extrem reich, klug, erfolgreich sein, erfolgreich,EN detailorientiert oder organisiert, um eine App zu erstellen. Der Computer kümmert sich um diese Organisation für Sie. Sie müssen nur die Versuch und Irrtum durchhalten, den Fokus aufrechterhalten und hart daran arbeiten, was Sie tun, und Sie werden in ganz dem, was Sie tun, eine sehr erfolgreiche Karriere haben. Wer ich bin: Mir ist klar, dass es im letzten Abschnitt mehr um das Lernen und Ihre Wege aus diesem Buch ging. Wer bin ich genau? Das ist eine komplizierte Frage. Ich bin mir selbst nicht sicher . Kurz gesagt, wenn Sie dieses Buch lesen, haben Sie es nach Hause gebracht, weil Sie es durchgeflippt und dachten, es sei nützlich, oder wenn Sie nur so weit in Sie gelesen haben, bin ich für Sie eine gleichgesinnte Person, die Sie in Erfolg sehen möchte alles was du tust. Ich bin selbst Ingenieur, eine SoftwareEntwickler und ein Student, und ich schreibe dieses Buch für andere Schüler, die ihr Leben erleichtern wollen, indem ich ein Handbuch der Software hat, das sie ihr Leben erleichtern müssen, indem sie Beispiele geben, um zu kopieren, die wie ein großes Puzzle in eine Arbeit zusammenpassen möchten nützlich, groß, funktional, kohärent und ansprechendes App, der den Erfolg fördern kann, unabhängig von der Geschäftszeile. Das ist es, was ich tue: Ich baue Apps auf, um mir und anderen Menschen erfolgreich zu helfen. Ich bin auch ein Autor, obwohl dies meine erste Veröffentlichung ist, die ich abschließen möchte, um mein Portfolio in ein nützliches Dokument zusammenzustellen, und ich bin auch ein Künstler. Ich gebe dir das zu, ich bin eine Art seltsamer Person. Ich bin nicht perfekt, ich habe mit dem Gesetz, das mich sogar dazu gebracht hat, Colleges und Universitäten zu verlassen und Staaten zu verlassen, um zu versuchen, mich mit mehr Erfolg einen Namen zu machen. Ich bin eine Frau von Geburtmännlich von Natur aus. Ich hatte in der Vergangenheit Probleme mit anderen Leuten, die zu Kämpfen mit dem Schreiben und Erstellen von Webapps führen, und ich entschuldige mich, dass ich dieses Buch nicht früher in die Hand bringen konnte: Sie brauchten das. Sie möchten Code lesen und schreiben, der wie meins aussieht und wie meins funktioniert und dasselbe tut, aber noch besser, denn wenn Sie es sich leisten können, dieses Buch zu kaufen, anstatt Ihre Tastatur zu pürieren Dafür haben Sie die Ressourcen, die Sie benötigen, um in Ihrem Leben erfolgreich zu sein. Ich hatte alle möglichen Probleme mit der Familie, die aufwuchsen, Gesundheitszustände, Ärzte, Medien und Gesetze, und mein Code spiegelt tief den Kampf wider, der Feminismus und weibliche Natur in einer geteilten und frustrierten Welt ist. Dieses Buch ist mir jedoch zutiefst wichtig, mein Baby, mein Portfolio und meinen Lebensunterhalt. Daher schätze ich Ihre Überlegung, wenn Sie den Text mit nach Hause nehmen und sorgfältig darüber poren, um von mir zu lernen. Bitte denken Sie daran, ich bin nicht perfekt,Das Buch wird Fehler, Überarbeitungen und neue Ausgaben haben, und Sie müssen mit Ihrem logischen Gehirn so gut wie möglich nachdenken, um eine erfolgreiche Erfahrung mit meinem Schreiben zu haben. Verstehe auch, dass ich es gut für dich meine, auch wenn du beim Schreiben Herausforderungen gegenübersteht. Denken Sie so darüber nach: Wenn Sie einfach ein Computersystem mieten können, um alles zu tun, was Sie sich im digitalen Bereich vorstellen können, speichern Sie alle Informationen, die Sie begegnen, #$%! Yze und organisieren Sie es und verstehen Sie es, Sie werden es tun Unweigerlich treten auf Schwierigkeiten mit den Informationen auf, die Sie einnehmen und sogar veröffentlichen. Ich sage dir das, weil ich auf die gleichen Schwierigkeiten stoße. Verwenden Sie dieses Buch auf eigenes Risiko, arbeiten Sie mit Ihrer Community und Ihren Communities zusammen, die Ihnen zur Verfügung stehen, um Software in einer sicheren Umgebung zu erstellen, und nehmen und warum ich Ihnen diesen Text bringen und Ihnen helfen kann, erfolgreich zu sein, ohne auf einen Wahnsinn zu gehen, der verlässtIch habe ruiniert, zerrissen und ausgefranst, während ich auf die gewöhnlichen Probleme stoße, die jeder auf globaler Ebene tut, dank der paralellistischen globalen Skala des Netzwerks, in der wir arbeiten werden, im Internet. Sie sind vielleicht nicht sehr vertraut damit, wer ich mit nur wenigen Worten bin, aber ich ermutige Sie, weiterzulesen, Sie werden mich kennenlernen, während Sie mich weiter lesen und verstehen, während Sie Ihre eigenen Projekte erstellen, um Ihre Arbeit abzuschließen. In diesem Buch gibt es keine Hausaufgaben, solange Ihre Professoren oder Lehrer Sie nicht zuweisen, aber ich ermutige Sie dringend, ein Portfolio von Projekten selbst aufzubauen, während Sie mit dem Lesen gehen, sowie ein Capstone -Projekt, das zeigt, wie Sie können Wenden Sie an, was Sie gelernt haben. Mein Capstone -Projekt ist die Grundlage für das meiste, was Sie in diesem Buch lesen werden, da es Code aus meinen vorherigen Projekten, Code, den ich erstellt und gelernt habe, methodisch von Hand zu schreiben, und eine breite Palette von Ideen und Tipps, die mir geholfen haben Erfolg bis zu dem Punkt, an dem ich eine einfache App drehen kann, die istUlly war vorgestellt und sieht aus und verhält sich wie eine beliebte App, die Sie möglicherweise Ihren Freund oder Ihre Familie im Internet verwenden, die Ihnen oder in den Nachrichten beworben wurden. Was dieses Buch ist: Dieses Buch ist ein Tutorial mit Beispiel. Hier finden Sie Code, Anweisungen zum Code, Informationen zum Debugging-Code und das Beheben von Fehlern, Fehlerbehebungsschritte, Anweisungen zum Sichern und Speichern Ihres Code Ihr Code, erstellen interaktive Websites, die unterhaltsam, engagiert und süchtig machen, und Sie werden ein Gefühl dafür bekommen, wer ich bin, warum dies wichtig ist und wie Sie sich selbst, Ihr App und Ihr Unternehmensimage sowie die Software, die Sie ers...
Praktisches webbasiertes Deep Learning und Sicherheit anhand von Beispielen

Praktisches webbasiertes tiefes Lernen und Sicherheit durch Beispiel Dritte Ausgabe Charlotte Harper 3. Juli 2024 Vorwort: Sicherheitsüberlegungen im Aufbau von Software für das Web sind ein wichtiger Bestandteil des Plans und der Ausführung eines Webentwicklers, während ein Prototyp für praktische Zwecke zuverlässig, stabil und nützlich ist. Das DOM (Dokumentobjektmarkup) mit der Implementierung von HTML, JavaScript und CSS sowie Backend -Software, die Python, C/C ++, Java und Bash implementiert, geben Webentwicklern die Freiheit und die Möglichkeit, eine Vielzahl von Projekten zu erstellen, die ausdrücken, die ausdrücken Kreativität, Benutzerfreundlichkeit und Funktionalität. Normalerweise auf einem Touchscreen -Smartphone -Gerät. Die meisten Menschen würden nicht einmal wissen, woher sie anfangen sollen, wenn sie eine Website erstellen möchtenKratzer, sie würden tendenziell auf der Website einer anderen Person beginnen und etwas Begrenztes in Funktionalität, Zuverlässigkeit, Benutzerfreundlichkeit und insbesondere Kreativität aufbauen, wenn sie alle neuesten leistungsstarken Tools hätten zur Verfügung haben können, um etwas Nützliches zu erstellen, ohne Zeit zu verschwenden, um Schaltflächen zu drücken und insbesondere Geld verschwenden, um teure Abonnements für Software zu bezahlen, die nur wenige Menschen angesichts der Einschränkungen in Bezug auf Benutzerfreundlichkeit und Flexibilität verwenden wollten. Wenn Sie ein paar Minuten Zeit haben, um dieses Buch durchzulesen und zu lernen, was ich Ihnen beibringen möchte, oder sogar mit mir persönlich über Ihre Ziele sprechen und eine Anleitung in die richtige Richtung erhalten und motiviert sind, zu lernen, Ihre eigene Software zu codieren und zu schreiben Nehmen Sie dieses Buch mit nach Hause und nutzen Sie einige Zeit, um zu lernen, die nächste einflussreiche, leistungsstarke, optimierte und wichtige Webanwendung zu erstellen, eine Website, die genau das ist, was Sie wollen, und erfüllt die Anforderungen Ihres Publikums. Über mich: Ich bin ein Softwareentwickler mitErfahrung in C/C ++, Java, Python, HTML, CSS und JavaScript. Ich baue Websites auf, die die Leute nutzen, besuchen und sogar süchtig machen wollen, um nur Zeit zu lernen, nachzubilden und zu töten, und vor allem verkaufe ich Software. Wenn Sie eine Idee hatten, wie Sie eine Website aussehen und funktionieren wollten, waren Sie bereit, mich zu unterstützen, damit ich meine eigenen Bedürfnisse erfüllen kann, während ich Ihre begegne, und Sie sind bereit, die Kosten für die Ausführung einer Website selbst zu decken. Ich würde Ihnen das nächste YouTube, Tiktok, Twitter, Google oder sogar eine High-Tech-Sicherheits-App aufbauen, auf die Sie zugreifen können. Anstatt zu versuchen, Ihnen meine Zeit zu verkaufen, versuche ich, Ihre zu kaufen: Ich möchte Sie über das Erstellen einer App (Website) mit den bereits vorhandenen Informationen sprechen und Ihnen beibringen, was Sie benötigen, um ein unabhängiger Softwareentwickler zu sein. Unternehmer, der eine erfolgreiche Karriere in dem gewünschten Bereich leitet. Und lassen Sie mich klar sein, die Ausbildung, die ich Ihnen gebe, wird informell sein. Sie könnten zur Schule gehen und all dies mit einem lernenFormale Ausbildung oder sogar dieses Buch in der Schule lesen, Ihre Aufgaben abschließen und viel von Ihrer Ausbildung abnehmen, aber ich werde Sie nicht offiziell in den heißen Sitz bringen und Sie bitten, Aufgaben abzuschließen. Ich bin nicht Ihr Professor, Sie können mich wie einen Freund vorstellen, der Sie zu einer Karriere führen möchte, die von Ihrem persönlichen Erfolg getrieben wird. Und ich verkaufe Ihnen auch keinen Erfolg, Sie müssen es mit Ihrer Zeit kaufen. Das Lernen des Codes hat eine steile Lernkurve und war nie einfach oder sollte es auch sein. Sie müssen so hart wie möglich arbeiten und weiterhin versuchen, zu scheitern und es erneut zu versuchen, selbst wenn Sie frustriert sind, um Apps selbst zu lernen und zu erstellen. Das liegt in der Natur des Code selbst. Der Code wird von einem Compiler ausgeführt, der die Programmiererfehlermeldungen angibt. Diese können Sie beibringen, wie Sie codieren, auch wenn Sie den Fehler einfach in Ihre Suchmaschine kopieren und die Beispiele anderer Personen lesen. Und ich muss sagen, du musst nicht extrem reich, schlau sein,Essful oder sogar detailorientiert oder organisiert, um eine App zu erstellen. Der Computer kümmert sich um diese Organisation für Sie. Sie müssen nur die Versuch und Irrtum durchhalten, den Fokus aufrechterhalten und hart daran arbeiten, was Sie tun, und Sie werden in ganz dem, was Sie tun, eine sehr erfolgreiche Karriere haben. Wer ich bin: Mir ist klar, dass es im letzten Abschnitt mehr um das Lernen und Ihre Wege aus diesem Buch ging. Wer bin ich genau? Das ist eine komplizierte Frage. Ich bin mir selbst nicht sicher . Kurz gesagt, wenn Sie dieses Buch lesen, haben Sie es nach Hause gebracht, weil Sie es durchgeflippt und dachten, es sei nützlich, oder wenn Sie nur so weit in Sie gelesen haben, bin ich für Sie eine gleichgesinnte Person, die Sie in Erfolg sehen möchte alles was du tust. Ich bin selbst Ingenieur,Entwickler und ein Student, und ich schreibe dieses Buch für andere Schüler, die ihr Leben erleichtern wollen, indem ich ein Handbuch der Software hat, das sie ihr Leben erleichtern müssen, indem sie Beispiele geben, um zu kopieren, die wie ein großes Puzzle in eine Arbeit zusammenpassen möchten nützlich, groß, funktional, kohärent und ansprechendes App, der den Erfolg fördern kann, unabhängig von der Geschäftszeile. Das ist es, was ich tue: Ich baue Apps auf, um mir und anderen Menschen erfolgreich zu helfen. Ich bin auch ein Autor, obwohl dies meine erste Veröffentlichung ist, die ich abschließen möchte, um mein Portfolio in ein nützliches Dokument zusammenzustellen, und ich bin auch ein Künstler. Ich gebe dir das zu, ich bin eine Art seltsamer Person. Ich bin nicht perfekt, ich habe mit dem Gesetz, das mich sogar dazu gebracht hat, Colleges und Universitäten zu verlassen und Staaten zu verlassen, um zu versuchen, mich mit mehr Erfolg einen Namen zu machen. Ich bin eine Frau von Geburtweiblich von Natur aus. Ich hatte in der Vergangenheit Probleme mit anderen Leuten, die zu Kämpfen mit dem Schreiben und Erstellen von Webapps führen, und ich entschuldige mich, dass ich dieses Buch nicht früher in die Hand bringen konnte: Sie brauchten das. Sie möchten Code lesen und schreiben, der wie meins aussieht und wie meins funktioniert und dasselbe tut, aber noch besser, denn wenn Sie es sich leisten können, dieses Buch zu kaufen, anstatt Ihre Tastatur zu pürieren Dafür haben Sie die Ressourcen, die Sie benötigen, um in Ihrem Leben erfolgreich zu sein. Ich hatte alle möglichen Probleme mit der Familie, die aufwuchsen, Gesundheitszustände, Ärzte, Medien und Gesetze, und mein Code spiegelt tief den Kampf wider, der Feminismus und weibliche Natur in einer geteilten und frustrierten Welt ist. Dieses Buch ist mir jedoch zutiefst wichtig, mein Baby, mein Portfolio und meinen Lebensunterhalt. Daher schätze ich Ihre Überlegung, wenn Sie den Text mit nach Hause nehmen und sorgfältig darüber poren, um von mir zu lernen. Bitte denken Sie daran, ich bin nichtDieses Buch wird Fehler, Überarbeitungen und neue Ausgaben haben, und Sie müssen mit Ihrem logischen Gehirn so gut wie möglich nachdenken, um eine erfolgreiche Erfahrung mit meinem Schreiben zu machen. Verstehe auch, dass ich es gut für dich meine, auch wenn du beim Schreiben Herausforderungen gegenübersteht. Denken Sie so darüber nach: Wenn Sie einfach ein Computersystem mieten können, um alles zu tun, was Sie sich im digitalen Bereich vorstellen können, speichern Sie alle Informationen, die Sie begegnen, #$%! Yze und organisieren Sie es und verstehen Sie es, Sie werden es tun Unweigerlich treten auf Schwierigkeiten mit den Informationen auf, die Sie einnehmen und sogar veröffentlichen. Ich sage dir das, weil ich auf die gleichen Schwierigkeiten stoße. Verwenden Sie dieses Buch auf eigenes Risiko, arbeiten Sie mit Ihrer Community und Ihren Communities zusammen, die Ihnen zur Verfügung stehen, um Software in einer sicheren Umgebung zu erstellen, und nehmen und warum ich Ihnen diesen Text bringen und Ihnen helfen kann, erfolgreich zu sein, ohne auf einen Weg des Wahnsinns zu gehenAves mich ruiniert, zerrissen und ausgefranst, während ich auf die gewöhnlichen Probleme stoße, die jeder auf globaler Ebene tut, dank der paralellistischen globalen Skala des Netzwerks, in der wir arbeiten werden, im Internet. Sie sind vielleicht nicht sehr vertraut damit, wer ich mit nur wenigen Worten bin, aber ich ermutige Sie, weiterzulesen, Sie werden mich kennenlernen, während Sie mich weiter lesen und verstehen, während Sie Ihre eigenen Projekte erstellen, um Ihre Arbeit abzuschließen. In diesem Buch gibt es keine Hausaufgaben, solange Ihre Professoren oder Lehrer Sie nicht zuweisen, aber ich ermutige Sie dringend, ein Portfolio von Projekten selbst aufzubauen, während Sie mit dem Lesen gehen, sowie ein Capstone -Projekt, das zeigt, wie Sie können Wenden Sie an, was Sie gelernt haben. Mein Capstone -Projekt ist die Grundlage für das meiste, was Sie in diesem Buch lesen werden, da es Code aus meinen vorherigen Projekten, Code, den ich erstellt und gelernt habe, methodisch von Hand zu schreiben, und eine breite Palette von Ideen und Tipps, die mir geholfen haben erfolgreich bis zu dem Punkt, an dem ich eine einfache App drehen kann, dieVollständig vorgestellt und sieht aus und verhält sich wie eine beliebte App, die Sie Ihren Freund oder Ihre Familie im Internet verwenden können, die Ihnen oder in den Nachrichten beworben werden. Was dieses Buch ist: Dieses Buch ist ein Tutorial mit Beispiel. Hier finden Sie Code, Anweisungen zum Code, Informationen zum Debugging-Code und das Beheben von Fehlern, Fehlerbehebungsschritte, Anweisungen zum Sichern und Speichern Ihres Code Ihr Code, erstellen interaktive Websites, die unterhaltsam, engagiert und süchtig machen, und Sie werden ein Gefühl dafür bekommen, wer ich bin, warum dies wichtig ist und wie Sie sich selbst, Ihr App und Ihr Unternehmensimage sowie die Software, die Sie erstellen, darstellen können Im absolut besten Licht, um für Ihre Endbenutzer, die Besucher Ihrer Website, so attraktiv wie möglich zu sein. In diesem Buch werde ich eine Reihe von Beispielen für Softwaredesign mit Schwerpunkt auf dem Web als Plattform und Sicherheit demonstrieren. Wir werden die Lernerfahrung initiieren, indem wir eine Basis bauenOjektieren Sie die UNIX -Shell mit Backup- und Skriptfunktionen. Anschließend untersuchen wir eine grundlegende Blog -Website, aktualisieren unser Blog mit Foto- und Videofunktionen sowie diese Funktionen, um Sicherheitslösungen mithilfe kostenloser Software zu verwenden, und sichern unseren Server mithilfe eines Steckbetriebs -Authentifizierungsmoduls (PAM). Anschließend werden die Dateibehandlungen und -verarbeitung, die Videobearbeitung, die Sprachspende, das Scannen von Barcode und die optische Charaktererkennung untersucht. Unterwegs werden wir APIs untersuchen, die uns helfen, unsere Software nützlicher und sicherer mit kostenlosen und bezahlten Optionen zu gestalten. Unterwegs werden wir physische Sicherheits- und militante Tools wie Schusswaffen und Munitionsdesign und -herstellung untersuchen, einschließlich Fass- und Repeater -Design, Turm- und Drohnendesign sowie andere Schulleiter, die wir in unsere Software im vorhandenen Netzwerk integrieren, um unsere Software zu schützen und Selbstverteidigung und Resillience demonstrieren. Wir werden auf dem Weg Pausen einlegen, um Spiele, 2D und 3D zu bauenEndering Motoren und arbeiten Sie mit eingebetteter Hardware in Fallstudienbeispielen für grundlegende dimensionale Rendering -Software und eines elektronischen vibrierenden Massagegeräts, der in Silikonkautschuk gegossen wurde. Unterwegs werden wir auch maschinelle Lernlösungen verwenden, die bereits verfügbar sind, um unsere Software besser zu sichern. Wir werden auch Aktien -Tools verwenden, die für das Web verfügbar sind, um den Prozess zu optimieren und zu sichern. Dieses Buch ist ein Leitfaden für Ihren Erfolg beim Erstellen einer Webanwendung und die Integration in ein professionelles Netzwerk von Computer und eingebetteten mechanischen Systemen sowie insgesamt ein Leitfaden zum Erstellen von Software und eingebetteter Hardware ohne Hintergrundkenntnisse oder frühere Erfahrung. Was dieses Buch nicht: Wenn Sie wirklich eine Website haben möchten, können Sie einfach einen einfachen Geschäft einrichten und verkaufen, was Sie benötigen, ein Blog veröffentlichen, Fotos oder Videos veröffentlichen oder auf andere Weise jemals eine einzige Codezeile schreiben. Dieses Buch ist das nicht. In diesem Buch werden Sie beigebracht, wie Sie Software erstellen, die vollständig nützlicher istVorgestellt, funktional und sicher als jede Software, die Sie bereits finden können, da sie die neueste Software bereitstellt, die noch Prototypen ist, möglicherweise teuer ist, in einer Skala ältere Unternehmen zu betreiben, und nicht an die rückwärts gerichteten, verworrenen Unternehmen eingerichtet werden Verdienen Sie Geld für Leute, die nichts wirklich tun. Wenn Sie diesem Buch genau folgen, möchten Sie Code schreiben, Code recherchieren, Ihre eigenen Apps erstellen und mit dem, was Sie tun, Geld verdienen. Ich werde mit diesem Buch auch in frühen Phasen Geld verdienen, da es Informationen enthält, die die Leute lesen und lesen möchten und bereits kaufen, wenn sie meine Apps kaufen oder verwenden. Dieses Buch erstellt keine App für Sie, zeigt Sie jedoch in die richtige Richtung und armiert Sie mit den Tools, die Sie benötigen Code, den Sie als Beispiel schreiben müssen, bereit, in Software zusammengefügt zu werden, die Sie und Ihre Anhänger, Gäste, KundschaftViehfänger, Familie, Besucher, Auftragnehmer und die Menschen im Internet möchten nutzen und unterstützen. Was Sie lernen werden: In diesem Buch werden Sie vermittelt, wie Sie Software, wirklich funktionale, nützliche Software, Medienaufzeichnungen, Sicherheitsfunktionen wie Gesichtserkennung, Barcode -Scannen von Maschinen, Video und Fotos wie Bluetooth erstellen und maschinenlesbarer Zonen -Barcode -Scannen, Web -APIs zum Authentifizieren, Aufzeichnungen und Rendern machen und austauschen und Near Field (NFC) Kommunikation. In diesem Buch werden Sie unterrichtet, wie Sie einen vernetzten Computer verwenden, der sich auf Debian Linux konzentriert, wie man Bash -Code erstellt, um die Installation und Unterstützung Ihrer Software zu einer nahtlosen, automatisierten Brise zu machen und Python -Code als Backend zum Servieren dynamischer Nachrichten zu erstellen, Stil Dinge, die gut mit CSS -Stilen mit Bootstrap verwendet werden, aktivieren Sie Benutzeranmeldungen und Interaktivität über vernetzte Geräte, erstellen interaktive Medien und Netzwerk mit anderen Websites, um Sicherheitsfunktionen wie Textnachrichten zur Überprüfung oder andere Zwecke, ID -Scannen, Bild- und Video -Moderation, Daten, Daten anzubietenRansaktionen, um Ihre Software sicher zu halten, Zahlungsverarbeitung, Kryptowährungshandel, asynchrone Aufgaben und vieles mehr. Sie lernen, wie Sie Ihre eigenen Bluetooth -Geräte mit Batterien, Ladegeräten, Mikrocontrollern, Schaltkreisen, Motoren und Sensoren, mit Lötmittel, Draht und 3D -gedrucktem sowie gegossenen Materialien bauen. Ich werde 3D -Design -Schulleiter demonstrieren, die auf additive Herstellung und Werkzeug und die Herstellung angewendet werden, sodass Sie Ihre eigenen eingebetteten Hardware -Geräte mit integrierten Batterien, Ladegeräten, elektronischen Schaltkreisen und funktionalen Ausgaben herstellen können. und vernetzen Sie sich mit Bluetooth und dem Web. Insbesondere werden wir zwei Fallstudien untersuchen, ein vibrierendes Massagegerät und eine hausgemachte Waffe, die beide in OpenSCAD programmiert sind, die als grafische Schnittstelle oder Befehlszeilen -Dienstprogramm verfügbar sind und für schnellere Ergebnisse in ein Web integriert werden können. Sie werden lernen, wie Sie eine Website von Grund auf ohne vorherige Erfahrung erstellen und bereitstellen, sie funktionieren, sicher, schön, nützlich und am meistenmportant praktisch. Sie lernen, wie Sie maschinelles Lernen und Computer Vision verwenden, um eine Website sicher und praktischer zu gestalten, Video und Audio von Ihrer Website aufzunehmen, Ihre Stimme zu spenden, Musik zu machen und Audio zu modulieren, um nützliche Samples zu erstellen und das Rauschen durchzubrechen Nutzung anderer Websites, um das bestmögliche Netzwerk von Websites zu erstellen, die Sie direkt mit Ihnen verknüpfen können, um alle nützlichen Informationen zu teilen, die Sie anbieten, und noch wichtiger ist, um Menschen zu Ihrer Software und Ihrem Geschäft zu bringen. Dieses Buch konzentriert sich am stärksten auf Medien, Sicherheit und maschinelles Lernen. Dies sind die drei Hauptkomponenten, die Ihnen helfen, nützliche Software für das Web zu erstellen, indem Sie die richtigen Benutzer einbeziehen und die falschen auf eine Weise auslassen, die realistisch, praktisch ist. Hände auf und engagiert und gleichzeitig automatisch und robust. Dieses Buch lehrt Unix, speziell Debian (Ubuntu), Bash Shell, Python, HTML, CSS, JavaScript und eine Reihe nützlicher Softwarepakete fürN wie Anfragen sowie nützliche Bash -Software wie Git und FFMPEG. Ich werde Ihnen auch beibringen, wie Sie Kryptowährung automatisch handeln und Zahlungen in Kryptowährung oder aus regulären Debitkarten übernehmen und gleichzeitig Ihre Besucher einen Anteil an Ihrem Einnahmen auszahlen, wenn Sie sich dafür entscheiden. Ich werde Ihnen beibringen, wie Sie mit Werbung Geld mit Ihrer Website verdienen können, wie Sie Ihre App für Suchmaschinen vorbereiten und es schnell machen, im ersten Platz für das, was Ihre Kunden suchen, nach Ihnen suchen, und in so vielen gemeinsamen Rangliste Suchanfragen wie möglich. Ich werde Ihnen beibringen, wie Sie Ihre Software verkaufen, sie bewerben, Kunden ansprechen, die nach Ihren Diensten suchen, und sich im Internet einen Namen machen, wenn Sie bereits existieren, kostengünstig sind und gut funktionieren. Ich werde Ihnen beibringen, wie Sie Ihre Daten auf Cloud -Computern speichern, die für Sie funktionieren, und Ihre Daten billig speichern, wie Sie eine Website planen und erstellen, auf der Ihre Benutzer wollen und was Sie wollen und wie Sie Ihre Benutzer von engagieren könnenTippen Sie auf Ihrer Website mit Benachrichtigungen, E -Mails, Textnachrichten, Telefonanrufen und weiteren Möglichkeiten, um Ihre Benutzer zurück zu Ihrer Website zu bringen, um eine Schaltfläche zu erreichen, die Ihnen nur sichergestellt ist. Dieses Buch konzentriert sich auf die praktische Veröffentlichung und Verteilung von Medien in großen Mengen, von Text über Fotos über Videos bis hin zu Audio, macht einen guten Eindruck auf Endbenutzer (Ihre Kunden) und den Verkauf auf eine Weise, die Sie tun, um zu erstellen, um zu erstellen Eine Website, eine App, die nur für Sie und Sie repräsentativ ist und Sie, Ihre Software und Ihr Unternehmen auf die bestmögliche Weise gut aussehen. Sie lernen auch ein paar Tipps und Tricks von mir, aus Codierungs -Tipps, praktischer Eitelkeit wie Make -up und Fotografie, Modellierung und Schauspiel und mehr, die wichtig sein werden, um sich und Ihr Unternehmen im bestmöglichen Licht mit allen verfügbaren Tools darzustellen Ihnen bei gleichzeitig so viel Inhalt verteilt, wie Sie es benötigen, um eine gesunde Balance von Plattformen zu erhalten, um Ihre zu bringenE ohne mehr Anstrengung, Arbeit oder Geld als nötig. Dieses Buch heißt „Praktisches webbasiertes Deep -Lern und Sicherheit mit Beispiel“ aus einem Grund: Es handelt Die im Text beschriebenen praktischen Zwecke. Die Lernkomponente dieses Textes umfasst auch maschinelles Lernen, den Code. Ich werde Ihnen zeigen Vorhersagekennzahlen aus Bildern, wie der Art des Bildes als authentisches, computergestütztes Bild oder eine optische Kopie (ein Foto eines Bildes oder gedrucktes Foto). Maschinelles Lernen ist sehr wichtig, wenn es um Websicherheit und Software -Sicherheit geht, da es ansonsten unmögliche Aufgaben vorformen kann. Ihr ComputerMelden Sie sich mit einem Passcode an, aber es kann sicherer sein, ihn zu verwenden, wenn es Sie mit Ihrem Gesicht einmeldet. Sie können einen Servercomputer so sicher machen, einen Computer, der Sie normalerweise um einen Benutzernamen und einen Passcode fordert und Sie anmelden, möglicherweise mit einem Bestätigungs -Token für jede neue Anmeldung oder neue IP Verwenden, grundsätzlich sicher und leistungsstarke Software, dies kann ausreichen. Das Binden Ihrer Software zu eng an die Software eines anderen, wie einen E -Mail -Dienst oder einen SMS -Dienst, reicht nicht aus, um Ihre Software zu sichern, oder jeder von Ihnen verwendete Website. Jeder, der Software erstellt, die tadellos sicher ist, hat einen Eindruck davon, was dies impliziert. Software ist von Natur aus unsicher, da die Geräte und Konten, die wir zugreifen, nicht immer zur Verfügung stehen, sie könnten in den Händen von Personen stehen, die schlecht für die Software beabsichtigen, und daher möglicherweise ein Risiko für die Software selbst darstellen. Dies ist etwas von dem Fokus dieses Buches. Ein vernetzter Computer ist standardmäßigMit einem langen Schlüssel -Token besichert, genannt und SSH- oder Secure -Shell -Schlüssel und ansonsten am besten mit einem Webserver gesichert, da der Webserver den auf dem Server selbst ausgeführten Open -Zugriff sowie Stand der Kunstsicherheitstools bietet. Der Webserver hat Zugriff auf den Webbrowser des Benutzers, der wohl der leistungsstärkste Teil des Benutzergeräts ist, da der Benutzer auf vernetzte Software zugreifen kann. Dieses Toolkit kann Text, die von Ihnen angezeigten Webseiten und aufzeichnen und auch Bilder, Audio und Video (wie ein Foto eines Gesichts oder eine Status -ID) aufzeichnen, können Bluetooth -Radiogeräte lesen und schreiben und lesen und auf das Field schreiben können Transponder -Tags, kostengünstige Schlüsselkarten, FOBs, Aufkleber, Ringe und sogar Chipimplantate mit einzigartigen Seriennummern, die mit Daten gelesen und geschrieben werden können, die von einem Webserver generiert und validiert werden können, der an der Website gebunden ist. Mit allen Ihnen zur Verfügung stehenden Tools mit diesem Buch werden Sie sich mit dem Wissen ausstatten, eine sichere Website zu erstellen, und insgesamt aURE Networked Computer System, das für Sie funktioniert, Ihr Gebot macht und sieht und fühlt sich richtig aus. Wo anfangen: Sie können gerne den Abschnitt überspringen. Ich beginne dieses Buch oder einen beliebigen Abschnitt in den genauen Code, den Sie benötigen, insbesondere wenn Sie Erfahrung mit der Codierung vor oder eines der oben genannten Tools haben sowie dokumentieren Anwendungsfälle und praktische Beispiele davon. Wenn Sie keine Erfahrung beim Schreiben von Code haben, empfehle ich Ihnen dringend, alle dieses Buch zu lesen und vor allem die vorherigen Abschnitte zu lesen, um sicherzustellen, dass dieses Buch für Sie geeignet ist. Wenn dieses Buch für Sie nicht geeignet ist, sollten Sie es einem Freund oder Verwandten verschenken, der möglicherweise daran interessiert ist, etwas über die Webentwicklung selbst zu lernen, und sogar in Betracht ziehen, es zurückzugeben und von ihnen zu lernen, um die Lücken zu schließen, in denen ich Sie als gescheitert habe Lehrer oder andere Lehrer haben es vor mir getan. Beginnen Sie dort, wo Sie wollen, jeder Teil dieses Buches ist nützlich, wenn Sie beabsichtigen, eine nützlichePP, und denken Sie daran, dass die besten Apps mit dem Endbenutzer erstellt werden: Kennen Sie Ihren Kunden. Jetzt kennst du mich, du kennst dieses Buch und bist bereit zu beginnen. Schnappen Sie sich zunächst einen Computer (sogar den billigsten Laptop aus einem Box Store, Amazon oder ein alter Desktop und stellen Sie ihn auf eine Weise ein, die für Sie funktioniert. So lesen Sie dieses Buch: Text hervorgehoben, bedeutet, dass der Text in eine Eingabeaufforderung gehört, in der Sie den von Ihnen ausgeführten Code schreiben. Die Eingabeaufforderung ist stark auf die Tastatur ausgerichtet und erfordert wenig bis gar kein Klicken, beschleunigt Ihren Workflow und erleichtert Ihnen die Dinge. Erste Schritte: Lassen Sie uns eintauchen. Wir werden mit dem Erstellen von Code auf einer lokalen Maschine beginnen und ohne eine mit dem Internet verbundene Website zu erstellen. Dies ist sicherer, kostet nichts und ist für Sie leicht. Abhängig von Ihrem Betriebssystem ist es etwas anders, in eine Bash -Shell zu gelangen. Für Mac OS empfehle ich, an dieser Stelle eine virtuelle Maschine zu installieren, da Sie mit der größten Kompatibilität mitVirtuelle Maschine. Verschiedene Anbieter wie VirtualBox und Paralells können eine virtuelle Maschine für Sie ausführen. Es ist jedoch auch möglich, Ubuntu direkt auf der Maschine zu installieren, wenn Sie es vorziehen, eine native Umgebung zu verwenden, die empfohlen wird, um ein schnelles, optimiertes Erlebnis zu schaffen. Wenn Sie Linux oder Windows verwenden, was ich empfehle, sollte es recht einfach sein, ein Projekt zu erstellen. Öffnen Sie Ihr Terminal, passen Sie die Größe nach Anpassung an und beginnen Sie nach Schritt 2. Wenn Sie Windows verwenden, befolgen Sie bitte Schritt 1. Schritt 1: - Nur Windows -Benutzer Öffnen Sie in Windows die Eingabeaufforderung als Administrator und geben Sie ein WSL –Install Schritt 2: - Weiter hier oder überspringen Sie Schritt 1 bis hier, wenn Sie Windows nicht verwenden Beginnen Sie in einem offenen Terminal (abhängig von Ihrem Betriebssystem, Ubuntu in Windows, Terminal in Mac oder Linux oder einem ähnlichen Namen) mit dem Erstellen eines Projekts. Wir tun dies mit dem Befehl mkdir, der ein Verzeichnis erstellt. Wenn Sie ein Verzeichnis erstellen müssen, um Ihr empfohlenes Projekt zu speichern, verwenden Sie dieCD -Befehl, um in das Verzeichnis zu wechseln und und CD/Pfad/zu/Verzeichnis - Der Pfad sind die Ordner (Dateien), die Ihrem Zielverzeichnis vorausgehen, Ihr Standardpfad ist ~ oder/home/username (wo der Benutzername Ihr Benutzername ist). Um in das Standardverzeichnis zu wechseln, geben Sie CD oder CD ~ ein Beispiel MKDIR - Ersetzen Sie "Beispiel" durch den Namen des Verzeichnisses Jetzt haben Sie ein Arbeitsverzeichnis für Ihr Projekt. Da es so wichtig ist, dieses Verzeichnis zu speichern, falls Sie zu einem anderen Computer wechseln oder den von Ihnen geschriebenen Code bereitstellen müssen, damit es für das Web bereit ist, erstellen wir ein Skript, um Ihr Verzeichnis in den nächsten Schritten zu sichern. Das Erstellen eines Skripts erfordert jedoch ein wenig Code, und Code muss automatisiert werden, um so nützlich wie möglich zu sein. Erstellen wir also zuerst ein Skript, um Skripte zu erstellen. Beginnen wir zunächst das Skript erstellen und es ausführbar machen. Wir werden sudo, chmod und berühren dafür und das Skript anrufen


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Jetzt haben wir das Skript erstellt, es ausführbar gemacht und sind bereit, es zu bearbeiten. Nano ist ein Texteditor, mit dem Sie Text ohne Klicken bearbeiten können. Dies ist viel einfacher als die Verwendung einer grafischen Benutzeroberfläche. Verwenden Sie Nano und dann den Pfad zur Datei, um eine Datei mit Nano zu bearbeiten. Um ein Skript zu erstellen, das ein Skript erstellt, ist es ziemlich ähnlich dem Erstellen unseres Skripts in erster Linie. Wir werden den gleichen Code wie oben verwenden und den Namen des Skripts „ASScript“ durch einen Argumentparameter $ 1 ersetzen. Auf diese Weise können wir das Skript anrufen, indem wir einfach sudo Ascript -Newskript eingeben. In diesem Punkt können wir ein neues Skript erstellen, indem wir „Newscript“ durch den Namen Ihres Skripts ersetzen. Der Code in Nano sollte aussehen wie:

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
Und um Nano zu schließen, können wir die Steuertaste halten und X drücken, dann y, um zu bezeichnen, dass wir die Datei speichern und die Rückgabe drücken. Anstatt diese drei Befehle zum Bearbeiten eines Skripts einzugeben, können wir Sudo Ascript Ascript eingeben, um das Skript erneut zu bearbeiten. Das funktioniert! Und jedes neue Skript kann einfach ausgeführt werden, indem es in der Shell aufgerufen wird. Lassen Sie uns jetzt unsere Arbeit speichern: Schreiben wir ein Sicherungsskript, um unser neues Skript zu speichern und es dann in unserem Projektverzeichnis zu sichern und gleichzeitig das Sicherungsskript zu sichern.

sudo ascript backup
Nun in Nano:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Wobei/path/to/verzeichnis der Pfad zu dem mit MKDIR erstellten Projekt ist. Später lernen wir, wie Sie wiederholte Pfade wie diese mit einer Schleife und einer Liste kopieren, die weniger Code sind, aber vorerst halten wir es einfach und haben Sie ein paar Zeilen. Um dieses Skript auszuführen und Ihren Code zu sichern, speichern Sie die Datei in Nano mit Steuerung+x, y und kehren Sie zurück und geben Sie die unten in Ihre Shell ein

backup
Wenn Sie beim Lesen dieses Buches überhaupt für ein Passwort aufgefordert werden und in der Shell miteinander folgen, geben Sie Ihr Benutzerkennwort korrekt ein. Sie haben drei Versuche, bevor Sie den Befehl erneut ausführen müssen. Sie können die Auf- und Ab -Pfeile verwenden, um Befehle erneut auszusetzen und zu bearbeiten, falls Sie etwas zweimal ausführen müssen. Einfachem Drücken Sie zeitweise nach oben und unten, um einen Befehl auszuwählen, bevor Sie den Befehl mit den rechten, linken Pfeilen bearbeiten und die Taste sowie die Tastatur löschen und mit Rückgabe ausgeführt werden. Glückwunsch! Sie haben es geschafft, ein fantastisches Backup -Skript zu erstellen, das zwei wichtige Shell -Skripte in Ihrem Arbeitsverzeichnis unterstützt. Wir könnten die Dinge später bewegen, wenn das Projekt größer wird, aber das funktioniert vorerst. Kommen wir weiter in die Cloud. Wir werden GitHub dafür verwenden (obwohl es zahlreiche andere Git -Lösungen für die Sicherung gibt, sie sind alle ungefähr gleich.) Git ist eine Verision -Steuerungssoftware, mit der Sie Änderungen auf Ihre Sicherungen unterstützen können Software, während Sie sie zu einem Server machen, währendErmöglichen Sie auch, dass Sie ganze Kopien Ihrer Software hinter einem Kennwort oder Schlüssel herunterladen. Es ist maßgeblich am Speichern Ihrer Software beteiligt, zumal wir in gesicherte Linux -Instanzen migrieren, die manchmal brechen, wenn eine einzige Codezeile ausfällt, und Sie sperrten, während Ihr Code möglicherweise nicht gesichert wird, wenn Sie keine Chance haben, es zu unterstützen automatisch nach oben, was wir abdecken werden. Wenn Sie zu diesem Zeitpunkt noch nicht eine virtuelle Ubuntu -Maschine verwenden, empfehle ich zu diesem Zeitpunkt mit einer virtuellen Maschine von Ubuntu Vorgänge auf Ihrem Computer. Wir werden den Code in naher Zukunft auf einen Webserver verschieben, aber wir möchten sicherstellen Das. Wenn Sie immer noch Mac OS verwenden möchten, können Sie nach suchen und installierenE notwendige Pakete online, aber es gibt möglicherweise nicht Alternativen für jedes Paket, das dieses Buch oder diese Serie abdeckt. Fügen wir ein paar Befehle hinzu, um unsere Arbeit mit dem Sicherungsskript zu begehen, indem wir den Befehl sudo Ascript ausführen

# …
git add –all
git commit -m “backup”
git push -u origin master
Kontrolle X erneut X, um zu speichern. Jetzt müssen wir eine einmalige Konfiguration für dieses Projekt durchführen. Da es bald ein Git -Projekt sein wird, müssen wir nicht jedes Mal, wenn wir aus einem Git -Repository bereitgestellt werden, jeden Befehl eingeben, aber wir werden den Dreh raus haben, wenn wir unsere Bereitstellungsskripte schreiben. Stellen wir zunächst sicher, dass wir im richtigen Verzeichnis sind und das Git -Repository initialisieren und SSH -Tasten generieren.

cd /path/to/directory
git init
git branch -m master
ssh-keygen
Nachdem wir SSH-Keygen eingegeben haben, sollte der neue Schlüssel im Home-Ordner unter einem Ordner namens SSH gespeichert werden. Es heißt id_rsa.pub. Lassen Sie uns diesen Schlüssel finden und ihn kopieren. Es sehen,

cd ~
cat .ssh/id_rsa.pub
Kopieren Sie den Text, der vom letzten Befehl zurückgegeben wird, und erstellen Sie ein Konto mit Ihrem Git -Anbieter (idealerweise Github), bevor Sie den SSH -Schlüssel zu Ihrem Konto hinzufügen. Sobald Sie ein Konto haben, klicken Sie auf das obere rechte Menü und geben Sie Einstellungen ein, bevor Sie Ihre SSH -Taste in SSH- und GPG -Tasten im Menü hinzufügen. Wählen Sie eine SSH -Taste hinzufügen und fügen Sie Ihre hinzu, indem Sie ihn einfügen und ihm einen Titel geben, bevor Sie speichern und zu Github zurückkehren, um ein neues Repository zu erstellen. Dies ist für andere GIT -Anbieter ähnlich. Sie müssen ihre Dokumentation lesen. Geben Sie in der neuen Repository -Konfiguration Ihrem Repository einen beschreibenden Namen an und entscheiden Sie, ob Sie sie veröffentlichen möchten, und konfigurieren Sie noch keine Dateien für die Aufnahme. Sobald das Repository erstellt wurde, kopieren Sie den Klon mit SSH -URL und fügen Sie ihn in den folgenden Befehl ein.

git remote add git://… (your remote URL)
Jetzt können Sie mit CD in Ihr Repository zurückkehren, Sie werden damit vertraut sein. Probieren Sie jetzt Ihr Backup -Skript mit Backup aus Großartig! Jetzt können wir wirklich eine Codierung bekommen. Lassen Sie uns jetzt Django installieren, da wir ein gutes Verständnis für Bash und Git haben. Django lässt uns unsere Software automatisch sichern, Bash kann dies auch tun, aber Django sollte eine einfachere sicherere Implementierung haben (es kann einfach deaktiviert und einfacher konfiguriert werden). Um Software in Ubuntu zu installieren, werden wir den Sudo Apt-Get-Befehl verwenden. Lassen Sie uns zunächst die Software, die wir bereits hatten, aktualisieren und aktualisieren. Dies kann mit Sudo APT-Get-Update und sudo APT-Get-Upgrade -y erfolgen. Als nächstes installieren wir Python und unsere virtuelle Umgebung, die Heimat unseres Codes, mit dem folgenden Befehl: sudo apt-Get Installieren Sie Python-is-Python3 Python3-Venv Dies ist alles, was Sie benötigen, um mit Django in Bezug auf Software -Installationen in der Ubuntu -Instanz in Gang zu kommen. Für Windows und Linux sollte dies ziemlich einfach sein, aber für Mac möchten Sie möglicherweise eine virtuelle Maschine installieren undLinux drauf mit einer kostenlosen oder bezahlten virtuellen Umgebung wie VirtualBox oder Paralells Desktop und erstellen Sie die obigen Schritte, um eine Ubuntu -Umgebung einzurichten. Ubuntu ist in diesem Fall von entscheidender Bedeutung, da es sich um die Software handelt, auf der die Websites ausgeführt werden, und ermöglicht es ihnen, Websites mit allen oben genannten Software zu hosten. Lassen Sie uns in den Django graben. Wieder in unserem Verzeichnis mit

python -m venv venv # Erstellt die virtuelle Umgebung, in der Code gespeichert wird
source venv/bin/activate # Aktiviert die virtuelle Umgebung
pip install Django
django-admin startproject mysite . # Wo MySite das Projekt ist, das ich in meinem aktuellen Verzeichnis beginne.
Django erhält uns gerade ein, weil Django den Webserver hostet und alles tut, was wir brauchen, um eine grundlegende lokale Website zum Laufen zu bringen. Nachdem wir Django installiert haben, lassen Sie uns die Einstellungen ein wenig bearbeiten, damit es so funktioniert, wie wir es brauchen. Lassen Sie uns zunächst eine neue App erstellen

python manage.py startapp feed
Sie werden bemerken, dass die erste App Feed genannt wird. Die App sollte so genannt werden, was Sie möchten, und wir erstellen neue Apps, aber der Name jeder App muss bei jeder App konsistent sein, wenn die App im Code verwiesen wird. Um eine neue App hinzuzufügen, werden wir immer die Einstellungen in dem anderen Verzeichnis bearbeiten, das die App erstellt hat, die in StartProject, im Folgenden der App genannt wird. Mit Nano,

nano app/settings.py
Finden Sie in den Einstellungen installed_apps und trennen Sie die [] in 3 Zeilen. Fügen Sie "vier Leerplätze in der leeren Mittellinie" "Feed" oder den Namen Ihrer App hinzu. Dieser Abschnitt der Einstellungen.Py sollte aussehen wie:

INSTALLED_APPS = [
    'feed',
]
Bevor wir vergessen, testen wir, dass Django arbeitet. Verwenden des Befehls Python Management.py RunServer 0.0.0.0:8000 können wir den Server ausführen und dann in einem Webbrowser auf dem Computer navigieren, der den Code auf http: // localhost: 8000 ausführt und eine Beispiel -Webseite anzeigen (es funktioniert!) Beenden Sie den Server mit der Kontrolle C, genau wie bei jedem anderen Befehl. Lassen Sie uns nun in das Schreiben von Python -Code eingehen. Django hat drei Hauptkomponenten, die alle vollständig von Code ausgeführt werden. Die Komponenten werden als Modell, Ansicht und Vorlage bezeichnet, und jeweils ist eine höhere bzw. niedrigere Ebene, bevor die Webseite an den Benutzer geliefert wird. Das Modell ist der Code, der Informationen in der Datenbank zum Abrufen, Sortatierung und Rendering speichert. Die Ansicht entscheidet, wie das Modell gerendert, manipuliert und modifiziert wird. Fast jede Ansicht verwendet ein Modell direkt. Die Vorlage ist der HTML -Code mit einigen zusätzlichen Schnickschnack, die als Vorlagesprache bezeichnet werden. Die Vorlage wird durch die Ansicht gerendert, in der sie mit Python -Code gefüllt ist undKontext wie Modelle und Informationen (Usuall -Zeichenfolgen und Ganzzahlen) aus der Sicht. Django hat auch andere Komponenten, einschließlich, aber nicht beschränkt auf: Einstellungen, die die App so konfigurieren, wie wir besprochen haben. URLs, die Muster sind, die der Benutzer folgt, um Zugriff auf bestimmte Teile der Webanwendung zu erhalten. Formulare, die definieren, wie Informationen, die an den Server gesendet werden, sowohl in die Datenbank als auch an den Benutzer behandelt und gerendert werden. Dies sind die Grundlage für die Verarbeitung von Informationen auf der Serverseite und können alle Art von Informationen akzeptieren, die der Computer speichert, vor allem Textzeichenfolgen, Zahlen und True/False Booleans (normalerweise Kontrollkästchen). Vorlagen, die HTML -Code und Vorlagensprache sind und die Lücke zwischen Python und HTML überbrücken. für eine Vielzahl von Zwecken auf einem Remote -Gerät, das dies nicht tuteed, um in der Nähe des Servers zu sein. Statische Dateien, die normalerweise JavaScript und Bibliotheken sind, denen der Server dient und mit der Vorlage verknüpft ist. Mediendateien, die der Server dient oder extern gehostet oder einfach auf den Server geschrieben wird, bevor sie verarbeitet und zum Hosting an einem anderen Server (einem Eimer) veröffentlicht werden. Middleware, Code, die gleichzeitig mit jeder Ansicht ausgeführt werden und in der Ansicht als "enthalten" betrachtet werden. Kontextprozessoren, die den Kontext jeder Ansicht verarbeiten und zum Hinzufügen eines zusätzlichen Kontextes verwendet werden. Tests, die bestätigen, dass der Benutzer oder die Anfrage bestimmte Anforderungen erfolgt, bevor die Ansicht gerendert wird. Verbraucher, die bestimmen, wie Websockets auf Kommunikation umgehen und darauf reagieren. Admin, mit dem Modelle registriert werden, damit sie auf der Django -Administratorseite ausführlich manipuliert werden können, auf der die Datenbank über eine grafische Schnittstelle verwaltet werden kann. Sellerie, der definiert, dass asynchrone Aufgaben Teile des Django -Code beginnen könnenNning, bevor Sie sofort mit der nächsten Aufgabe oder Codezeile fortfahren. Django kann viele andere Komponenten haben, die wir hier ausführlich besprechen werden. Es gibt viele Möglichkeiten, Django funktionaler zu gestalten und Websockets hinzuzufügen, die schnelle, optimierte Kommunikationskanäle, Sellerie, die asynchrone Aufgaben ausführt Der Code wird ausgeführt. Die Ansichtsfunktionen sind der Schlüssel, da sie normalerweise jeden Code deklarieren, der für ein bestimmtes URL -Muster oder einen Abschnitt des Servers spezifisch ist. Lassen Sie uns zunächst Ansichtsfunktionen erkunden. Die Ansichtsfunktionen beginnen mit Importen, die Code bezeichnen, die in der Ansicht verwendet werden, und werden mit regulären Funktionsdefinitionen oder Klassen definiert. Die einfachsten Ansichten werden durch die Funktionsdefinition def definiert und geben eine httPesponse mit einer grundlegenden Vorlage zurück. Beginnen wir zunächst eine grundlegende Ansicht, um den Text „Hello World“ zurückzugeben. Denken Sie daran, dass Sie jedes Mal, wenn Sie hinzufügenWenn Sie eine Aussage wie Def haben, müssen Sie für jede der vorhandenen Definitionen, die Sie auf Ihre Funktion anwenden möchten, 4 Leerzeichen hinzufügen. Wir werden uns bald in das einlassen, was jedes dieser bedeutet. Bearbeiten Sie aus dem Verzeichnis unserer Website die Datei Feed/Views.py mithilfe von Nano und fügen Sie die folgenden Zeilen zum Ende des

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
Djangos httPesponse antwortet mit einer Textzeichenfolge, die mit dem Öffnen und Schließen bezeichnet wird. Jedes Mal, wenn Sie Informationen an eine Funktion oder Klasse wie Anforderung oder eine Zeichenfolge übergeben, müssen Sie Klammern verwenden (, Öffnen und Schließen). Dies ist nicht alles, was wir brauchen, um unsere Ansicht zu sehen. Natürlich haben wir dem Server nicht mitgeteilt, wo die Ansicht genau ist, wir müssen noch einen Pfad definieren, auf dem die Ansicht rendern sollte. Beginnen wir zunächst einen grundlegenden Pfad in App/urls.py, und wir werden später in Pfadgruppen einsteigen. Fügen Sie in App/URLS.PY nach Beginn des Imports der gerade erstellten Ansicht eine Zeile nach den Importanweisungen hinzu.

from feed import views as feed_views
Lassen Sie uns nun das Ansichtsmuster definieren. Die Ansichtsmuster verfügen über drei Komponenten, die Pfadkomponente, die dem Server mitteilt, auf dem die Ansicht auf dem Server vorhanden ist (der URL -Pfad, den der Benutzer in die Navigationsleiste eintippt, um die Webseite einzugeben), die Ansichtskomponente, in der die Ansicht angegeben ist, und a Freundlicher Name für die Ansicht, so dass es einfach ist, das Muster bei der Arbeit mit einer Vorlage abzurufen, insbesondere, sodass der Name geändert und aktualisiert werden kann, um Platz für eine andere Ansicht zu schaffen oder einen logischeren Namen anzunehmen. Es ist sinnvoll, Dinge auf diese Weise zu tun und flexibel zu sein, da Ihre Codebasis eine sich ständig verändernde Umgebung sein wird, die Flexibilität und Improvisation benötigt, um wertvoll und einfach zu arbeiten. So wird Ihre Ansicht aussehen. Sie können dies dem urlpatterns = [Abschnitt der App/urls.py hinzufügen. Das Ansichtsmuster wird mit den drei oben beschriebenen Komponenten und einer Funktion namens Pfad definiert. Ihre URL -Muster sind eine Liste. Beenden Sie also immer jeden Element darinmit einem Komma, weil dies jeden trennt. Jeder Artikel sollte auch eine neue Zeile mit vier Leerplätzen vor sich geben, genau wie die App in Settings.py. Wir definieren die erste Komponente der Ansicht mit einer leeren String -Funktion, um eine Ansicht zu erstellen, die auf dem Stammverzeichnis des Webservers ausgeführt wird. Ihre urls.py sollte jetzt so aussehen wie

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Dies ist die Grundlage für die Erstellung einer Website mit Django, die völlig statisch ist. Um eine dynamischere Website zu erstellen, auf der wir mit dem Zwischenspeichern von Informationen wie Bildern, Videos, Audio und mehr mit dem Caching -Caching -Caching beginnen können, müssen wir Modelle verwenden, die wir als nächstes untersuchen werden. Lassen Sie uns vorerst unseren Code überprüfen und den Server ausführen. Um den Code auf Fehler zu überprüfen, führen Sie aus:

python manage.py check
Wenn es Fehlermeldungen gibt, sollten Sie die Änderungen, die Sie an Ihrer App vorgenommen haben gelöschter Charakter oder irgendetwas anderes. Wenn Sie die Fehlermeldung durchlesen (wenn Sie eine haben), sollten Sie den Pfad zu einer Datei sehen, die Sie zusammen mit einer Zeilennummer erstellt oder bearbeitet haben . Wenn Sie das Problem behoben haben, führen Sie den obigen Befehl erneut aus. Wenn Ihre Software ausgeführt wird und funktioniert, wird die Ausgabe „Systemprüfung keine Probleme“ angezeigt. Jetzt bist du bereit zu gehen. Führen Sie den Server mit: aus:

python manage.py runserver 0.0.0.0:8000
Öffnen Sie nun einen Webbrowser und navigieren Sie zu http: // localhost: 8000. Sie sollten den in der Klammern zurückgegebenen Text und die Zitate der HttPesponse -Funktion in Ihrer Ansicht sehen. Dies ist nur ein grundlegendes Beispiel, aber wenn Sie es so weit geschafft haben, verstehen Sie die Grundlagen, wie Linux, Bash, Python und Django arbeiten. Lassen Sie uns tiefer in eine Datenbankmodellierung eintauchen und die Leistung einer Python -Klasse beim Speichern von Informationen untersuchen. Dann werden wir anfangen, HTML und CSS in den Griff zu bekommen, bevor wir unsere Website mit JavaScript und maschinellem Lernen vollständig, flexibel und sicher machen. Die Klassen werden in den Modellen gespeichert. Py Ihrer App. Verwenden Sie Nano, bearbeiten Sie App/Models.py und fügen Sie eine neue Klasse hinzu. Eine Klasse wird mit der Klassendefinition definiert und wird in einer Superklasse übergeben, von der sie in diesem Fallmodelle.model erbt. Der Name der Klasse erfolgt nach der Klassendefinition, und nach der Klassendefinition a: (colon) wird verwendet, bevor die an die Klasse gebundenen Attribute und Funktionsdefinitionen nachstehend bezeichnet werden. Unsere KlasseBenötigt eine ID, mit der wir sie abrufen und einzigartig halten können. Außerdem benötigt es ein Textfeld, um einige Informationen zu speichern. Später können wir einen Zeitstempel, Dateien, Booleschen (wahre oder falsche Definitionen, die unserem Code helfen können in den Server und mehr. Lassen Sie uns den Code auspacken

from django.db import models # Der Import, der verwendet wird, um unsere Klasse und seine Attribute zu definieren

class Post(models.Model): # Die Definition unserer Klasse selbst
    id = models.AutoField(primary_key=True) # Die ID unseres Modells, ein automatisch generierter Schlüssel, mit dem wir das Modell abfragen, es einzigartig halten und nützlich sind, wenn wir nach dem Erstellen mit dem Modell interagieren müssen.
    text = models.TextField(default='') # Das Attribut unserer Klassenspeicher in diesem Fall ein paar Text, die zu einer leeren Zeichenfolge versetzt sind.
Schließen und speichern Sie die Datei wie zuvor, um fertig zu werden. Es gibt viele andere Felder und Optionen, die wir untersuchen, wenn wir diese Klasse aktualisieren, während sich unsere App weiterentwickelt, aber dies ist die Grundbedürfnisse, eine App zu erstellen, um einen Text zu veröffentlichen. Dieses Modell funktioniert jedoch nicht alleine. Wie bereits beschrieben, benötigen wir eine benutzerdefinierte Ansicht und ein benutzerdefiniertes URL -Muster, damit dieses Modell funktioniert, und wir benötigen auch ein Formular zusammen mit einer Vorlage. Lassen Sie uns zuerst das Formular erkunden. Um ein Formular zu definieren, bearbeiten Sie App/Form.Py mit Nano und fügen Sie die folgenden Zeilen hinzu. Wir benötigen zwei Importe, unsere Formulare -Klasse sowie das von uns erstellte Modell (feed.models.post), eine Klassendefinition, die dem Modell ähnelt, und ein Feld zusammen mit einer Unterklasse namens Meta, die das Modell definiert, das das Formular interagiert mit. Das Formular kann auch eine Initialisierungsfunktion haben, die sie basierend auf Informationen in der Anforderung, dem Modell oder anderweitig festlegt, werden wir dies später untersuchen. Modellformulare sind so nützlich, weil sie ein Modell erstellen oder auch ein Modell bearbeiten können.Also werden wir sie für beide verwenden. Definieren wir einen in forms.py

from django import forms
from feed.models import Post

class PostForm(forms.ModelForm):
    text = forms.CharField(widget=forms.Textarea)
    class Meta:
        model = Post
        fields = ('text',)
Dies sind die Grundlagen, wie eine Form und ein Modell aussehen. Dieses Modellformular kann verwendet werden, um einen Beitrag zu instanziieren oder zu bearbeiten, wodurch der enthält, den er enthält. Wir werden uns mit der Integration dieses Formulars als nächstes in eine Ansicht integrieren. Lassen Sie uns zunächst die Migrationen erstellen und die Datenbank migrieren, damit unser Code beim Ausführen mit dem Modell interagieren kann. Führen Sie dazu die folgenden Befehle aus:

python manage.py makemigrations
python manage.py migrate
Die Ausführung dauert eine Minute, aber sobald dies der Fall ist, können Sie auf das Modell in den Ansichten, in der Middleware oder an einem anderen Ort in der Software zugreifen. Lassen Sie uns fortsetzen, indem wir unser Modell sehen können, wo wir unser Modell sehen können. Bearbeiten Sie Feed/Views.py und fügen Sie den folgenden Code hinzu, wie angegeben. Sie müssen nach dem # Zeichen nichts hinzufügen. Dieser Code ist Kommentare, mit denen Informationen über den Code angegeben werden. Wir werden zunächst unser Modell in den Ansichten importieren und es in einen Kontext hinzufügen, in dem wir es in einer Vorlage als Liste für die Anzeige rendern können. Als nächstes werden wir eine Vorlage hinzufügen, in der wir das Formular und das Modell mit einer Schaltfläche rendern können, um ein neues Objekt basierend auf dem Modell zu erstellen und auf dem Server zu veröffentlichen. Das klingt kompliziert, nehmen wir es also Schritt für Schritt. Bevor wir die Ansicht beenden, erstellen wir eine Vorlage, die das Modell nur rendert, und stellen Sie sicher, dass wir sie sehen können, indem wir einen neuen Beitrag in der Shell erstellen. So sollte diese Ansicht aussehen:

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

def feed(request):
    posts = Post.objects.all() # Fragen Sie alle Beiträge in der Datenbank bisher ab
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })
Das alles sieht ziemlich einfach aus, bis wir nach unten gehen. Render, der von der Funktion zurückgegebene Wert anstelle einer HTTP -Antwort wie im vorherigen Beispiel, nimmt immer eine Anforderung als erste Eingabe an, akzeptiert einen Kontext (in diesem Fall die Beiträge in der Datenbank), die jetzt in der Vorlage gerendert werden können und gibt die in der Funktion definierte Vorlage zurück. Die Vorlage wird ein HTML -Dokument mit einer kleinen Sprache namens Jinja2 sein, die Python -Informationen in die HTML macht. Um Vorlagen zu erstellen, erstellen Sie zwei Verzeichnisse im Feed.

mkdir feed/templates
mkdir feed/templates/feed
Bearbeiten Sie als nächstes eine Vorlage im obigen Verzeichnis, Feed/Vorlagen/Feed und fügen Sie den Code für dieses Beispiel hinzu. Schauen wir uns die Vorlage für dieses Beispiel an.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Dies ist eine sehr einfache Vorlage. Es definiert das Öffnen und Schließen von HTML -Tags, ein Dokumenttyp -Tag, ein Body -Tag mit einem Legenditel, ein Break -Tag, das eine kleine Zeile über den Bildschirm hinzufügt die Vorlage. Dies ist alles, was es braucht, um Beiträge zu rendern, aber es gibt noch keine in der Datenbank. Lassen Sie uns einige mit der Shell erstellen. Wir können die Shell mit Managing.py ausführen

python manage.py shell
Importieren wir jetzt unser Postmodell

from feed.models import Post
Als nächstes erstellen wir einen einfachen Beitrag mit einer Zeichenfolge und beenden wir die Shell. Die Zeichenfolge kann alles sein, solange es ein gültiger Text ist.

Post.objects.create(text='hello world')
exit()
Zuletzt müssen wir unserem Feed ein URL -Muster hinzufügen. Da unsere Feed -App mehrere URLs verwendet und wir Dateigrößen klein halten möchten, erstellen wir eine lokale URLS.Py in unserer Feed -App, die so aussieht:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
Wir müssen auch die URLS.Py in der Basis -App bearbeiten, was auch immer wir uns entschieden haben, dies zu nennen, dies war das erste Verzeichnis, das wir erstellt haben. Bearbeiten Sie App/App.py und fügen Sie den URL -Mustern Folgendes hinzu

from django.urls import include # oben

urlpatterns = [
    # ... vorheriger Code hier
    path('feed/', include(('feed.urls'), namespace='feed')),
]
Wenn wir den Server jetzt mit Python Managing.Py RunServer ausführen, werden wir die Seite sehen, die wir erstellt haben, da wir das Modell, die Ansicht und die Vorlage sowie das URL -Muster sowie Elemente in der Datenbank haben. Lassen Sie uns als nächstes das von uns erstellte Formular implementieren und beginnen unsere eigenen Beiträge. Aber bevor wir zu viel Code schreiben, lassen Sie uns ein Sicherungsback mit dem zuvor geschriebenen Skript erstellen, das wir zuvor geschrieben haben, Backup. Führen Sie dieses Skript in der Shell aus, warten Sie ein paar Momente, und der gesamte Code wird in unserem Git -Repository gesichert.

backup
Die Implementierung des Formulars ist relativ einfach. Wir werden unser Formular importieren, der Ansicht einen Postanforderungs -Handler hinzufügen und den Beitrag in der Datenbank speichern, bevor wir auf dieselbe Ansicht umgeleitet werden. Wir können die von uns bereits importierte Umleitungsfunktion und eine andere Funktion namens Reverse verwenden, um die URL für das Ansichtsmuster zu erhalten. Wir werden dies mit dem String 'Feed: Feed "abfragen, da der Namespace des enthaltenen Musters Feed ist und die Ansicht auch als Feed bezeichnet wird.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Fragen Sie alle Beiträge in der Datenbank bisher ab
    if request.method == 'POST': # Behandeln Sie die Postanfrage ab
        form = PostForm(request.POST) # Erstellen Sie eine Instanz des Formulars und speichern Sie die Daten darauf
        if form.is_valid(): # Validieren Sie das Formular
            form.save() # Speichern Sie das neue Objekt
        return redirect(reverse('feed:feed')) # Umleiten
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # Stellen Sie sicher, dass Sie das Formular in den Kontext geben, damit wir sie rendern können.
        'posts': posts,
    })
Jetzt müssen wir die Vorlage aktualisieren, um das neue Formular zu berücksichtigen. Wir können dies tun, indem wir die verwenden
Tag in HTML und rendert das Formular in der HTML -Vorlage mit einer Schaltfläche Senden. Wir benötigen auch ein CSRF -Token, ein Token, das verhindert, dass externe Websites das Formular veröffentlichen, ohne zuerst eine Seite zu laden.
 
<!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>
 
Lassen Sie uns das niederlassen. Es gibt eine neue Formklasse, ein Token, das Formular selbst und eine Sendetaste. Ziemlich einfach, aber wenn wir es uns ansehen, möchten wir vielleicht besser aussehen. Es funktioniert, wir können neue Beiträge mit dem Formular veröffentlichen und sie werden jetzt in der Datenbank gespeichert. Hier gibt es ein paar Dinge. Wir verwenden HTML -Tags, um zu erklären, dass es sich bei dem Dokument um ein HTML -Dokument handelt. Wir verwenden ein Template -Tag ({ %… %}), um das Token für das Formular zu rendern, und eine andere, {{…}}, um das Formular zu rendern. Wir haben auch eine Schleife, um den Text mit Block -Tags und einem Vorlagen -Tag zu rendern. Block -Tags sind wirklich wichtig, da wir definieren können, wie Abschnitte der Vorlage mit ihnen gerendert werden, und Template -Tags die Grundlage dafür sind, wie wir Variablen in unseren Code einfügen. Jetzt müssen wir unsere App besser aussehen lassen, denn im Moment sieht es wirklich einfach aus. Wir können dies tun, indem wir CSS entweder inline oder in Klassen verwenden, die an jedes Objekt im Dokument gebunden sind. CSS ist wirklich schön, weil es alles auf der Seite sagt, wie es aussehen sollte,Und kann es wirklich gut aussehen lassen. Es gibt ein paar Bibliotheken, die dies tun können, aber mein persönlicher Auftritt ist Bootstrap. Bootstrap kann von ihrer Website heruntergeladen werden.Getbootstrap.com/. Drücken Sie dort die Taste, um die Installationsdokumente zu lesen, und kopieren Sie den Code aus dem Abschnitt CDN aus. Sie benötigen diesen Code oben in Ihrem HTML -Dokument in einem Tag namens Head. Lassen Sie uns außerdem eine Basisvorlage erstellen, damit wir diese Links in jeder Vorlage nicht neu erstellen müssen. Machen Sie ein neues Verzeichnis namens Vorlagen mit MKDIR -Vorlagen und bearbeiten Sie dann Vorlagen/Base.html. Es sollte so aussehen:
 
<!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>
 
Vergewissern Sie sich, dass CSS und JavaScript, die .CSS- und JS -Dateien, da wir das JavaScript benötigen, um unsere Website in Zukunft funktionaler zu machen. Kehren wir nun zur Bash -Shell zurück und führen Sie einen schnellen Befehl aus. Denken Sie daran, wenn Sie jemals auf die virtuelle Umgebung zugreifen müssen, geben Sie Quelle Venv/bin/aktivieren. Auf diese Weise können Sie Python -Pakete lokal so auf eine Weise installieren, mit der Django auf sie zugreifen kann. Um unsere Formulare zu geben, die von Django Bootstrap -Klassen erzeugt werden, werden wir ein Python -Paket namens Crispy Forms verwenden. Wir können dies mit dem folgenden Befehl herunterladen

pip install django-crispy-forms
Sobald dies installiert ist, fügen Sie es zu den Einstellungen hinzu.py

INSTALLED_APPS = [
    # … Vorheriger Code hier
    'crispy_forms',
]
Jetzt, zurück in unserer Feed -Vorlage, können wir einige Dinge entfernen. Entfernen wir den Anfang und Ende des Dokuments und ersetzen Sie es durch die Vererbung aus unserer Basisvorlage unter Verwendung von Erweiterungen und der Blockdefinition. Außerdem werden wir dem Formular einen Vorlagenfilter -Import und einen Vorlagenfilter hinzufügen. Zuletzt fügen wir der Schaltfläche des Formulars eine Bootstrap -Klasse hinzu, damit sie mehr wie eine Taste aussieht. Das sollte so aussehen:
 
{% 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 %}
 
Schön! Das ist schon ein ziemlich viel Code. Als nächstes sollten wir es testen und sicherstellen, dass wir sehen können, dass alles gut aussieht, und sicherstellen, dass alles richtig funktioniert. Führen Sie den Server gemäß den vorherigen Anweisungen aus und stellen Sie sicher, dass die Website in Ordnung aussieht und funktioniert. Toller Job! Sie können mit dem nächsten Schritt fortfahren, in dem wir mit ähnlichen URLs, Formularen, Ansichten und Vorlagen die Benutzeranmeldungsfunktionalität hinzufügen. Die Basisvorlage ist wichtig, und wir werden sie weiterhin ändern und bei Bedarf Änderungen vornehmen. Im Moment konzentrieren wir uns darauf, unsere Site sicherer zu machen, indem wir Benutzern ermöglichen, sich mit einem Benutzernamen und einem Passcode anzumelden und schließlich noch wichtigere Informationen, die Wird Ihre App sicher halten und Ihr eigenes Konto nur von Ihnen zugänglich sein. Dazu müssen wir das in Django integrierte Benutzermodell verwenden. Das Benutzermodell ist ein Datenbankmodell, wie unser Beitrag, das so gerendert werden kann, dass ein Benutzer auf der Website protokolliert wird. Bevor wir die Website im Internet bereitstellen, werden wir in Zukunft werdenErweitern Sie dieses Modell mit anderen ihm zugeschriebenen Modellen und erstellen Sie zusätzliche Sicherheitsmaßnahmen für die Anmeldung, die gegen Phishing resistent sind. Wir werden zunächst einige integrierte Anmeldesformulare verwenden, die Django bereitstellt. Lassen Sie uns zunächst eine neue App erstellen, mit der wir die Vorlagen und Ansichten für die grundlegende Anmeldeseite rendern. Wir werden auch andere Apps erstellen, um die fortgesetzten Anmeldungsherausforderungen darzustellen, um die App zu sichern, einschließlich Pincode, Gesichtserkennung, Nahfeldkommunikation, externe Geräte, Multi -Faktor -Authentifizierung und Fingerabdruckerkennung. Wir haben bereits darüber gesprochen, eine App zu gründen. Aus unserem Verzeichnis, in der virtuellen Umgebung, passieren Sie diese.

python manage.py startapp users
Jetzt sollten wir ein Verzeichnis für die neue App haben. Beginnen wir zunächst eine Ansicht in diesem Verzeichnis, das der Benutzeranmeldung entspricht. Django hat Ansichten für Benutzeranmeldungen eingebaut, diese werden jedoch nicht für uns geeignet, da wir eine benutzerdefinierte Ansicht benötigen, die vorzugsweise mit einer Definition erfolgt. In dieser Ansicht werden wir zunächst nach einer Postanforderung prüfen, die Anfrage übergeben. Posten Sie in ein von Django importierter Anmeldung, authentifizieren das Benutzerkonto und melden Sie sich im Benutzer an, bevor Sie sie in unsere Feed -App umleiten. Fügen Sie in Benutzern/Ansichten.py den folgenden Code hinzu

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'] # Holen Sie sich den Benutzernamen und das Passwort aus der Postanforderung
        password = request.POST['password'] # Authentifizieren den Benutzer
        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()})
Dies ist alles, was Sie für eine grundlegende Anmeldeansicht benötigen. Erstellen wir nun ein Formular für die Ansicht, indem Sie die Basisvorlage erweitern. Wir werden zunächst ein neues Verzeichnis für Vorlagen im Ordner des Benutzer erstellen.

mkdir users/templates
mkdir users/templates/users
Jetzt sollten wir in der Lage sein, Benutzer/Vorlagen/Benutzer/Login.html zu bearbeiten. Während wir dabei sind, erstellen wir eine Vorlage, mit der sich der Benutzer auch anmelden kann.

nano users/templates/users/login.html
Nun in der Vorlage,
 
{% 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 %}
 
Dies sind die Grundlagen einer Anmeldevorlage. Es ist wirklich genau wie die andere Vorlage in der Struktur, aber es sieht ein bisschen anders aus, wenn es gerendert wird. Wir können diesen Code kopieren, um eine andere sehr ähnliche Vorlage namens Register.html zu erstellen, in der wir den Wortlaut ändern und ein neues Formular verwenden, das wir erstellen. Lassen Sie uns zuerst die Vorlage machen. Bearbeiten Sie Benutzer/Vorlagen/Benutzer/Register.html und fügen Sie den folgenden Code hinzu:
 
{% 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 %}
 
Erstellen wir nun ein Formular für unsere Benutzerregistrierung und kreisen zu den Ansichten zurück, bevor wir unsere Benutzeranmeldungen mit einem Modell aktualisieren. Wir werden dieses Formular zunächst grundlegend machen, aber in Zukunft weitere Details und Sicherheitsfunktionen wie Vereinbarungen und Captcha einbeziehen. Bearbeiten Sie die Formulare mit Nano -Benutzern/Forms.py und fügen Sie den folgenden Code hinzu.

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']
Wir haben also hier eine andere Form, die ziemlich einfach funktioniert. Es handelt sich um ein Benutzerregisterformular mit einem Benutzernamen, einer E -Mail und einem Passwort sowie einem Feldbestätigungskennwort. Beachten Sie, dass dieses Formular nicht die reguläre Form.Form -Klasse erweitert, sondern ein Modellformular, was bedeutet, dass es eine Meta hat. Ein Feld ist genauso definiert, und das Klassen -Meta definiert das Modell Das Formular entspricht den restlichen Informationen, die in das Formular geschrieben werden. Das meiste davon existiert bereits in Djangos in der BenutzercreationForm eingebauter Benutzerfunktion. Daher werden wir diese als Grundlage für die Klasse (in der Klammern übergeben) verwenden. Als nächstes werden wir die Ansicht untersuchen, um einen Benutzer zu registrieren, da wir ein Formular und eine Vorlage haben. Dies ist ein Modelform, genau wie der in der neuen Postansicht. Bearbeiten Sie Benutzer/Ansichten.py und fügen Sie den folgenden Code hinzu:

# … Beträge
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})
Dies ist alles, was wir brauchen, um einen Benutzer zu registrieren, aber wir sollten mehr Informationen haben. Wir möchten wissen, wann der Benutzer registriert ist, wann sie zuletzt auf der Website waren, einige Informationen darüber, wie eine Biographie, Zeitzone usw. Außerdem müssen wir unser Feed -Modell aktualisieren, Post, um den Benutzer zu berücksichtigen Modell- und Attributbeiträge für jeden Benutzer. Dazu werden wir die Modelle in beiden Apps aktualisieren. Beginnen wir zunächst das Feed -Modell. Es sollte jetzt so aussehen:

from django.db import models # … Beträge
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') # Fügen Sie in dieser Zeile hinzu
    text = models.TextField(default='')
Achten Sie auf die zweite Zeile, die der Datei hinzugefügt wurde. Dies ist ein Fremdschlüssel, der jeden Beitrag einem einzelnen Benutzer pro Beitrag zuordnet, sodass wir sicherstellen können, dass die Beiträge die Beiträge auf der Basis von Benutzer-per-Benutzer speichern und kein Beitrag vorgenommen werden kann, ohne sie einem Benutzer zuzuordnen. Wir definieren diesen Fremdschlüssel mit der Klasse, die sie darstellt, ein Löschenargument, um sicherzustellen, dass Beiträge mit Benutzern, Null- und leeren Argumenten gelöscht werden, um sicherzustellen Erstellt und ein verwandter Name, mit dem wir uns auf die Postobjekte beziehen können, die der Benutzer erstellt. Dieser verwandte Name gibt uns im Gegensatz zu Post.Author, dem Autor des Beitrags, den Benutzer, der den Beitrag selbst veröffentlicht hat. Wir können jetzt die Beiträge erhalten, die ein Benutzer erstellt, indem wir user.posts.All () oder Author.posts.All () ausführen. Lassen Sie uns nun unsere Anmeldungen widerstandsfähiger machen. Wir können unsere Website bereits für Phishing bereits viel weniger anfällig machen, indem wir einfach die Häufigkeit beschränken, wenn wir uns anmeldung an die Anmeldung zu erlaubenSite, das ist ziemlich einfach. Lassen Sie uns außerdem anfangen, einige Informationen über jeden Benutzer zu speichern, während wir unsere App weiterentwickeln. Bearbeiten von Benutzern/Models.py, fügen Sie Folgendes hinzu

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='')
Beachten Sie, dass dieses Modell dem Postmodell ziemlich ähnlich ist. Wir haben einen zusätzlichen Import, TimeZone, mit dem wir Standardeinstellungen auf den Feldern von DateTime festlegen können, und wir haben auch ein Charakterfeild und ein Textfeld wie den Beitrag. Durch die Verwendung all dieser Zeitstempel können wir die Website sichern und ihre Verwendung verstehen, und in den Textfeldern können wir Informationen über jeden Benutzer oder Autor auf der Website rendern. Das OnetooneField sollte die einzige geringfügige Überlegung sein, es verhält sich genauso wie ein Vorginkey, jedoch nur ein professionelles Modell. Auf diese Weise hat der Benutzer nur ein Profil, während er möglicherweise viele Beiträge hat. Lassen Sie uns nun unsere Login- und Registrierungsansichten verbessern, um das Profil zu berücksichtigen. Bearbeiten Sie zunächst Benutzer/Ansichten.py und konzentrieren Sie sich auf die Registeransicht:

# … Beträge
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) # Stellen Sie sicher, dass Sie diese Zeile hinzufügen, um ein Profil für den Benutzer zu erstellen
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Dadurch wird einfach ein Profil für den Benutzer erstellt, ohne die Informationen einzufüllen. Jetzt möchten wir sicherstellen, dass das Benutzerkonto nicht zu oft angemeldet werden kann oder zumindest Passwörter nicht zu oft ausprobiert werden können. Aktualisieren wir also die Anmeldeansicht.

# … Beträge
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(): # Beachten Sie, dass wir jetzt überprüfen, ob sich der Benutzer anmelden kann
            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: # Wenn der Login nicht erfolgreich war,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Dies ist der Teil, in dem wir das Benutzerprofil aktualisieren
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Sie können sich also einige Sekunden lang nicht wieder anmelden
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Dies ist die grundlegende grundlegende Sicherheit. Stellen Sie sicher, dass die Site für jemanden nicht anfällig ist, der einfach jede mögliche Passwort -Kombination oder sogar einige von ihnen gleichzeitig ausprobiert. Dies wird für den gewöhnlichen Benutzer, der seinen Passcode kennt, nicht frustrierend sein und sich nur auf ein paar Geräte anmeldet, aber es wird zahlreiche Phishing -Roboter aus der App fernhalten. Beachten Sie, dass wir eine IF -Anweisung mit einer Variablen hinzugefügt haben, CAN_LOGIN, die in der Vergangenheit eine Zeit dauern sollte, und sie mit jedem erfolglosen Login mit demselben Benutzernamen aktualisieren. Auf diese Weise kann ein böswilliger Benutzer ein Passwort annähernd so schnell erraten. Die Anzahl der Sekunden in der DateTime.Timedelta () kann ebenfalls aktualisiert werden, und die Website wird mit mehr Sekunden widerstandsfähiger und weniger verwendbarer sein. Ich empfehle 15, mit zu beginnen. Denken Sie daran, wir haben ein Backup -Skript gebaut, um unsere Arbeit zu retten. Führen Sie den Befehl aus:

sudo backup
Dies speichert Ihre Arbeit noch einmal bisher. Ich empfehle, häufige Backups auszuführen, um Ihre Arbeit zu speichern, und Sie möchten möglicherweise sogar einen Backup -Job automatisch ausführen. Sie können dies mit einem UNIX -Dienstprogramm namens Cron tun. Führen Sie den folgenden Befehl aus und geben Sie Ihr Passwort ein:

sudo crontab -e
Wenn Sie Option 1 für Nano noch nicht ausgewählt haben, sollten Sie den Texteditor, mit dem Sie bereits vertraut sein sollten, und scrollen Sie mit den Pfeiltasten zum Ende der Datei. Fügen Sie die folgende Zeile hinzu:

0 * * * * sudo backup
Cron verwendet die Formatminute, die Stunde, den Tag des Monats, den Monat, einen Tag der Woche, an dem eine * oder eine Zahl darstellt, wann der Befehl ausgeführt werden soll. Mit einer 0 für die Minute und * für den Rest der Optionen können wir in der ersten Minute jeder Stunde zu Beginn der Minute einen Befehl ausführen. Dadurch können wir den Code automatisch unterstützen. Alle Jobs von Cron, wenn sie mit sudo als root ausgeführt werden, müssen wir nicht jede Stunde ein Passwort eingeben. Um unseren Code zu sichern, ohne ein Passwort zu verwenden, deaktivieren wir das Passwort für unseren Sicherungsbefehl. Wir werden dies tun, indem wir den folgenden Befehl ausführen und ein Passwort eingeben:

sudo visudo
Lassen Sie uns nun zum Ende der Datei scrollen und eine weitere Zeile hinzufügen:

ALL ALL=NOPASSWD: /bin/backup
Auf diese Weise können wir den Befehl "Backup" als Benutzer ohne Passwort ausführen. Das Format dafür ist einfach. Präfix einfach die Linie mit "All = Nopasswd:/bin/" und enden Sie den Befehl, beispielsweise/bin/backup, der in/usr/bin/existiert. Beginnen wir nun mit der Arbeit mit E -Mail. E -Mails ist für Websites sehr wichtig, da dies eine Möglichkeit ist, eine Website sicherer zu halten, Benutzer echte Personen sind und sogar Produkte oder Dienstleistungen für Kunden zu vermarkten. Viele Personen, die das Internet häufig besuchen, überprüfen ihre E -Mail -E -Mails täglich und erhalten alle möglichen Marketing -E -Mails über Produkte und Dienstleistungen, an denen sie interessiert sind. Es gibt einige Optionen, wenn es darum geht, E -Mails auf einer Django -Website zu aktivieren, und Sie können gerne auswählen Was auch immer für Sie am besten funktioniert. Zunächst können Sie einen E -Mail -Dienst bezahlen, mit dem Sie E -Mails von Ihrer Domain senden können, und benötigt nur einen minimalen Code. Es gibt viele Dienste, die dies anbieten, wie Google Workspace, SendInblue, Mailgun und mehr. Ansonsten sind Sie gut abgebautIhr eigener E -Mail -Dienst in Ihrem Server von Grund auf neu. Ich empfehle diese Option, obwohl es mehr Code ist und möglicherweise ein spezielles Hosting erfordert. Sie können einen Mailserver nicht höchstwahrscheinlich von Ihrem Heimcomputer aus starten. Lassen Sie uns also die Konfiguration und den Code untersuchen, um E -Mails zu senden, bevor wir einen Server in der Cloud starten und unseren eigenen Mailserver in sich erstellen. Bearbeiten Sie zunächst die Einstellungen.Py mit den folgenden

nano app/settings.py
Wobei die App der Name der App ist, die Sie mit StartApp erstellt haben. Fügen Sie die folgenden Zeilen hinzu:

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)
Stellen Sie sicher, dass Sie diese ändern, wenn Sie bereit sind, Ihre App bereitzustellen. Wir werden dies später noch einmal besuchen. Die Einstellung von E -Mail_Address sollte die E -Mail sein, aus der Sie senden möchten, und das Kennwort (E -Mail_host_password) sollte auf das Passwort festgelegt werden, das Sie für den Server generieren. Ich lade das Kennwort von einer Konfigurationsdatei ein, um es mithilfe der folgenden Logik über diesen Zeilen in Einstellungen aus dem Code herauszuhalten. PY:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Dann habe ich eine JSON -Datei mit der Konfiguration in /etc/config.json mit Nano wie folgt eingerichtet. So bearbeiten Sie die Datei:

sudo nano /etc/config.json
Fügen Sie die folgenden Zeilen hinzu:

{
	“EMAIL_HOST_PASSWORD”: “<some password here>”
}
Wir werden die Konfigurationsdatei weiter bearbeiten und alle Passwörter und Schlüssel hinzufügen, die wir in der App verwenden. Lassen Sie uns vorerst schnell untersuchen, wie Sie E -Mails mit Python senden. Lassen Sie uns zunächst eine Vorlage für eine Überprüfungs -E -Mail erstellen, die wir an unsere Benutzer senden können, und sie in das Verzeichnis der Benutzervorlagen einfügen. Diese Vorlage wird in HTML geschrieben.

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>
 
Diese E -Mail ist ziemlich einfach. Es nimmt einen Kontext eines Benutzers, der Basis -URL für die Website und einer Benutzer -ID und Token verwendet, mit denen die E -Mail des Benutzers überprüft wird. Stellen Sie sicher, dass Sie die Basis -URL in Einstellungen definieren. Fügen Sie die folgenden Zeilen zu Apps/Settings.py am Anfang hinzu.

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

BASE_URL = PROTOCOL + '://' + DOMAIN
Wenn Ihre Website für das Internet bereit ist und Sie es bereitstellen, möchten Sie Ihre Domain als Domain -Namen definieren, die Sie kaufen, um die Website darzustellen. Dies ist der Name, den Sie in der Navigationsleiste eingeben, um auf Ihre Website zuzugreifen. Im Moment können Sie die Domain leer lassen oder einen Platzhalter verwenden. Sie möchten auch den Site_NAME in einen Namen ändern, den Sie Ihrer Website und Ihrer Wahl geben möchten. Bevor wir E -Mails senden, erstellen wir einen Token -Generator, damit wir ein Kontoaktivierungs -Token haben können, das niemals abläuft. Wir können dies tun, indem wir ein Kontoaktivierungs -Token erstellen und importieren, das wie folgt aussieht. Bearbeiten Sie die Datei:

nano users/tokens.py
Fügen Sie den folgenden Code hinzu:

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()
Dieser grundlegende Token -Generator generiert ein Token. Wir können den Benutzer in einer URL senden, und der Benutzer kann die E -Mail überprüfen und sein Konto aktivieren. Lassen Sie uns als nächstes sehen, wie Sie eine E -Mail senden. Bearbeiten Sie Benutzer/E -Mail.py mit Nano.

nano users/email.py
Das Senden der HTML -E -Mail der Überprüfung sieht folgt aus:

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)
Das ist ziemlich einfach. Wir importieren die Funktionen, die wir die E -Mail senden müssen, die E -Mail mit Vorlagen und unsere Einstellungen abgeben. Anschließend definieren wir die E -Mail mit dem Vorlagennamen und senden sie mit einer Funktion an den Benutzer. Sie werden feststellen, dass wir die Funktion nicht definiert haben, um die E -Mails zu senden, send_html_email. Schreiben wir diese also unter dem Code, den wir bereits zu Benutzern/E -Mails hinzugefügt haben.

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()
Dies ist etwas komplexer und wir sind noch nicht bereit, all diesen Code auszuführen. Beachten Sie, dass wir einen UNSUB_LINK definieren. Der Link, den der Benutzer verwenden kann, um sich von unseren E -Mails abzumelden. Dies ist wichtig, da Benutzer in der Lage sein müssen, unsere E -Mails abzuwenden, es sei denn, sie möchten sie jederzeit sehen. Wir fügen auch eine Textalternative zu unserer Nachricht hinzu, nämlich die HTML -Nachricht, die von HTML -Tags entzogen ist. Zuletzt überprüfen wir, ob die E -Mail gesendet wird, und wenn dies nicht der Fall war, markieren wir im Profil des Benutzers, dass ihre E -Mail nicht gültig ist. Kehren wir zu den Benutzermodellen zurück, damit wir dies alles funktionieren können. Wir müssen eine Funktion definieren, um einen Link zum Abbestellen zu generieren und ein boolesches Feld zu definieren, um zu markieren, dass die E -Mail des Benutzers nicht gültig ist. Fügen Sie zunächst die folgenden Importe an die Spitze von Benutzern/Modellen hinzu.py

nano users/models.py

# …
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
Fügen wir als nächstes Funktionen zum Benutzermodell hinzu, um das Token zu erstellen und das Token zu überprüfen, mit dem die E -Mail aktiviert wird, sowie das Feld, um zu speichern, ob der Benutzer erfolgreich seine E -Mail empfängt. In user/models.py erneut den folgenden Code zum Ende des Modells (eingerateter Code) hinzufügen

# …
    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 Tage gültig
        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,})
Dies ist ziemlich einfach, wir verwenden einen Timestampsigner, bei dem es sich um ein grundlegendes Kryptographie -Tool handelt, um ein Token zu erstellen, das nach einer bestimmten Zeit ablauft, und wir verwenden auch eine andere Funktion, um zu überprüfen, ob es gültig ist. Wir verwenden diese Token zweimal, einmal, um die E -Mail zu überprüfen, und einmal für einen Link zum Abbestellen. Nachdem wir diese haben, ist der letzte der Arbeiten, die wir tun müssen, in den Ansichten. Fügen wir innerhalb von Benutzern/Ansichten.py Ansichten hinzu, um die E -Mail -Adresse zu überprüfen und sich abzumelden.

nano users/views.py
Fügen Sie zunächst die folgenden Importe hinzu. Ich habe ein paar Extra eingeworfen, damit wir später nicht mehr Artikel importieren müssen.

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 # Stellen Sie sicher
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
Möglicherweise haben Sie bereits einige dieser Importe, aber es tut nicht weh, sie zu wiederholen. Sie müssen unter anderem die Funktion zur Sendefunktion der Überprüfung von E -Mail -Sendungsfunktion sowie Account_Activation_Token importieren. Fügen Sie nun am Ende der Datei den folgenden Code hinzu:

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)):
        # melden Sie sie ab
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    # Andernfalls leiten Sie die Anmeldeseite um
    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()
# sendWelcomeMail (Anfrage, Benutzer)
        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})
Dies ist viel Code. Lass es uns zusammenbrechen. Die erste Funktion, sauber und einfach, beschreibt den Benutzer aus der Mailingliste. Die zweite Funktion aktiviert ihre E -Mail und Sie werden feststellen, dass ich eine kommentierte Funktion hinzugefügt habe, sendWelcomeMail. Sie können gerne eine E -Mail -Vorlage und Funktionsdefinition verwenden, um eine willkommene E -Mail zu senden. Die letzte Funktion, die ich geworfen habe, ist wichtig, da Aktivierungs -E -Mails ablaufen. Daher müssen wir die Aktivierungs -E -Mail einige Zeit wiedergeben. Wir können dafür ein grundlegendes Formular verwenden und die Funktion aufrufen, um die Überprüfungs -E -Mail zu senden. Bevor wir dies tun, stellen wir sicher, dass es an erster Stelle gesendet wird, indem wir der Registeransicht einen Funktionsaufruf hinzufügen. Fügen Sie diese Zeile kurz vor der Umleitung in der Registeransicht, Def Register, in Benutzern/Views.py hinzu.

nano users/views.py

# … (Nach) Def Register (Anfrage):
            send_verification_email(user)
# … (Vor) umleiten (
Sie müssen die ersten und letzten Zeilen in diesem Code -Snippet nicht hinzufügen. Stellen Sie einfach sicher, dass die Registeransicht die Überprüfungs -E -Mail an den Benutzer sendet. Es sollte so aussehen:

# … Beträge
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) # Stellen Sie sicher, dass Sie diese Zeile hinzufügen!
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Jetzt müssen wir ein Formular hinzufügen, um die Aktivierungs -E -Mail wiederzugeben. Fügen Sie in Benutzern/Forms.Py das folgende Formular hinzu:

# … (Beträge)
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)
Wir benötigen auch eine Vorlage, die diesem Wiederherstellungsformular für das E -Mail -Aktivierungsformular entspricht. Fügen wir diese Vorlage hinzu. Bearbeiten Sie die Datei:

nano users/templates/users/resend_activation.html
Fügen Sie als nächstes den folgenden Code zur Datei hinzu.

{% 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 %}
Puh, das ist viel! Wenn wir den Code nun auf unserem Server bereitstellen, können wir HTML -E -Mails senden und Benutzerkonten mit einem Klick in die E -Mail aktivieren. Möglicherweise möchten wir auch eine einfache Begrüßungs -E -Mail senden. Lassen Sie uns also sehen, wie das geht. Fügen Sie in Benutzern/E -Mail.py den folgenden Code hinzu:

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)
Außerdem benötigen wir eine Vorlage, um alle diese Informationen zu rendern. Auf meiner Website sieht die Vorlage nach unten aus, aber Sie können sie gerne formatieren, wie Sie möchten.
 
<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>
 
Beachten Sie, dass wir keine Schließkörper- oder HTML -Tags haben, da wir diese hinzufügen, wenn wir den HTML -Link zum Abbestellen hinzufügen. Diese sind wichtig, aber wir wollen sie nicht zweimal definieren. Also, was kommt als nächstes? Wir haben einen langen Weg zurückgelegt. Wirklich, wir sollten bereit sein, die Site auf einem Server bereitzustellen. Wir können den Dekorator @Login_Required hinzufügen und unsere Ansichten sicher machen, Benutzeranmeldungen mitnehmen, konforme E -Mails senden und Informationen haben, was die Grundlage dafür ist, was eine Website tun muss, um relevant zu bleiben. Wir fügen ein paar weitere nützliche Funktionen hinzu und erstellen dann eine Grundlage für die Bereitstellung unseres Codes auf einem Remote -Server, ein E -Mail -Server, eine Domänenkonfiguration und Filter, um unsere Website zu sichern und angemessen zu gestalten. Wir werden auch eine Passwort -Reset -Ansicht benötigen. Fügen wir das also sehr schnell hinzu. Djangos integrierte Passwort -Reset -Ansicht ist in einigen Funktionen unterbrochen. Wir werden uns jedoch ansehen, wie Sie unsere eigene Ansicht, E -Mail -Vorlage, Formulare und URL -Muster schreiben. So sieht die Ansicht in Benutzern/Ansichten.py aus

# ... Beträge
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)
Dieses Formular ist in Django integriert. Wir benötigen jedoch eine Vorlage, um das Zurücksetzen des Kennworts zu bestätigen.
 
{% 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 %}
 
Wir haben außerdem eine Vorlage zum Senden einer E -Mail mit Kennwort -Zurücksetzen mit einem einfachen Formular in Benutzern/Vorlagen/Benutzer/password_reset.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Request Password Reset</button>
            </div>
        </form>
{% endblock content %}
 
Die Vorlage für die E -Mail selbst ist einfach. Es handelt sich um eine grundlegende HTML -Datei, die einen Link zum Zurücksetzen des Kennworts in den Benutzern/Vorlagen/Benutzern/password_reset_email.html richtet. Django interpretiert diese Datei automatisch.
 
<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>
 
Wir werden auch zwei weitere Vorlagen brauchen. Die erste besteht darin, zu bestätigen, dass die E -Mail gesendet wurde. Ansichten für diese sind bereits in Django, daher müssen wir sie nur in der URLS.Py ansprechen. Diese Vorlage befindet sich bei Benutzern/Vorlagen/Benutzer/password_reset_done.html
 
{% extends 'base.html' %}
{% block content %}
  <div class="media-body">
    <div class="alert alert-info">
        An email has been sent with instructions to reset your password.
    </div>
  </div>
{% endblock content %}
 
Und schließlich zu bestätigen, dass das Kennwortreset vollständig ist, Benutzer/Vorlagen/Benutzer/password_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 %}
 
Jetzt brauchen wir URL -Muster für diese Ansichten. Fügen Sie in Benutzern/URLs.py die folgenden URL -Muster hinzu:

urlpatterns = [
    # ... vorherige URLs hier
    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'),
]
Vier Vorlagen, das ist viel! Jetzt können wir jedoch sicher sein, dass wir das Kennwort des Benutzers jederzeit aus dem Webbrowser zurücksetzen können. Ich verstehe, dass dies viel Code ist. Wenn es ein bisschen über deinem Kopf scheint, ist das in Ordnung. Sie werden sich verbessern, Ihr Verständnis wird sich verbessern und Sie werden sehr bald viel kompetenter werden. Wenn Sie total verloren sind, empfehle ich, später auf diese Software zurückzukehren, nachdem Sie an einem selbstverständlichen Lernen gearbeitet haben, online zu codieren. Diese können in der Regel anfangen und führen Sie durch alles, was Sie benötigen, um erfolgreich zu sein, wenn Sie zu diesem Projekt zurückkehren. Wenn Sie das Gefühl haben, dass Sie bereit sind, weiterzumachen, weiterzulesen. Als nächst Ein paar einfache Befehle. Das Letzte, was wir tun müssen, bevor wir auf einem Remote -Server bereitgestellt werden, ist, unsere Website ein bisschen sicherer zu machen. Du wirstBeachten Sie, dass die Anmeldeansicht nur einen Benutzernamen und ein Passwort enthält und keine Mehrfaktor -Authentifizierung oder einmalige Code vorliegt. Dies ist eine einfache Behebung, und mit demselben Code können wir unsere Website Textnachrichten senden und sogar auf Textnachrichten reagieren, die an den Server gesendet werden. Zunächst werden wir in die Benutzermodelle zurückkehren und einen Zeitstempelunterzeichner hinzufügen, der jede Anmeldung darstellt. Wir werden dem Benutzermodell auch eine eindeutige, rotierende Kennung hinzufügen, mit der unser Anmeldung zusätzliche Sicherheit hinzufügen wird. Bearbeiten der Benutzermodelle, Benutzer/Modelle.py, fügen Sie Folgendes hinzu

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# Stellen Sie sicher, dass Sie den UUID, den Zeitstempel -Unterzeichner und den URL -Generator (umgekehrt) importieren (umgekehrt).
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='')
    # Fügen Sie diesen Code hier hinzu
    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)

    # Und fügen Sie diese Funktion hinzu
    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) # Gültig für 3 Minuten
        except (BadSignature, SignatureExpired):
            return False
        return True
Stellen Sie sicher, dass Ihre Benutzer/Modelle wie dies so aussehen, neben den Kommentaren (Code in den Zeilen mit #). Das ist einfach. Wir haben ein paar Importe, einen Zeitstempelschalter, der ein kryptografisches Dienstprogramm ist, das einen sicheren Code generieren und diese überprüfen kann, um sicherzustellen, dass er gültig ist, nur einmal verwendet und nicht älter als eine bestimmte Anzahl von Sekunden. Wir verwenden auch eine UUID, eine eindeutige Kennung, die unseren Benutzer bei der Unterzeichnung des Tokens und in der URL, an der das Token an den Benutzer gesendet wird, identifiziert. Wir werden diese grundlegende Kryptographie verwenden, um eine Zwei -Faktor -Authentifizierungsansicht zu erstellen. Bevor wir etwas anderes tun, führen wir die Migrationen aus, damit unsere Benutzermodelle aktualisiert werden. Führen Sie im Verzeichnis mit Manager.py die folgenden Befehle aus, um die Migrationen zu erstellen und zu vervollständigen.

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Dies ist wichtig, da jedes Mal, wenn wir Änderungen an den Modellen vornehmen, die Tabellen erstellen und die Datenbank mit Standardeinstellungen aktualisieren müssen, bevor wir die Modelle tatsächlich verwenden können. Lassen Sie uns als nächstes unsere Anmeldeansicht improvisieren, um zu einer sekundären Authentifizierungsansicht umzuleiten. Entfernen Sie in den Benutzern/Ansichten.py die Anmeldemittel und leiten Sie sie in die URL um, die wir gerade in den Benutzermodellen generiert haben.

# … Beträge

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(): # Beachten Sie, dass wir jetzt überprüfen, ob sich der Benutzer anmelden kann
            # Entfernen Sie die Funktion des Auth_logins, die hier war
            messages.success(request, 'Your password was accepted. Please continue.')
            if user.profile.mfa_enabled:
                return redirect(user.profile.create_auth_url()) # Beachten Sie, dass wir hier zu einer neuen URL umgeleitet werden
            else: # Wenn der Benutzer keine Multi-Faktor-Authentifizierung verwendet, melden Sie sich einfach an.
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # Wenn der Login nicht erfolgreich war,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Dies ist der Teil, in dem wir das Benutzerprofil aktualisieren
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Sie können sich also einige Sekunden lang nicht wieder anmelden
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Das ist also ziemlich einfach, wir haben jetzt eine Möglichkeit, die Ansicht der beiden Faktorauthentifizierung zu leiten, wenn wir sie erstellen. Wir haben auch einen Fallback, falls der Benutzer keine Telefonnummer hinzugefügt hat. Wir werden eine grundlegende Ansicht hinzufügen, um bald eine Telefonnummer hinzuzufügen und sich bald mit einer Textnachricht anzumelden. Erstens brauchen wir eine einfache Möglichkeit, eine SMS von unserem Code zu senden. Dazu können wir aus einer Reihe von APIs auswählen, aber meiner Meinung nach ist das Twilio. Sie bieten auch gute Preise für kleinere Projekte sowie massenhafte Rabatte. Erstellen Sie ein Konto auf Twilio.com, geben Sie einige Details zu Ihrem Projekt aus, kaufen Sie eine Telefonnummer und kopieren Sie Ihre API -Schlüssel in Ihre Einstellungen. Fügen Sie diesen Code dann unter eine neue Datei hinzu, Benutzer/sms.py.

nano users/sms.py

# Importieren Sie alle erforderlichen Pakete
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

# Dieser Code sendet den Text mit Twilio
def send_text(target_phone, text):
    from twilio.rest import Client
    try:
        client = Client(account_sid, auth_token)
        if len(target_phone) >= 11:
            message = client.messages.create(
                to=target_phone,
                from_=source_phone,
                body=text)
    except:
        print(traceback.format_exc())

# Eine Helferfunktion, um eine Zahl mit so vielen Ziffern zu erhalten
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# Senden Sie den Text, um den Benutzer zu überprüfen
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)))

# Senden Sie einem Benutzer einen Text mit dieser Funktion
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# Validieren Sie den Code mit dieser Funktion
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

# Validieren Sie die Zeit
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
Ändern Sie Ihre Einstellungen angemessen und fügen Sie diese Zeilen mit Ihren Schlüsseln hinzu:

# Stellen Sie sicher, dass Sie diese aus Ihrem Twilio Dashboard kopieren
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 # Die Anzahl der Minuten Die TFA -Seite ist aktiv
Erstens benötigen wir Formulare für unsere zwei Faktorauthentifizierungsansichten. Bearbeiten von Benutzern/Form.Py Fügen Sie den folgenden Code hinzu.

# … Beträge
from django import forms

# Ein Formular zum Eingeben unserer Telefonnummer
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

# Eine Form zur Authentifizierung
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.'
    }
Erstellen wir als nächstes die Ansichten in Benutzern/Ansichten.py

# … Beträge
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})
Wir werden auch Vorlagen für diese beiden Ansichten benötigen. Fügen wir zuerst die MFA -Vorlage hinzu.

nano users/templates/users/mfa.html
Fügen Sie diesen HTML -Code der Vorlage hinzu
 
{% 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 %}
 
Dies ist ziemlich selbsterklärend. Das Formular sendet entweder einen Code oder einen leeren Code, und Sie werden in der Ansicht feststellen, dass wir den Code senden, wenn wir einen leeren Code erhalten. Dann haben wir nur zwei Sendentasten, und auf diese Weise können wir den Code mit beiden Tasten senden. Als nächstes fügen wir ein einfaches Formular hinzu, um eine Telefonnummer hinzuzufügen.

nano users/templates/users/mfa_onboarding.html
Fügen Sie die folgenden HTML hinzu:
 
{% 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 %}
 
Dieses Formular ist viel einfacher, es macht nur das von uns erstellte Telefonnummer -Formular und lässt den Benutzer eine Telefonnummer hinzufügen. Das sieht wirklich gut aus! Solange alles ordnungsgemäß eingerichtet ist, sollten wir in der Lage sein, Nachrichten zu senden und den Benutzer mit seiner Telefonnummer zu protokollieren, sobald wir die URL -Muster hinzufügen. Das Letzte, was wir einrichten müssen, ist eine Profilansicht, damit wir sicherstellen können, dass der Benutzer seine Telefonnummer ändern kann, ohne angemeldet zu sein "Stoppen Sie", um sich von zukünftigen Textnachrichten zu entscheiden. Fügen wir den Benutzern/Ansichten.Py eine Profilansicht hinzu. Diese Ansicht aktualisiert die Bio-, E -Mail-, Benutzername und Telefonnummer des Benutzers sowie die Multi -Faktor -Authentifizierung. Erstens benötigen wir zwei weitere Formulare in Benutzern/Forms.py

# ... Beträge
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']
Als nächstes können wir eine Ansicht erstellen, um diese beiden Formen zu verwenden. Bearbeiten Sie Benutzer/Ansichten.py und fügen Sie die Ansicht hinzu.

# Fügen Sie diese Importe hinzu
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)
Wir werden auch eine Vorlage für diese Ansicht benötigen.

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 %}
 
Sie werden feststellen, dass dies eine ziemlich einfache Form ist, aber ein JavaScript enthält, das den Inhalt des Formulars automatisch veröffentlicht, sobald sie aktualisiert werden. Dies ist nützlich zu haben, sodass Sie Änderungen vornehmen können, ohne jedes Mal die Einreichung einreichen zu müssen. Als nächstes brauchen wir URLs, die all diese Ansichten in den URL -Mustern der Benutzer darstellen. Bearbeiten Sie Benutzer/URLs.py und fügen Sie diesen Code hinzu:

# … Vorheriger Code, Importe
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
# … URL -Muster, die wir zuvor eingegeben haben, fügen Sie die nächsten drei Zeilen hinzu
    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'),
]
Jetzt ist ein guter Zeitpunkt, um unser Projekt zu testen. Aber zuerst führen wir ein weiteres Backup durch.

backup
Und führen Sie den Server aus. Bevor wir uns auf einem Linux -Server bereitstellen, ist es eine gute Idee, zwei Faktorauthentifizierung auf dem Konto zu aktivieren. Wir werden dies tun, um unsere Profil -URL,/Benutzer/Profil/Profil/zu überprüfen und das Kontrollkästchen zu überprüfen, um die Authentifizierung nach Eingabe unserer Telefonnummer zu aktivieren und dann das Formular einzureichen.

python manage.py runserver localhost:8000
Besuchen Sie die Webseite, indem Sie zu Ihrem Webbrowser gehen. Ich verwende Google Chrome in diesem Beispiel und geben Sie die URL https: // localhost: 8000/Accounts/Profil/ein. Sie können sich bei Bedarf anmelden und zwei Faktorauthentifizierungen aktivieren. Dieses Projekt benötigt einen Server zum Ausführen, damit es wirklich Mail senden kann. Aber zuerst brauchen wir eine Möglichkeit, Fehler zu erkennen. Wenn Sie den Server im Debug -Modus ausführen, werden die Server automatisch angezeigt, wenn Sie den Server im Debug -Modus ausführen. Um Fehler zu zeigen, ohne den Debug -Modus zu verwenden, der auf einem Produktionsserver unsicher ist, sollten wir eine Ansicht dafür hinzufügen. Die wichtigsten Fehler, die wir benötigen, um behandeln zu können, sind: Fehler 500 - Ein Problem mit unserem Code Fehler 404 - Eine Seite, die nicht gefunden wurde (zerbrochene URL) Fehler 403 - Eine Erlaubnis verweigert Fehler Fügen wir eine neue App hinzu, um diese Fehler zu behandeln, die als Fehler bezeichnet werden.

python manage.py startapp errors
Fügen Sie dies in die Einstellungen hinzu, wie wir es zuvor in der Einstellung installed_apps getan haben, und fügen Sie zunächst Verweise auf einige Ansichten in App/URLS.PY hinzu, wobei die App der Name Ihres Django -Projekts ist.

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
Dies ist alles, was wir neben Fehleransichten, Vorlagen und ein wenig Middleware brauchen. Definieren wir diese als SO:

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

# Erstellen Sie hier Ihre Ansichten.
@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.'})
Lassen Sie uns als nächstes die Middleware definieren, um diese Fehler zu behandeln. Wir werden dies tun, indem wir zuerst zu Middleware_classes in Settings.py mit dem Namen unserer Middleware hinzugefügt werden.

MIDDLEWARE_CLASSES = [
    # ... vorherige Middleware
    'errors.middleware.ExceptionVerboseMiddleware,
]
Als nächstes fügen wir die Middleware hinzu.

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.')
Wir fügen eine Funktion hinzu, um die aktuelle Ausnahme zu erhalten, indem wir einen Threading -Lokal verwenden, der uns hilft, Fehler in unserem Code zu verfolgen. In Bezug auf Vorlagen brauchen wir nur einen, da wir den Titel in der Ansicht dynamisch definieren. Die Vorlage muss nur den Titel und den „Trace“, unseren Fehlerverzeichnis aus dem Kontext, rendern.

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
Dies ist unsere bisher einfachste Vorlage, aber so einfach ist es, die Fehler in unserem Projekt zu erkennen. Lassen Sie uns als nächstes Debugg in Einstellungen deaktivieren.

nano app/settings.py
Finden Sie diese Zeile, in der sie auf wahr eingestellt ist, und ändern Sie sie in False

DEBUG = False
Gehen Sie jetzt die App. Wir sind bereit, auf einem Remote -Linux -Server bereitzustellen und von dort aus Funktionen hinzuzufügen.

sudo backup
Bevor wir diesen Code auf einem Server veröffentlichen, sollten wir in Betracht ziehen, dass es einige Probleme mit dem Code geben kann. Abhängig von dem Fall werden Websites, die an sie veröffentlichte Informationen akzeptieren, Probleme haben, wenn Spam veröffentlicht wird und die Spam -Entfernung von Schwierigkeiten wird. Dies sollte nicht sofort passieren, aber wenn es geschieht, werden wir später untersuchen Ein Scan ihrer ID oder ein biometrischer Scan wie ein Fingerabdruck oder eine Gesichtserkennung. Betrachtet man das Multi -Faktor -Authentifizierungsbeispiel, das wir in der Produktion untersuchten, können unterschiedlich sein. Beachten Sie, wie wir Ratenbegrenzungsanmeldungen und ablaufende Token sind. Wenn Roboter auf eine Site zugreifen, kann die Zwei -Faktor -Authentifizierung schwieriger sein, da sie gleichzeitig Codes eingeben können. Um dies zu bekämpfen, verwenden wir ein Modell in den Benutzermodellen und erklären, wie wir mit der Website interagieren, wenn wir sindAuthentifizierung mithilfe der Multi -Faktor -Authentifizierung mit einer Telefonnummer. Wir werden auch eine Option zum Authentifizieren mit E -Mail hinzufügen. Bearbeiten Sie zunächst die Benutzermodelle mit

nano users/models.py
So sollte das Modell, das wir hinzufügen, aussehen. Wir benötigen keine Methoden, nur Variablen, um eine ID zu speichern, den Benutzer, den Zeitstempel, den Ablauf, die Länge und die Versuche gegen eine Multi -Faktor -Authentifizierung (ein Code wie 123456, das an ein Telefon oder eine E -Mail gesendet wurde).

# Ein grundlegendes Token, das sich bei der Website angemeldet hat
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)
Fügen wir unserem Benutzer auch ein Privileg hinzu, und wir werden es vorerst manuell einstellen, bevor wir schließlich automatisch in die Eintragung privilegierter Benutzer migrieren. Fügen Sie in den Benutzermodellen diese Zeile im Profil hinzu:

    vendor = models.BooleanField(default=False)
Wie bei allen Änderungen an der Datenbank müssen wir Migrationen vornehmen und die Datenbank jederzeit migrieren, wenn wir eine Modelle in Django bearbeiten. Denken Sie daran, dass wir zuerst die Quelle verwenden (wenn es seit dem Öffnen des Terminals nicht bereits verwendet wurde) und dann Python verwalten.py, um die Migrationen zu erstellen und zu migrieren.

cd project-directory-you-named # (falls erforderlich)
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Im Moment können Sie alle Konten, die Sie als Anbieter erstellt haben, mithilfe der Shell erstellt.

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
Lassen Sie uns nun unsere Multi -Faktor -Authentifizierungsansicht entwickeln, um dieses Token zu verwenden. Zunächst müssen wir unsere MFA -Helfer -Dienstprogramme ändern. Mit Nano,

nano users/mfa.py

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

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

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

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

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

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

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

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

# Authentifizieren Sie den Benutzer mit seiner E -Mail oder Telefonnummer
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() # Filtern Sie das Token durch den in der URL übergebenen Wert (ein 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)) # Wenn diese Sitzung nicht erstellt wurde, erstellen Sie sie
    user = User.objects.filter(id=token.user.id).first() # Holen Sie sich den Benutzer vom Token
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # Wenn sie bereits authentifiziert sind, melden Sie sich an
    if not user: raise PermissionDenied() # Leugnen, wenn kein Benutzer gefunden wurde
    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): # Überprüfen Sie das Auth -Token
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Melden Sie sich im Benutzer an, wenn er noch nicht angemeldet ist
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # Legen Sie eine Ablauf für ihre Multi -Faktor -Authentifizierung fest
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # Umleiten Sie den Benutzer auf die nächste Seite um
    if not user.profile.mfa_enabled: # Überprüfen Sie, ob MFA aktiviert ist
        if not check_verification_time(user, token): # Überprüfen Sie die Zeit
            user.profile.mfa_enabled = False # Löschen Sie die Telefonnummer
            user.profile.enable_two_factor_authentication = True # Aktivieren Sie MFA
            user.profile.phone_number = '+1' # Deaktivieren Sie die Telefonnummer
            user.profile.save() # Speichern Sie das Profil
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Melden Sie den Benutzer an, wenn sein MFA nicht aktiviert ist
            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): # Wenn die Anfrage eine Postanforderung ist
        form = TfaForm(request.POST) # Die Form instanziieren
        code = str(form.data.get('code', None)) # Holen Sie sich den Code
        if code and code != '' and code != None: # Stellen Sie sicher, dass es nicht leer ist
            token_validated = user.profile.check_auth_token(usertoken) # Überprüfen Sie das Auth -Token
            p = user.profile
            is_verified = check_verification_code(user, token, code) # Überprüfen Sie den Code
            p.mfa_authenticated = is_verified
            if token_validated: # Wenn alles
                if is_verified: # Ist in Ordnung
                    user.profile.mfa_enabled = True # Aktivieren Sie MFA (wenn nicht bereits aktiviert)
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Melden Sie sich im Benutzer an
                    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(): # Erstellen Sie einen QueryString für den nächsten Parameter (falls vorhanden)
                        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) # Umleiten
                    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: # Wenn das Token ungültig war
                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: # Wenn es zu viele Versuche gab
                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): # Senden Sie die E -Mail (oder Text)
                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('/'))
    # Rendern Sie das Formular (für Get -Anfragen)
    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'})
Wenn wir diesen Code hinzufügen, importieren Sie die Funktion, um eine E -Mail zu senden. Oben in der Datei, die Benutzeransichten (mit anderen Importen), fügen Sie hinzu

from .mfa import send_verification_email as send_mfa_verification_email
Jetzt müssen wir diese Funktion schreiben, bevor irgendetwas davon funktioniert. Es sollte unsere Send -E -Mail -Funktion erweitern und einfach eine E -Mail an den Benutzer mit dem Bestätigungscode senden.

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))
Das alles funktioniert also großartig, jetzt haben wir ein Multi -Faktor -Authentifizierungssystem, das eine Telefonnummer oder E -Mail abhängt, um sich anzumelden. Wir benötigen aber auch eine Möglichkeit, Benutzer zu entfernen oder zumindest Benutzer zu verbergen, die nicht mit unseren Begriffen kooperieren. Dies könnten Spammer, Roboter oder jeden sein, der für unsere Arbeit nicht gut bedeutet. Schauen Sie sich einen Blick auf eine Ansicht, die ich für die Überwachung von Benutzern auf meiner Website habe:

# Beträge
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor # Wir müssen diesen Test erstellen

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # Holen Sie sich eine Liste von Benutzern
    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', { # Rückgänge Benutzer in einer Vorlage zurückgeben
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
Beachten Sie, dass dieser Code einen Test verwendet. Wir müssen diesen Test in einer Tests.Py -Datei deklarieren und importieren. Bearbeiten von Benutzern/Tests.py, erstellen wir den Test.

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
Dies erfolgt in Verbindung mit der Vorlage für Benutzer/Benutzer.html, die ungefähr so ​​aussieht:
 
{% 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 %}
 
Beachten Sie, dass die Vorlage eine andere Vorlage enthält, Benutzer/_user.html. Bei Verwendung einer Vorlage mit einer Subtemplate und nicht der Verwendung von Erweiterungen ist es eine gute Idee, vor dem Namen der Datei einen Unterstrich (_) vor dem Namen der Datei hinzuzufügen, um Vorlagen zu unterscheiden. Beachten Sie, dass dies eine Menge Jinja ist. Möglicherweise haben Sie möglicherweise nicht alle diese Variablen definiert. Aber so sieht mein Code aus.
 
{% 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>
 
Wir brauchen auch eine andere Subtemplate, toggle_active.html. Diese Vorlage sollte ein Formular sein, mit dem wir umschalten können, ob ein Benutzer aktiv ist.
 
<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>
 
Wir müssen auch eine Ansicht zum Umschalten der Benutzeraktivität und geeigneten URL -Mustern hinzufügen. Während wir dabei sind, fügen wir eine Ansicht hinzu, um einen Benutzer zu löschen, falls wir dies brauchen.

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


# Beträge
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import DeleteView

class UserDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = User
    success_url = '/' # Die Weiterleitung der Erfolgs -URL
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        return context

    def test_func(self): # Testen Sie, ob der Benutzer Superuser ist und die Erlaubnis zum Löschen hat
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
Wenn dies bei Bedarf praktisch ist, sollte das Löschen eines Benutzers die meiste Zeit nicht erforderlich sein, aber wir können die Sichtbarkeit von Benutzern, die die Website besuchen, einfach umschalten, wenn wir sie entlassen müssen. Die URL -Muster, die wir hinzugefügt haben, sehen so aus. Bearbeiten Sie mit Nano Benutzer/URLs.py und fügen Sie folgende Zeilen hinzu:

nano users/urls.py
Die Zeilen sollten in der Liste der Pfade in den Benutzeransichten vor dem Ende „]“, aber nach dem Anfang „[“.

# …
    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'),
# …
Stellen Sie nun sicher, dass Sie die Website sichern, damit Sie sie auf dem Webserver herunterladen können, an dem wir weiter arbeiten. Aus der Befehlszeile,

sudo backup
Jetzt ist unsere Website gesichert. Jetzt haben wir also ein paar weitere nützliche Funktionen. Aber was ist mit dem Gesamtbild hier? Dieser Code ist immer noch nicht aus dem Internet zugänglich, wir haben noch keinen Mailserver und wir müssen unsere App so erweitern, dass wir einen umfassenden Überprüfungsprozess sowie reibungslose Layouts enthalten . Wir werden all das erreichen. Das Wichtigste für den Moment wird nur diesen Code online bekommen, was wir mit nur wenigen Zeilen von Bash auf einem Ubuntu -Server tun können. Sie müssen einen Server dafür mieten, es sei denn, Sie haben einen Server zu Hause und ein Geschäft mit Business -Internet, mit dem Sie Ports öffnen können. Ich persönlich führe meine Website auf einem HP Z440 aus, das in meiner Wohnung installiert ist, aber es ist normalerweise viel billiger für die Grundbedürfnisse, um einen virtuellen privaten Server (VPS) zu mieten. Denken Sie daran, dass der Code, den wir jetzt ausführenBereit, das zu verwenden, was wir haben, um ein Produkt zu erstellen. Stellen Sie sicher, dass Sie vorsichtig sind, was Sie mit dem Internet tun. Wenn Sie diese Website auf einem Linux -Server öffentlich im Web bereitstellen, haben Sie einen Plan, unerwünschte Interaktionen mit Ihrer Website zu blockieren. Dies wird wahrscheinlich zunächst kein Problem sein, aber wir werden uns mit einer Vielzahl von Lösungen befassen, um dies zu bekämpfen, einschließlich maschinelles Lernen, künstlicher Intelligenz und Computer Vision. Wenn es zu einem Problem wird, suchen Sie in diesem Text nach einer Lösung weiter. In Bezug auf die Vermietung eines VPS gibt es viele Orte, an denen Sie gehen können. Google Cloud verfügt über VPS -Server, Ionos, Kamatera, Amazon AWS und mehr Anbieter bieten Cloud -Server -Lösungen an, die unseren Anforderungen entsprechen. Sie müssen durch ihre Formulare klicken und einen Plan auswählen, um loszulegen. Sie können mit jedem Anbieter einen grundlegenden Plan entscheiden. Stellen Sie jedoch sicher, dass der Anbieter Port -Server -Ports öffnen, um E -Mails zu senden (dies sollte Port 587 und Port 25 sein). Einige Anbieter blockieren diese Ports. Bisher hatte ich dasEST -Erfahrung mit Ionos und Kamatera, beide werden es mir ermöglichen, unbegrenzte E -Mails zu senden, und ihre Preisgestaltung ist ziemlich günstig. Sie werden eine Verbindung zu Ihrem neuen Server über einem Protokoll namens SSH oder Secure Shell herstellen, mit dem Sie genau wie Ihr PC -PC -PC -PC -SERN mit dem Server eine Ferne mit dem Server schneiden können. Wenn Sie den Server einrichten, wird der Hosting -Anbieter Sie wahrscheinlich auffordern, einen SSH -Schlüssel hinzuzufügen, oder er gibt Ihnen einen Benutzernamen und ein Passwort. Der SSH -Schlüssel ist, wie Sie sich aus der Befehlszeile beim Server anmelden, um den Code zu bearbeiten. Verwenden Sie die folgenden SSH-Keygen-Optionen, um ein SSH zu generieren

ssh-keygen
Speichern Sie die Datei und überschreiben Sie sie, wenn Sie benötigen. Jetzt können Sie den folgenden Befehl verwenden, um Ihren SSH -Schlüssel zu sehen. Sie möchten es auf Ihren Remote -Server kopieren, damit Sie es zur Authentifizierung verwenden können.

cat ~/.ssh/id_rsa.pub
Wenn Sie beim Eingeben dieses Befehls (eine lange Reihe von Ziffern und Buchstaben, die mit „SSH-RSA AAA“ beginnen), keinen SSH-Schlüssel sehen konnten), versuchen Sie, einen RSA-Schlüssel zu generieren (sie sind sicherer, daher rate ich, sie zu verwenden .) Der folgende Code generiert einen 4096 -Bit -RSA -SSH -Schlüssel.

ssh-keygen -t rsa -b 4096
Erstellen Sie ein VPS, das Ubuntu ausführt. Sie planen dies jedoch. Sobald Sie ein VPS erstellt haben, indem Sie die Formulare der Providers -Website (Kamatera.com, Ionos.com oder ähnliches) durchklicken, sollten Sie sich anmelden. Verwenden Sie dazu den Befehl SSH mit Ihrer IP -Adresse (die Adresse Das sieht aus wie xx.xx.xx.xx). Sie müssen auch auf den Standard -Benutzernamen auf dem von uns erstellten Server sensibel sein, beispielsweise Ubuntu.

ssh ubuntu@XX.XX.XX.XX
Möglicherweise werden Sie nach einem Passwort gefragt. Wenn Sie nach einem Passwort gefragt werden, geben Sie es ein. Beginnen wir zunächst eine neue SSHD_CONFIG -Datei, die dem Server mit der Verwendung von SSH mitteilt.

nano sshd_config

# Dies ist die sshd server-systemweite Konfigurationsdatei.  Sehen
# SSHD_CONfig (5) für weitere Informationen.

# Dieser SSHD wurde mit PATH =/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games kompiliert

# Die Strategie, die für Optionen in der Standard -SSHD_CONFIG mit verschicktem SSHD_Config verwendet wird
# OpenSSH soll Optionen mit ihrem Standardwert angeben, wo
# Möglich, aber lassen Sie sie kommentiert.  Überfassende Optionen überschreiben die
# Standardwert.

# Port 22
# Adressfamily alle
# ListenAddress 0.0.0.0
# ListenAddress ::

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

# Chiffren und Titeln
# RekeyLimit default none

# Protokollierung
# Syslogfacility auth
# Loglevel Info

# Authentifizierung:

# Logringracetime 2m
# ErlaubnisRootlogin-Verbot-Passwort
# Strictmodes Ja
# MaxAuthtries 6
# Maxessionen 10

PubkeyAuthentication yes

# Erwarten Sie, dass .Ssh/autorized_keys2 in Zukunft standardmäßig missachtet wird.
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# AutorizedPrincipalsfile keine

# AutorizedKeyscommand keine
# AutorizedKeysCommanduser Niemand

# Damit dies funktioniert
# HostbasedAuthentication Nr
# Wechseln Sie zu Ja, wenn Sie nicht ~/.ssh/bekannt_hosts für vertrauen, für
# HostbasedAuthentication
# IgnoreUser Bekanntenhosts nr
# Lesen Sie nicht die ~/.rhost- und ~/.hosts -Dateien des Benutzers
# Ignorerhosts ja

# Ändern Sie hier auf Nein, um Tunnel -klare Textkennwörter zu deaktivieren!
PasswordAuthentication no
# Erläuterungspasswörter Nr

# Wechseln Sie zu Ja, um Challenge-Response
# Einige PAM -Module und Threads)
KbdInteractiveAuthentication no

# Kerberos Optionen
# Kerberosauthentifizierung Nr
# Kerberosorlocalpasswd Ja
# KerberosticketCleanup Ja
# Kerberoskotte

# GSSAPI -Optionen
# GSSAPIAauthentication Nr
# GSSAPICLEANUPCredentials Ja
# GSSAPISTRICTACCEPETORCECKECE JA
# GSSAPIKEYExchange Nr

# Legen Sie dies auf "Ja" fest, um die PAM -Authentifizierung, die Kontoverarbeitung zu aktivieren,
# und Sitzungsverarbeitung. Wenn dies aktiviert ist, wird die PAM -Authentifizierung
# durch die kbdinteractiveAuthentication erlaubt sein und
# PasswortAuthentication.  Abhängig von Ihrer PAM -Konfiguration,
# PAM -Authentifizierung über kbdinteractiveAuthentication kann umgehen
# Die Einstellung von "Genehmigungsrootlogin ohne Passwort".
# Wenn Sie nur möchten, dass das PAM -Konto und die Sitzungsprüfungen ohne Ausführung führen
# PAM -Authentifizierung, dann aktivieren Sie dies, setzen Sie jedoch die PasswordAuthentication fest,
# und kbdinteractiveAuthentication zu "Nein".
UsePAM yes

# Zulassungsverwartung Ja
# ALLETCPFORWARDING JA
# Gatewayports Nr
X11Forwarding yes
# X11DisplayOffset 10
# X11uselocalHost Ja
# Pille ja
PrintMotd no
# Printlastlog Ja
# Tcpkeepalive Ja
# Dingensumgebung in
# Komprimierung verzögert
# Clientalive Intervall 0
# ClientaliveCountMax 3
# Gebraucht in
# Pidfile /run/ssshd.pid
# Maxstartups 10: 30: 100
# Pemittunl Nr
# Chrootdirectory keine
# VersionAddendum none

# Kein Standard -Bannerweg
Banner /etc/banner

# Erlauben Sie dem Kunden, lokale Variablen zu bestehen
AcceptEnv LANG LC_*

# Überschreiben Sie die Standardeinstellung ohne Subsysteme
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Beispiel für übergeordnete Einstellungen von pro-user-Basis
# Übereinstimmen Benutzer anoncvs
# X11foring Nr
# Zulassende Nr
# Zulassung in
# ForceCommand CVS -Server
PermitRootLogin no
Denken Sie daran, Strg+X und Y, um die Datei zu speichern. Schreiben wir als nächstes ein grundlegendes Skript namens Initialize (alle im Standard -Home -Verzeichnis unseres Benutzers).

nano initialize
Fügen Sie diese Zeilen der Datei hinzu und ersetzen SieMit Ihrem SSH -Schlüssel, den Sie mit Cat gefunden haben. (.Ssh/id_rsa.pub)

# !
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
Um Sie durch diese Datei zu führen, starten wir die Zeile für die Zeile. Die erste Zeile teilt dem Compiler mit, dass dies ein Bash -Skript ist. Anschließend installieren wir Abhängigkeiten, kopieren SSHD_CONfig in das richtige Verzeichnis, starten Sie SSH, generieren SSH -Tasten für Root und fügen Sie das Benutzer -Team hinzu (Sie können einen Namen auswählen, den Sie dafür mögen, den Befehl adduser mit ihrem Namen und deaktiviertem Passwort für deaktiviertes Kennwort verwenden. Jetzt). Wir fügen auch das Team in die Sudo -Gruppe hinzu, generieren ihren SSH -Schlüssel, fügen unseren Schlüssel zu autorisierten Schlüssel und ihre und drucken ihren Schlüssel. Dieser neue Benutzer wird sein, wie wir uns auf der Website anmelden. Geben Sie in einem neuen Terminal den Server erneut auf.

ssh team@XX.XX.XX.XX
Diesmal sollten Sie kein Passwort benötigen, da Sie einen SSH -Schlüssel haben. Wir haben auch das Anmeldung mit Passwort deaktiviert, um die Website sicherer zu halten. Jetzt startet dieser Server ohne Informationen völlig leer. Beginnen wir damit, unser Projekt aus Git zu klonen, damit wir es herunterladen und auf dem Remote -Computer ausführen können. Drucken Sie auf dem über SSH angeschlossenen Remote -Server zuerst Ihren SSH -Schlüssel aus:

cat ~/.ssh/id_rsa.pub
Fügen Sie diese Taste als nächstes in die Git -Einstellungen ein, wie wir es zuvor getan haben, um unser Git -Repository einzurichten. Wir können jetzt unser Projekt direkt auf den Server klonen. Stellen Sie sicher, dass Sie das Projekt zuerst vor Ort gesichert haben, damit es auf dem Git -Server heruntergeladen werden kann.

git clone git://github.com/you/yourproject.git
Perfekt. Jetzt sind alle Dateien hier. Wir können sie mit LS sehen

ls
Beginnen wir nun, den Server einzurichten. Kopieren Sie zunächst Ihr Projektverzeichnis in einen einfachen, unvergesslichen Namen, den wir für das Projekt verwenden werden.

cp -r yourproject whatyoucalledit
Wo „Whatyoucalledit“ der neue Name Ihres Projekts ist. Als nächstes müssen wir ein grundlegendes Dienstprogramm erstellen, um den Server einzurichten. Wir werden dieses Dienstprogramm retten und in Zukunft einsetzen. Um dieses Dienstprogramm aufzubauen, erstellen wir einen Benutzer -Binärdatum, um zu definieren, wie wir ein Skript bearbeiten. Verwenden von Bash, bearbeiten/usr/bin/ascript

sudo nano /usr/bin/ascript
Stellen Sie dort sicher, dass Sie sudo dort verwenden, damit Sie Berechtigungen zum Bearbeiten der Datei haben. Fügen Sie in der Datei folgende Zeilen hinzu:

# !
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
Denken Sie daran, dass dieses Skript ein Argument, den Skriptnamen, als $ 1. Zuerst prüft es, ob die Datei vorliegt oder auf andere Weise erstellt wird, die erste Zeile zum Deklarieren des Skripts ist, ändert seine Berechtigungen, bearbeitet sie und fügt ihren Namen zu /etc /ascripts hinzu, wodurch wir die Namen der Skripte speichern können erstellen. Wenn die Datei bereits vorhanden ist, ändern Sie einfach die Berechtigungen und bearbeiten Sie sie. Speichern Sie die Datei und als nächstes werden wir ihre Berechtigungen ändern. Solange wir dieses Skript verwenden, müssen wir das nicht noch einmal tun.

sudo chmod a+x /usr/bin/ascript
Perfekt. Erstellen wir nun ein Skript namens Setup. Erstens, um Sie nicht zu überwältigen, sondern schauen Sie sich an, wie mein Setup -Skript aussieht. Wir werden durchgehen, wie dieses Skript in Ihrem Projekt aussehen soll, Sie brauchen nicht alles in meinem Skript.

# !
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
# sudo chmod a+x scripts/userSetup
# ./Scripts/usersetup
# Ssh-keyen
# Projektverzeichnis
DIR="/home/team/femmebabe"
USER="team"
# Protokollbefehle
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 -Konfiguration
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git -Konfiguration
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
# Aktualisieren und installieren
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
# Aktivieren Sie das Clamav -Antivirus
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Hostname festlegen
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Setup Postgres
echo "Postgres setup"
sudo -u postgres psql -U postgres -c "DROP DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE USER django WITH PASSWORD 'password';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET client_encoding TO 'utf8';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET default_transaction_isolation TO 'read committed';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET timezone TO 'UTC';"
sudo -u postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE database TO django;"
# Setup Backup -Datenbank einrichten
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
# Deaktivierte 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
#  Install BitDefender
cd $DIR
echo "Runnning BitDefender antivirus installer"
wget https://cloud.gravityzone.bitdefender.com/Packages/NIX/0/7aTSsy/setup_downloader.tar
mkdir bitdefender
tar -xf setup_downloader.tar -C bitdefender
sudo rm setup_downloader.tar
sed -i -e 's/{LOGINPASSWD/z&A*3BPd_qBGUMs/g' bitdefender/installer
sudo chmod a+x bitdefender/installer
sudo ./bitdefender/installer
# Setup 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
# Schaffung von Diren
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
# SETUP VIRTUELENV
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# Holen Sie sich ab und bauen Sie Abhängigkeiten auf
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
# Festlegen von Firewall -Regeln
cd $DIR
# Installieren Sie PYPI -Abhängigkeiten
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 Installation OpenCV-Python == 4.5.5.64
# PIP Installation OpenCV-Contrib-Python == 4.5.5.64
pip3 install --upgrade opencv-python-headless
pip3 uninstall channels
pip3 uninstall daphne
pip3 install channels["daphne"]
pip3 install Pillow==9.5.0
pip3 install librosa
pip3 install -U 'Twisted[tls,http2]'
pip3 install --upgrade certifi requests urllib3 numpy oauthlib twisted pyjwt sqlparse cryptography astral webauthn docbarcodes pdf417 deepface --no-cache-dir
pip3 install tensorflow==2.15.1
# Certbot installieren
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
# Rennen certbot
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# Mailserver neu laden
sudo systemctl restart opendkim postfix dovecot
# Kopieren von Zertifikaten
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privkey.pem
# sudo cp /etc/lettescrypt/live/femmebabe.com/cert.pem cert.pem
# Patch
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"
# Setzen Sie die Benutzereinstellungen
sudo gpasswd -a www-data users
# Berechtigungen festlegen
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# sudo chown -r Team: Benutzer/var/run/
# sudo chown root: root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
# sudo chmod 664 db.sqlite3
# sudo chown www-data: Benutzer 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
# Konfigurationen kopieren und Berechtigungen festlegen
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
# Datenbank -Setup
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 -Konfiguration injizieren und fehlerhafte SSH -Konfiguration entfernen
# sudo sed -i '' -e '$ d' /tc/pam.d/ssshd
# Sudo sed -i '' -und $ 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
# Kopieren Sie Bin -Skripte und setzen Sie Berechtigungen
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
# Dienste neu laden und aktivieren
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
# Aktivieren Sie Apache -Module
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
# Deaktivieren Sie die Standard -Site
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# Für die Website aktivieren
sudo a2ensite femmebabe-le-ssl
# Laden Sie Daemon neu und starten Sie Apache, Postfix und Opendkim neu
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# Berechtigungen festlegen
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# Swap -Konfiguration
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
# Init Caption Motor
echo "Initializing routine caption"
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/routine_caption.py
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/setup_mail.py
# Setup Git
echo "Setting up git"
cd $DIR
sudo rm -r .git
git init --initial-branch=main
echo "Setting user password"
sudo usermod --password $(echo team | openssl passwd -1 -stdin) team
# IPv6 und Opendkim für die Domänenkonfiguration anzeigen
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}'
# Setup abgeschlossen
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."
Das ist eine Menge Setup! Kurz gesagt, diese Code protokolliert Befehle, konfiguriert Nano und Git, kopiert über Dateien, downloads und installiert Ubuntu APT -Pakete, Python -Abhängigkeiten, konfiguriert Postfix, konfiguriert Postgresql (der Datenbankserver) und lädt die Datenbank, konfiguriert UFW (eine unkomplizierte Firewall). Deaktiviert Iptables, lädt ein Antivirus herunter, stellt Verzeichnisse her, Kloneabhängigkeiten, installiert Zertifikate und richtet den Server ein, installiert die Konfiguration, startet und ermöglicht den Abtausch, Zuwachs, legt Berechtigungen fest und druckt die IP-, IPv6 -Adresse und Oppendkim -Taste. Ziemlich einfach, aber es sieht nach viel Code aus. Wir werden nicht viel davon brauchen, weil wir nicht die Abhängigkeiten haben, wir nicht Sellerie, Celerybeat oder Daphne verwenden, aber wir werden einige davon trotzdem installieren, um loszulegen. Beachten Sie, dass dieser Code eine Domäne mehrmals deklariert hat. Wir müssen auch einen Domain -Namen erwerben (was eine kleine jährliche Gebühr ist). Ich empfehle Squarespace für den Kauf einer Domain, ihr Layout istintuitiv und einfach zu bedienen. Sie können eine Domain Ihrer Wahl kaufen, aber ich verwende in diesem Beispiel die Domain femmebabe.com. Sobald Sie eine Domäne gekauft haben, besuchen Sie das Squarespace DNS -Konfigurationspanel und fügen Sie einen Datensatz hinzu, der Ihre Domäne per IP -Adresse zum Server verweist. Es sollte so aussehen: @ A xx.xx.xx.xx Mit dem @ operator als Host, was bedeutet, dass alle Subdomains unter dieser Domäne und die Stammdomäne alle zum Server leiten. Es gibt mehr Aufzeichnungen zu erklären, aber wir können zu diesen übergehen, sobald wir bereit sind, E -Mails zu senden. Beachten Sie, dass es einige Tage dauern kann, bis Sie E -Mails erfolgreich vom Server senden können. Die DNS -Aufzeichnungen, die wir festlegen, dauert Zeit, um sich zu verbreiten. Wie auch immer, der einzige Rekord, den wir starten müssen, ist ein A -Rekord. Jetzt können wir das folgende Skript entsprechend unserem Projekt ausfüllen und es ausführen. Beginnen wir mit einem kleineren Setup -Skript, um einfach das zu installieren, was wir für einen grundlegenden Fortschritt benötigen. Wir werden noch nicht so viele Abhängigkeiten oder Postgresql verwenden, wir werden nur nureinen grundlegenden HTTP -Server und sorgen Sie sich um eine Zertifizierung, wenn dies erfolgt. Denken Sie daran, ein HTTPS -Zertifikat zu erhalten und den Server sicher auszuführen, müssen wir eine Domäne zusammen mit der Miete eines Servers kaufen. Ersetzen Sie vorerst „Team“ in dieser Datei durch den Namen Ihres Benutzers, „Dir“ durch das Verzeichnis Ihres Projekts und liefern Sie Ihre E -Mail und Domain in den <> -Tags. Bevor wir diesen Code ausführen, müssen wir die Einstellungen in der Firewall ändern, die der Hosting -Anbieter unterstützt, falls vorhanden. Normalerweise befindet sich dies auf der Registerkarte "Netzwerke" Ihres Hosting -Anbieters oder wenn Sie sich selbst Hosting befinden, ist es im Abschnitt "Portweiterleitung" Ihres Routers. Sie möchten auch eine statische IP über Ihren Router mit der Adresse Ihres Servergeräts einrichten, wenn Sie Selbsthosting verwenden. Sie müssen die folgenden Ports für den Lese-/Schreibzugriff öffnen. 22 (SSH) 25 (Mail) 587 (Mail) 110 (Mail Client) 80 (HTTP) 443

# !
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
# Protokollbefehle
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 -Konfiguration
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git -Konfiguration
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
# Aktualisieren und installieren
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
# Aktivieren Sie das Clamav -Antivirus
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Hostname festlegen
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
# Setup Backup -Datenbank einrichten
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
# Deaktivierte 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
# SETUP VIRTUELENV
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
# Certbot installieren
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
# Rennen certbot
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# Setzen Sie die Benutzereinstellungen
sudo gpasswd -a www-data users
# Berechtigungen festlegen
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# sudo chown -r Team: Benutzer/var/run/
# sudo chown root: root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
# Dienste neu laden und aktivieren
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Aktivieren Sie Apache -Module
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
# Laden Sie Daemon neu und starten Sie Apache, Postfix und Opendkim neu
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# IPv6 und Opendkim für die Domänenkonfiguration anzeigen
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
Stellen Sie vor dem Ausführen dieses Codes sicher, dass die von Ihnen gekaufte Domain mit dem Server verbunden ist. Öffnen Sie dazu ein Terminal auf Ihrer lokalen Maschine und führen Sie diesen Befehl mit Ihrer Domain aus:

ping femmebabe.com # Fügen Sie Ihre Domain hier nach dem Ping ein
Wenn alles gut aussieht und der Server Antworten sendet, können wir das Skript ausführen und Pakete installieren sowie unseren Apache -Server starten, aktivieren und zertifizieren. Dies ist nicht das gesamte Setup, das für die Konfiguration von Postfix benötigt wird. Wir werden uns dieses Setup später mehr ansehen. Führen Sie diesen Setup -Code vorerst aus und es sollte einige Minuten dauern, bis Sie Ihren Server installieren und zertifizieren. Stellen Sie erneut sicher, dass Sie den Namen von Namen, E -Mail und Domain im Skript entsprechend dem von Ihnen gekauften Namen ersetzen. Nachdem der Server bereitgestellt wird, können Sie in jedem Webbrowser zur URL gehen und sicherstellen, dass der Server HTTPS ausführt. Wenn dies nicht der Fall ist, sollten Sie ein wenig warten, bis die DNS -Datensätze nachholen können, und führen Sie den folgenden Befehl aus, um die Zertifizierung von Certbot wiederzuerlangen:

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
Solange Sie alles richtig konfiguriert haben, sollten Sie in der Lage sein, auf die Standardseite von Apache zugreifen zu können, um zu wissen, dass Ihr Code funktioniert und eine Live -Webseite anzeigt. Bearbeiten wir als nächstes die Einstellungen.py, um unseren Standard -Debug -Modus in die Produktion zu ändern. Wir werden auch die Domäne in den Einstellungen sowie interne IPs konfigurieren.

nano yourproject/settings.py
Ändern Sie diese Zeilen in den Einstellungen.

DEBUG = False

# Site -Konfiguration
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',
]
Jetzt müssen wir Apache2 konfigurieren. Bearbeiten wir die Konfigurationsdatei, die wir mit dieser Zeile bereitstellen:

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
Diese Konfigurationsdatei sollte unseren Domänennamen und den Namen des Benutzers und des Projekts enthalten. Ich verwende den Domainnamen femmebabe.com, das Benutzername -Team und den Projektnamen Femmebabe.

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

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

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

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

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

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

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

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

	TimeOut 60000
	LimitRequestBody 0

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

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

	RewriteEngine on
	RewriteCond %{SERVER_NAME} =femmebabe.com
	RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
</IfModule>
Stellen Sie bei der Konfiguration Ihres Servers den Namen des Projekts, der Verzeichnisse und der Domäne in diesem Beispielcode aus. Jetzt müssen wir die Standard -Site deaktivieren. Dies kann mit Bash erfolgen.

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
Als nächstes können wir die Standard -Site aktivieren und Apache2 mithilfe von Bash neu laden. Denken Sie daran, Femmebabe durch den Namen der Datei zu ersetzen, die Sie bei der Bearbeitung in/etc/apache2/sites-verfügbaren/verfügbaren Datei/.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Gehen Sie zurück zu Ihrer Domain in der Navi. Sie sollten die Site sehen, die Sie in Ihrem Webbrowser konfiguriert haben. Glückwunsch! Wenn Sie es nicht sehen, müssen Sie möglicherweise einige Änderungen vornehmen. Überprüfen Sie die Einstellungen in Ihrem Projekt und in Ihrer Apache -Konfiguration sorgfältig und stellen Sie sicher, dass Sie keine Fehler haben, und führen Sie die folgenden Befehle aus, um das Projekt auf Fehler zu überprüfen.

cd projectname
source venv/bin/activate
python manage.py check
Wenn Sie Fehler in Ihrem Python -Projekt haben, verfolgen Sie sie dort, wo sie sich befinden, und beheben Sie sie. Möglicherweise sind Sie möglicherweise nicht alle Ihre Fehler festzustellen Fehler.

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Scrollen Sie zu Zeile 83, in der dieser Laufzeitfehler erhöht wird (RuntimeError erhöhen („Populate () ist nicht wieder eingetragen“)) und fügen Sie vor dieser Zeile einen Kommentar hinzu, und fügen Sie dann mit derselben Eindrückung self.app_configs = {} hinzu. Das sieht so aus:

            if self.loading:
                # Verhindern Sie, dass regelante Anrufe vermeiden, AppConfig.ready () auszuführen.
                # Methoden zweimal.
# RundTimeError reben ("Populate () ist nicht wieder eingetragen"))
                self.app_configs = {}
            self.loading = True
Sie können das Projekt dann erneut überprüfen und den Fehler aufdecken.

python manage.py check
Dann können Sie den Fehler sehen und ihn beheben. Wenn Sie es behoben haben und der Code ohne Fehler kompiliert, ändern Sie die Datei zurück, damit sie so aussieht:

            if self.loading:
                # Verhindern Sie, dass regelante Anrufe vermeiden, AppConfig.ready () auszuführen.
                # Methoden zweimal.
                raise RuntimeError("populate() isn't reentrant")
# self.app_configs = {}
            self.loading = True
Vorausgesetzt, der Server ist online, wenn wir weitere Änderungen daran vornehmen, müssen wir den folgenden Befehl verwenden, um den Server neu zu laden:

sudo systemctl reload apache2
Eindrucksvoll! Aber was ist mit dem Versenden von Post? Um E -Mails zu senden, müssen wir zunächst die Domänenkonfiguration aktualisieren. Dies sollte in Ihrem DNS -Panel in Squarespace oder in welchem ​​Domainnamen -Registrar, das Sie ausgewählt haben, enthalten sein. Wir müssen auch die Konfiguration installieren und hinzufügen und einige Befehle ausführen. Lassen Sie uns zunächst die IPv6 -Adresse des Servers erhalten. Wir werden dann Ihre DNS öffnen und die Datensätze hinzufügen. Verwenden Sie diesen Befehl, um die IPv6 -Adresse des Servers zu erhalten:

ip -6 addr
Jetzt können wir den DNS -Einstellungen die folgenden Datensätze hinzufügen. Meine Platten sehen so aus. Für Ihre Datensätze sollten Sie die IP -Adresse jedoch durch Ihre IP ersetzen (nicht 75.147.182.214, das ist meine). Fügen Sie auch Ihre Domain anstelle von femmebabe.com sowie Ihre IPv6 -Adresse hinzu, die mit dem vorherigen Befehl gefunden wurde (Sie können meine nicht verwenden, Fe80 :: 725A: FFF: FE49: 3E02). Machen Sie sich vorerst keine Sorgen um den DomainKey, dies wird erstellt, wenn wir Postfix, den Mailserver, mit Opendkim einrichten und den Schlüssel drucken. Wir werden dies zuletzt konfigurieren. @ A N / A 75.147.182.214 @ Mx 10 femmebabe.com @ Ptr N / A femmebabe.com @ TXT N / A Txt @ v = spf1 MX IP75.147.182.214IP6: FE80 :: 725A: FFF: FE49: 3E02 ~ All default._bimi TXT N / A v = bimi1; l = https: //femmebabe.com/media/static/femmebabe.svg _dmarc TXT N / A v = dmarc1; p = keine sendonly._domainkey TXT N / AJetzt müssen wir eine persistierende Konfiguration für Postfix hinzufügen. Wir müssen nur sicherstellen, dass wir den Domain -Namen Femmebabe.com durch den von Ihnen verwendeten Domain -Namen ersetzen. Schauen wir uns alle Konfigurationsdateien nacheinander an und installieren Sie sie in einem Verzeichnis namens Config in unserem Projekt, um das Betriebssystem zu installieren.

nano config/etc_postfix_main.cf
Fügen Sie diesen Text der Datei hinzu

# Siehe /usr/share/postfix/main.cf.dist für eine kommentierte, vollständigere Version


# Debian spezifisch: Das Angeben eines Dateinamens verursacht den ersten
# Zeile dieser Datei, die als Name verwendet werden soll.  Der Debian -Standard
# ist /etc /mailName.
# myorigin = /etc /mailName

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

# Anhängen .Domain ist der Job der MUA.
append_dot_mydomain = no

# Überzeugen Sie die nächste Zeile, um Warnungen "verspätete Post" zu generieren
# delay_warning_time = 4h

readme_directory = no

# Siehe http://www.postfix.org/compatibility_readme.html - Standard auf 3.6 auf
# Frische Installationen.
compatibility_level = 3.6



# TLS -Parameter
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 -Konfiguration
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
Nächste Konfiguration!

nano config/etc_postfix_master.cf
Fügen Sie diese Zeilen hinzu:

# 
# Postfix Master -Prozesskonfigurationsdatei.  Einzelheiten zum Format
# der Datei finden Sie auf der Handbuchseite der Master (5) (Befehl: "Man 5 Master" oder
# Online: http://www.postfix.org/master.5.html).
# 
# Vergessen Sie nicht, nach dem Bearbeiten dieser Datei "Postfix Reload" auszuführen.
# 
# ====================================================== =========================
# Servicetyp Privat unriv chroot wakeup maxproc Befehl + Argum
# (Ja) (Ja) (Nein) (niemals) (100)
# ====================================================== =========================
smtp      inet  n       -       y       -       -       smtpd
# SMTP INET N - Y - 1 Postscreen
# SMTPD -Pass - - y - - SMTPD
# Dnsblog unix - - y - 0 dnsblog
# tlsproxy unix - - y - 0 tlproxy
# Wählen Sie eine aus: Aktivieren Sie die Einreichung nur für Loopback -Clients oder für einen Kunden.
# 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/submission
# -O SMTPD_TLS_SECURITY_LEVEL = ENCRYPT
# -O SMTPD_SASL_AUTH_ENABLE = JA
# -O SMTPD_TLS_AUTH_ONLY = JA
# -O SMTPD_REJECT_UNLISTED_RECIPIENT = NO
# -O SMTPD_CLIENT_RESTRIKTIONS = $ MUA_CLIENS_RESTRIKTIONEN
# -O SMTPD_HELO_RESTRIKTIONS = $ MUA_HELO_RESTRIKTIONS
# -O SMTPD_SENDER_RESTRIKTIONS = $ MUA_SENDER_RESTRIKTIONS
# -O SMTPD_RECIPIENT_RESTRIKTIONS =
# -O SMTPD_RELAY_RESTRIKTIONS = CENN_SASL_AUTHENTICATION, Ablehnung
# -O milter_macro_daemon_name = Ursprung
# Wählen Sie eine aus: Aktivieren Sie SMTPS nur für Loopback -Clients oder für einen Kunden.
# 127.0.0.1:Smtps inet n - y - - SMTPD
# SMTPS INET N - Y - - SMTPD
# -O syslog_name = postfix/SMTPS
# -O SMTPD_TLS_WRAPPERMODE = JA
# -O SMTPD_SASL_AUTH_ENABLE = JA
# -O SMTPD_REJECT_UNLISTED_RECIPIENT = NO
# -O SMTPD_CLIENT_RESTRIKTIONS = $ MUA_CLIENS_RESTRIKTIONEN
# -O SMTPD_HELO_RESTRIKTIONS = $ MUA_HELO_RESTRIKTIONS
# -O SMTPD_SENDER_RESTRIKTIONS = $ MUA_SENDER_RESTRIKTIONS
# -O SMTPD_RECIPIENT_TRASTRICTIONS =
# -O SMTPD_RELAY_RESTRIKTIONS = CENN_SASL_AUTHENTICATION, Ablehnung
# -O milter_macro_daemon_name = Ursprung
# 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
# 
# ====================================================== ===================
# Schnittstellen zu Nicht-Postfix-Software. Achten Sie darauf, das Handbuch zu untersuchen
# Seiten der Nicht-Postfix-Software, um herauszufinden, welche Optionen sie haben möchten.
# 
# Viele der folgenden Dienste verwenden die Postfix Pipe (8) Lieferung
# Agent.  Informationen zu $ ​​{Empfänger} finden Sie auf der Seite der Pfeife (8) Frau
# und andere Optionen für Nachrichtenumschläge.
# ====================================================== ===================
# 
# maildrop. Weitere Informationen finden Sie in der Datei postfix maildrop_readme.
# Geben Sie auch in main.cf an: maildrop_destination_recipient_limit = 1
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# ====================================================== ===================
# 
# Neuere Cyrus -Versionen können den vorhandenen "lmtp" Master.cf -Eintrag verwenden.
# 
# Geben Sie in Cyrus.conf an:
# lmtp cmd = "lmtpd -a" hör = "localhost: lmtp" proto = tcp4
# 
# Geben Sie in main.cf eine oder mehrere der folgenden an:
# mailbox_transport = lmtp: inet: localhost
# Virtual_transport = lmtp: inet: localhost
# 
# ====================================================== ===================
# 
# Cyrus 2.1.5 (Amos Gouaux)
# Geben Sie auch in main.cf an: cyrus_destination_recipient_limit = 1
# 
# Cyrus unix - n n - - Pfeife
# flags = drx user = cyrus arg =/cyrus/bin/liefer -e -r $ {sender} -m $ {Erweiterung} $ {user}
# 
# ====================================================== ===================
# Altes Beispiel für die Lieferung über Cyrus.
# 
# Alt -Cyrus Unix - n n - - Pfeife
# Flags = r user = cyrus argv =/cyrus/bin/liefer -e -m $ {Erweiterung} $ {user}
# 
# ====================================================== ===================
# 
# In der Datei postfix uucp_readme finden Sie Konfigurationsdetails.
# 
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# 
# Andere externe Liefermethoden.
# 
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}
Und die Opendkim -Konfiguration. Opendkim identifiziert E -Mail -Server mit Domänenschlüssel, um sie sicherer zu machen. Ohne sie wird Mail nicht unterschrieben und schaffen es möglicherweise nicht in einen Posteingang.

nano config/etc_default_opendkim
Fügen Sie diese Zeilen hinzu:

# Hinweis: Dies ist eine Legacy -Konfigurationsdatei. Es wird nicht vom Opendkim verwendet
# Systemd Service. Bitte verwenden Sie die entsprechenden Konfigurationsparameter in
# /etc/opendkim.conf stattdessen.
# 
# Zuvor würde man die Standardeinstellungen hier bearbeiten und dann ausführen
# /lib/opendkim/opendkim.service.generate, um Systemd -Override -Dateien an zu generieren
# /etc/systemd/system/opendkim.service.d/override.conf und
# /etc/tmpfiles.d/opendkim.conf. Während dies noch möglich ist, ist es jetzt jetzt
# Empfohlen, um die Einstellungen direkt in /etc/opendkim.conf anzupassen.
# 
# DAEMON_OPTS=""
# Wechseln Sie zu/var/spool/postfix/run/opendkim, um eine UNIX -Socket mit zu verwenden
# Postfix in einem Chroot:
# Rundir =/war/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Überzeugung, um einen alternativen Sockel anzugeben
# Beachten Sie, dass die Einstellung dies in Opendkim.conf überschreibt
# Standard:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Hören Sie sich alle Schnittstellen auf Port 54321 an:
# SOCKET=inet:54321
# Hören Sie sich Loopback auf Port 12345 an:
# SOCKET=inet:12345@localhost
# Hören ist 192.0.2.1 ist Port 12345:
# SOCKET=inet:12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

nano config/etc_dovecot_conf.d_10-master.conf
Fügen Sie diese Zeilen hinzu:

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

# Standard -VSZ -Grenze (virtuelle Speichergröße) für Serviceprozesse. Dies ist hauptsächlich
# beabsichtigt, Prozesse zu fangen und zu töten, die den Speicher lecken, bevor sie auffressen
# alles.
# default_vsz_limit = 256m

# Der Anmeldebutzer wird intern durch Anmeldeprozesse verwendet. Dies ist am nicht vertrauenswürdigsten
# Benutzer im Dovecot -System. Es sollte überhaupt keinen Zugang zu irgendetwas haben.
# default_login_user = dovenull

# Der interne Benutzer wird von nicht privilegierten Prozessen verwendet. Es sollte getrennt sein von
# Login -Benutzer, damit Anmeldungsprozesse andere Prozesse nicht stören.
# default_internal_user = doveCot

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

  # Anzahl der Verbindungen, die vor Beginn eines neuen Prozesses verarbeitet werden sollen. Typischerweise
  # Die einzigen nützlichen Werte sind 0 (unbegrenzt) oder 1. 1 ist sicherer, aber 0
  # ist schneller. <doc/wiki/loginprocess.txt>
  # service_count = 1

  # Anzahl der Prozesse, um immer weiter auf weitere Verbindungen zu warten.
  # Process_min_avail = 0

  # Wenn Sie service_count = 0 festlegen, müssen Sie dies wahrscheinlich ausbauen.
  # vsz_limit = $ default_vsz_limit
}

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

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

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

  # Erstellen Sie INet Listener nur, wenn Sie die obige UNIX -Socket nicht verwenden können
  # INET_LISTER LMTP {
    # Vermeiden Sie es, LMTP für das gesamte Internet sichtbar zu machen
    # Adresse =
    # Port =
  # }
}

service imap {
  # Der größte Teil des Speichers geht an MMAP () -Dateien. Möglicherweise müssen Sie dies erhöhen
  # Begrenzen Sie, wenn Sie riesige Postfächer haben.
  # vsz_limit = $ default_vsz_limit

  # Max. Anzahl der IMAP -Prozesse (Verbindungen)
  # process_limit = 1024
}

service pop3 {
  # Max. Anzahl der POP3 -Prozesse (Verbindungen)
  # process_limit = 1024
}

service submission {
  # Max. Anzahl der SMTP -Einreichungsprozesse (Verbindungen)
  # Process_limit = 1024
}

service auth {
  # auth_socket_path verweist standardmäßig auf diesen UserDB -Socket. Es ist normalerweise
  # verwendet von dovecot-lda, doveadm, möglicherweise iMAP-Prozess usw. Benutzer, die haben
  # Vollständige Berechtigungen für diesen Socket können eine Liste aller Benutzernamen erhalten und
  # Holen Sie sich die Ergebnisse der UserDB -Lookups aller.
  # 
  # Der Standardmodus 0666 ermöglicht es jedem, eine Verbindung zum Socket herzustellen, aber der
  # UserDB -Lookups sind nur dann erfolgreich, wenn das UserDB ein "UID" -Feld zurückgibt
  # entspricht der UID des Anruferprozesses. Auch wenn die UID oder GID des Anrufers mit dem übereinstimmen
  # Die UID von Sockel oder die Suche ist erfolgreich. Alles andere verursacht einen Versagen.
  # 
  # Um dem Anrufer die vollständigen Berechtigungen für die Suche nach allen Benutzern zu geben, setzen Sie den Modus auf
  # Etwas anderes als 0666 und Dovecot lässt den Kernel das durchsetzen
  # Berechtigungen (z. B. 0777 ermöglicht allen vollen Berechtigungen).
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # Der Auth -Work -Prozess wird standardmäßig als Root ausgeführt, damit er zugreifen kann
  # /etc/Shadow. Wenn dies nicht erforderlich ist, sollte der Benutzer auf geändert werden
  #  $default_internal_user.
  # User = root
}

service dict {
  # Wenn der Diktatproxy verwendet wird, sollten E -Mail -Prozesse zu Zugang zu seiner Sockel.
  # Zum Beispiel: Modus = 0660, Group = vmail und global mail_access_groups = vmail
  unix_listener dict {
    # Modus = 0600
    # Benutzer =
    # Gruppe =
  }
}
Stellen Sie erneut sicher, dass Sie die Domain in all diesen Dateien femmebabe.com durch die von Ihnen ausgewählte Domain ersetzen. Bearbeiten Sie die nächste Datei, die Konfiguration von Dovecot,

nano config/etc_dovecot_dovecot
Und fügen Sie diese Zeilen hinzu

## Ovekot -Konfigurationsdatei

# Wenn Sie es eilig haben, finden Sie http://wiki2.dovecot.org/quickConfiguration

# Der Befehl "doveConf -n" gibt eine saubere Ausgabe der geänderten Einstellungen. Benutze es
# Anstelle von Kopieren und Einfügen von Dateien, wenn Sie in die doveCot -Mailingliste veröffentlichen.

# '# 'Charakter und alles, nachdem es als Kommentare behandelt wurde. Zusätzliche Räume
# und Registerkarten werden ignoriert. Wenn Sie eines dieser explizit verwenden möchten, setzen Sie die
# value inside quotes, eg.: key = "# Char und Trailing Whitespace "

# Die meisten (aber nicht alle) Einstellungen können durch verschiedene Protokolle und/oder überschrieben werden
# Quell-/Ziel -IPS durch Platzieren der Einstellungen in Abschnitten, zum Beispiel:
# Protokoll IMAP {}, Lokal 127.0.0.1 {}, Remote 10.0.0.0/8 {}

# Standardwerte werden für jede Einstellung angezeigt. Es ist nicht erforderlich, um sich zu entwickeln
# diese. Dies sind jedoch Ausnahmen dazu: keine Abschnitte (z. B. Namespace {})
# oder Plugin -Einstellungen werden standardmäßig hinzugefügt, sie werden nur als Beispiele aufgeführt.
# Pfade sind auch nur Beispiele, bei denen die tatsächlichen Standardeinstellungen auf Konfiguration basieren
# Optionen. Die hier aufgeführten Pfade sind für die Konfiguration von -prefix =/usr
# --Sysconfdir =/etc--localStatedir =/var

# Aktivieren Sie installierte Protokolle
!include_try /usr/share/dovecot/protocols.d/*.protocol

# Eine Komma -getrennte Liste von IPs oder Hosts, in denen sie Verbindungen anhören können.
# "*" hört in allen IPv4 -Schnittstellen zu, "::" hört in allen IPv6 -Schnittstellen zu.
# Wenn Sie nicht defekten Ports oder etwas Komplexeres angeben möchten,
# bearbeiten conf.d/master.conf.
# Hören = *, ::

# Basisverzeichnis, wo Laufzeitdaten gespeichert werden sollen.
# Base_dir =/var/run/doecot/

# Name dieser Instanz. In Multi-Instance-Setup Doveadm und andere Befehle
# kann -i <instance_name> verwenden, um auszuwählen, welche Instanz verwendet wird (eine Alternative
# to -c <config_path>). Der Instanzname wird auch zu Dovecot -Prozessen hinzugefügt
# in PS -Ausgang.
# instance_name = dovecot

# Begrüßungsnachricht für Kunden.
# login_greeting = dovecot bereit.

# Space getrennte Liste der vertrauenswürdigen Netzwerkbereiche. Verbindungen von diesen
# IPs dürfen ihre IP -Adressen und Ports überschreiben (zur Protokollierung und
# für Authentifizierungsprüfungen). disable_plaintext_auth wird ebenfalls ignoriert für
# Diese Netzwerke. Normalerweise geben Sie hier Ihre IMAP -Proxy -Server an.
# login_trusted_networks =

# Space getrennte Liste der Anmeldungszugriffsprüfungen (z. B. tcpwrap)
# login_access_sockets =

# Mit Proxy_Maybe = Ja, wenn das Proxy -Ziel einem dieser IPs entspricht, tun Sie dies nicht
# stellvertretend. Dies ist normalerweise nicht erforderlich, kann aber nützlich sein, wenn das Ziel
# IP ist z. IP eines Lastausgleichs.
# auth_proxy_self =

# Zeigen Sie mehr ausführliche Prozesstitel (in PS). Zeigt derzeit den Benutzernamen an und
# IP -Adresse. Nützlich, um zu sehen, wer tatsächlich die IMAP -Prozesse verwendet
# (zB freigegebene Postfächer oder wenn die gleiche UID für mehrere Konten verwendet wird).
# Verbose_proctle = gut

# Sollten alle Prozesse getötet werden, wenn der Masterprozess für den Haltestand von Dovecot abgeschaltet wird.
# Wenn Sie dies auf "Nein" setzen
# vorhandene Client -Verbindungen zum Schließen erzwingen (obwohl dies auch sein könnte
# Ein Problem, wenn das Upgrade z. wegen einer Sicherheitsfixierung).
# schadendown_clients = ja

# Wenn ungleich Null E-Mail-Befehle über so viele Verbindungen zum Doveadm-Server ausführen,
# anstatt sie direkt im gleichen Prozess auszuführen.
# DEVEADM_WERKER_COUNT = 0
# UNIX -Socket oder Host: Port verwendet, um eine Verbindung zum Doveadm -Server herzustellen
# DOVEADM_SOCKET_PATH = DOVEADM-SERVER

# Space getrennte Liste der Umgebungsvariablen, die auf dem Devecot erhalten bleiben
# Startup und weiter an alle ihre Kinderprozesse weitergegeben. Sie können auch geben
# Key = Wertpaare, um immer bestimmte Einstellungen festzulegen.
# Import_Environment = TZ

## 
## Wörterbucheinstellungen
## 

# Wörterbuch kann verwendet werden, um Key = Value -Listen zu speichern. Dies wird von mehreren verwendet
# Plugins. Auf das Wörterbuch kann entweder direkt oder obwohl a zugegriffen werden
# Wörterbuchserver. Die folgenden DICT -Blockkarten -Wörterbuchnamen zu URIs
# Wenn der Server verwendet wird. Diese können dann mit URIs im Format verwiesen werden
# "Proxy :: <Name>".

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

# Der größte Teil der tatsächlichen Konfiguration wird unten enthalten. Die Dateinamen sind
# Zuerst nach ihrem ASCII -Wert sortiert und in dieser Reihenfolge analysiert. Die 00-Prefixes
# In Dateinamen sollen es einfacher werden, die Bestellung zu verstehen.
!include conf.d/*.conf

# Eine Konfigurationsdatei kann auch versucht werden, ohne Fehler aufzunehmen, wenn ein Fehler angezeigt wird, wenn
# es ist nicht gefunden:
!include_try local.conf

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

protocols = imap pop3

# Ermöglicht DEVECOT, alle Eingabeverbindungen anzuhören (IPv4 / IPv6).

listen = *, ::
Fügen Sie dem Dovecot -Benutzer ein Passwort hinzu:

nano config/etc_dovecot_passwd
Der erste Teil der Akte vor dem Dickdarm ist der Benutzername. Der letzte Teil, "IhrPassword", bezeichnet das Passwort, das Sie Ihrem Mailserver geben möchten.

team:{plain}yourpassword
Als nächstes die Opendkim -Konfiguration

nano config/etc_opendkim.conf
Und fügen Sie diese Zeilen hinzu:

# Dies ist eine grundlegende Konfiguration für die Unterzeichnung und Überprüfung. Es kann leicht sein
# angepasst an eine grundlegende Installation. Siehe Opendkim.conf (5) und
# /usr/share/doc/opendkim/examples/opendkim.conf.Sample für die vollständige
# Dokumentation der verfügbaren Konfigurationsparameter.

Syslog			yes
SyslogSuccess		yes
# Logwhy nein

# Häufige Signier- und Überprüfungsparameter. In Debian ist der "From" Header
# übergenannt, weil es oft der Identitätsschlüssel ist, der von Reputation Systems verwendet wird
# und damit etwas sicherheitsempfindlich.
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# Signierdomäne, Selektor und Schlüssel (erforderlich). Zum Beispiel Unterzeichnung durchführen
# Für Domain "example.com" mit Selector "2020" (2020._Domainkey.example.com),
# Verwenden des privaten Schlüssels in /etc/dkimkeys/example.private. Mehr granular
# Setup -Optionen finden Sie in /usr/share/doc/opendkim/readme.opendkim.
# Domain Beispiel.com
# Selektor 2020
# KeyFile /etc/dkimkeys/example.private

# In Debian läuft Opendkim als Benutzer "Opendkim". Eine Ummask von 007 ist erforderlich, wenn
# Verwenden einer lokalen Sockel mit MTAs, die als nicht privilegierte Zugriff auf den Sockel zugreifen
# Benutzer (beispielsweise Postfix). Möglicherweise müssen Sie den Gruppen Benutzer "Postfix" hinzufügen
# "Opendkim" in diesem Fall.
UserID			opendkim
UMask			007

# Socket für die MTA -Verbindung (erforderlich). Wenn sich der MTA in einem Chroot -Gefängnis befindet,
# Es muss sichergestellt werden, dass die Steckdose zugänglich ist. In Debian läuft Postfix in
# ein chroot in/var/spool/postfix, daher müsste ein Unix -Socket sein
# Konfiguriert wie in der letzten Zeile unten gezeigt.
# Socket Local: /run/opendkim/opendkim.sock
# Socket Inet: 8891@localhost
# Socket Inet: 8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Hosts, die unterschreiben und nicht überprüfen können, ist der Standard 127.0.0.1. Siehe das
# Betriebsabschnitt von Opendkim (8) Weitere Informationen.
# Internalhosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# Der Vertrauensanker ermöglicht DNSSEC. In Debian wird die Vertrauens -Ankerdatei bereitgestellt
# durch das Paket DNS-Root-Data.
TrustAnchorFile		/usr/share/dns/root.key
# Namenserver 127.0.0.1

# Kartendomänen von Adressen zu Schlüssel, zum Signieren von Nachrichten verwendet werden
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Eine Reihe interner Hosts, deren Mail unterschrieben werden sollte
InternalHosts       /etc/opendkim/trusted.hosts

nano config/etc_default_opendkim
Und fügen Sie diese Zeilen hinzu

# Hinweis: Dies ist eine Legacy -Konfigurationsdatei. Es wird nicht vom Opendkim verwendet
# Systemd Service. Bitte verwenden Sie die entsprechenden Konfigurationsparameter in
# /etc/opendkim.conf stattdessen.
# 
# Zuvor würde man die Standardeinstellungen hier bearbeiten und dann ausführen
# /lib/opendkim/opendkim.service.generate, um Systemd -Override -Dateien an zu generieren
# /etc/systemd/system/opendkim.service.d/override.conf und
# /etc/tmpfiles.d/opendkim.conf. Während dies noch möglich ist, ist es jetzt jetzt
# Empfohlen, um die Einstellungen direkt in /etc/opendkim.conf anzupassen.
# 
# DAEMON_OPTS=""
# Wechseln Sie zu/var/spool/postfix/run/opendkim, um eine UNIX -Socket mit zu verwenden
# Postfix in einem Chroot:
# Rundir =/war/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Überzeugung, um einen alternativen Sockel anzugeben
# Beachten Sie, dass die Einstellung dies in Opendkim.conf überschreibt
# Standard:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Hören Sie sich alle Schnittstellen auf Port 54321 an:
# SOCKET=inet:54321
# Hören Sie sich Loopback auf Port 12345 an:
# SOCKET=inet:12345@localhost
# Hören ist 192.0.2.1 ist Port 12345:
# SOCKET=inet:12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Wenn wir bereit sind, unseren Postfix -Server einzurichten, führen wir den folgenden Code mit dem entsprechenden Domänennamen aus. Erstellen Sie zunächst ein Skript

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
Bearbeiten Sie nun in Nano, dem Texteditor diese Datei, damit Sie Ihren Domain -Namen anstelle von femmebabe.com enthält.

# !
# Setup 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}'
Führen Sie nun das ausgefüllte Skript aus, um Postfix, Opendkim und Dovecot zu konfigurieren.

./scripts/postfixsetup
Sobald dieses Skript ausgeführt wurde, kopieren Sie die letzte Zeile, die es druckt, und fügen Sie es in Ihre DNS -Konfiguration als Wert für sendonly._domainkey ein. Dies ist der Opendkim -Schlüssel, mit dem Sie Ihre Domain beim Senden sicherer Mails identifizieren. Eindrucksvoll! Innerhalb weniger Tage sollten Sie in der Lage sein, E -Mails vom Server zu senden, vorausgesetzt, alles ist korrekt konfiguriert. Wenn Sie den DNS nur für Ihren Mailserver konfiguriert haben, sollte es weniger als 72 Stunden dauern, bis die Datensätze aktualisiert werden können. Es ist normalerweise viel schneller. Sie können überprüfen, ob Ihr Server mit diesem Befehl funktioniert, und liefert Ihre E -Mail:

echo “test” | mail -s “Test Email” youremail@gmail.com
Wenn alles richtig funktioniert, sollten Sie in der Lage sein, E -Mails mit Ihrem Server zu senden. Wenn es nicht funktioniert, schauen Sie sich die Protokolle an, um zu sehen, wie der Fehler aussehen könnte.

tail –lines 150 /var/log/mail.log
Dies bietet ausführliche Informationen über Mail, die vom Server gesendet werden und ob es ordnungsgemäß funktioniert. Sie sollten auch in der Lage sein, die E -Mail in Ihrem Posteingang anzusehen. Wenn sie nicht vorhanden ist, überprüfen Sie Ihren Spam -Ordner. Sie müssen Ihre Einstellungen auch in Ihren Einstellungen konfigurieren.Py, damit Ihr E -Mail -Server mit Ihrer Django -App, dem Projekt, sprechen kann. Fügen Sie diese Zeilen in Ihren Einstellungen hinzu oder ersetzen Sie

EMAIL_HOST = DOMAIN
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = 'team@femmebabe.com'
EMAIL_HOST_USER = 'team' # 'Love@mamashen.com'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
Beachten Sie, dass wir eine Konfigurationsdatei verwenden, um das Kennwort zu erhalten. Laden wir diese Datei in den Einstellungen wie folgt zu Beginn der Datei .::

import os
import json

# Offen und laden Sie die Konfiguration
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Lassen Sie uns diese Datei erstellen und einen geheimen Schlüssel sowie das E -Mail -Passwort hinzufügen. Verwenden Sie diesen Befehl, um einen geheimen Schlüssel zu generieren, mit jeder Länge, die Sie am Ende mögen:

openssl rand -base64 64
Kopieren Sie nun den Text, den OpenSSL generiert und bearbeiten /etc/config.json

sudo nano /etc/config.json
Fügen Sie Ihrer Datei die folgenden Zeilen hinzu, wobei der Schlüssel, der als geheimes Schlüssel erzeugt wird, geöffnet wird.

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
Das JSON -Format ist einfach und einfach zu bedienen. Wir können auch andere Schlüssel deklarieren, die wir in unserem Projekt so verwenden möchten allein aus unserem Projektverzeichnis. Dies ist eine empfohlene Praxis für API -Schlüssel, von denen wir hier mehr als einige verwenden werden. Sie möchten auch Ihr Projekt sichern, um sicherzustellen, dass alles gespeichert ist, und Sie können Ihre Arbeit später wiederherstellen, selbst wenn Sie keinen Server mehr mieten möchten.

sudo backup
Versuchen Sie nun, eine HTML -E -Mail aus dem Webserver zu senden, sodass das Senden von Sendungen aus der Befehlszeile funktioniert. Fragen Sie Ihre Benutzerinstanz in der Shell ab und senden Sie eine HTML -E -Mail an diesen Benutzer über Django. Ändern Sie meinen Namen im Code Charlotte in Ihren Benutzernamen.

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()
Wenn der erste Befehl nicht funktioniert, stellen Sie sicher

source venv/bin/activate
Vorausgesetzt, alles ist korrekt eingerichtet, Sie erhalten jetzt eine willkommene E -Mail in Ihrem Mailbox, die von Ihrer Web -App gesendet werden. Gute Arbeit! Du hast einen langen Weg zurückgelegt. Ich wollte hinzufügen, wenn Sie jemals mit Fehlern zu kämpfen haben, während Sie an einem solchen Projekt arbeiten, zögern Sie nicht, nach Antworten zu suchen und um Hilfe zu bitten. Google sind unter anderem großartige Ressourcen, um nach Programmierhilfe zu suchen. Suchen Sie einfach nach dem Fehler, den Sie erhalten, und Sie können sehen, wie andere Personen das Problem lösen. Außerdem können Sie mich, Ihre Pädagogen (Lehrer, Professoren, Tutoren), alle Kollegen im Internet, die für die Programmierhilfe zur Verfügung stehen, kontaktieren oder dieses Buch erneut oder andere Ressourcen konsultieren, um Lösungen für die Probleme zu finden, die Sie erleben, mich erneut mit mir oder anderen Ressourcen wenden. Ich verstehe, dass dies nicht einfach ist, aber selbst wenn Sie so weit gelesen haben und keinen Code schreiben, lernen Sie viel über das Erstellen einer Web -App von Grund auf. Klopfen Sie sich auf den Rücken, Sie machen eine großartigeArbeit. Vielen Dank, dass Sie sich die Zeit genommen haben, diesen Webentwicklungshandbuch der dritten Ausgabe zu lesen. In zukünftigen Ausgaben werde ich weitere wichtige Beispiele aufnehmen, die zu Beginn des Dokuments diskutiert werden, und wir werden viel tiefer in die Welt der Software- und Hardwareentwicklung eintauchen. Seien Sie gespannt auf das, was kommen wird, und ich freue mich darauf, Ihnen beizubringen, wie Sie unglaubliche Software aufbauen können. Wir sehen uns im nächsten






Schließen
Seite 1
Springen
Siehe vollständigen Artikel
Lesen Sie weiter

Kaufen | Kaufen Sie mit Krypto



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


(Klicken Sie auf oder tippen Sie auf, um das Bild herunterzuladen)
Professionelle Unterhaltung, Fotos, Videos, Audio, Livestreaming und ungezwungenes Gameplay sowie ID -Scannen, Webentwicklung und Leihmutterschaftsdienste.

Lassen Sie mir einen Tipp in Bitcoin mit dieser Adresse: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

Nutzungsbedingungen