Nachricht - Besuchen Sie die Website
Praktisches webbasiertes Deep Learning und Sicherheit anhand eines Beispiels, dritte Ausgabe, Charlotte Harper, 3. Juli 2024, aktualisiert/konvertiert am 3. Juni 2025, Vorwort: Sicherheitsüberlegungen beim Erstellen von Software für das Web sind ein wichtiger Bestandteil der Planung und Ausführung eines jeden Webentwicklers bei der Entwicklung eines Prototyps, der zuverlässig, stabil und für praktische Zwecke nützlich ist. Das DOM (Document Object Markup) mit seiner Implementierung von HTML, JavaScript und CSS sowie der Backend-Software, die Python, C/C++, Java und Bash implementiert, gibt Webentwicklern die Freiheit und Macht, eine Vielzahl von Projekten zu erstellen, die Kreativität zum Ausdruck bringen, Benutzerfreundlichkeit und Funktionalität bieten, Bescheidenheit und Charakter darstellen und Benutzerfreundlichkeit sowie Komfort und wichtige Dienste bieten, die alle für den durchschnittlichen Joe attraktiv sind, den Endbenutzer, der Zeit totschlagen oder etwas im Internet erledigen möchte, normalerweise auf einem Touchscreen-Smartphone. Die meisten Menschen würden nicht einmal wissen, wo sie anfangen sollen, wenn sie eine Website von Grund auf erstellen möchten. Sie neigen dazu, mit der Website einer anderen Person zu beginnen und etwas zu erstellen, das hinsichtlich Funktionalität, Zuverlässigkeit, Benutzerfreundlichkeit und vor allem Kreativität eingeschränkt ist, wenn ihnen die neuesten leistungsstarken Tools zur Verfügung stehen könnten, um etwas Nützliches zu erstellen, ohne Zeit mit dem Drücken von Knöpfen zu verschwenden, und vor allem ohne Geld für teure Abonnements für Software zu verschwenden, die aufgrund der Einschränkungen in der Benutzerfreundlichkeit und Flexibilität ohnehin nur wenige Leute nutzen wollten. Wenn Sie ein paar Minuten Zeit haben, dieses Buch durchzulesen und zu erfahren, was ich Ihnen beibringen möchte, oder sogar persönlich mit mir über Ihre Ziele sprechen und eine Orientierung in die richtige Richtung erhalten möchten, und motiviert sind, das Codieren und Schreiben Ihrer eigenen Software zu lernen, nehmen Sie dieses Buch mit nach Hause und nehmen Sie sich etwas Zeit, um zu lernen, wie Sie die nächste einflussreiche, leistungsstarke, optimierte und wichtige Webanwendung erstellen, eine Website, die ganz auf Sie ausgerichtet ist und genau das tut, was Sie wollen und die Bedürfnisse Ihres Publikums erfüllt. Über mich: Ich bin ein Softwareentwickler mit umfassender Erfahrung in C/C++, Java, Python, HTML, CSS und JavaScript. Ich erstelle Websites, die die Leute nutzen wollen, die sie besuchen wollen und die sogar süchtig danach werden, sie zu nutzen, nur um zu lernen, neu zu erstellen und die Zeit totzuschlagen, und was am wichtigsten ist, ich verkaufe Software. Wenn Sie eine genaue Vorstellung davon hätten, wie eine Website aussehen und funktionieren soll, Sie bereit wären, mich zu unterstützen, damit ich meine eigenen Bedürfnisse erfüllen kann, während ich Ihre erfülle, und Sie bereit sind, die Kosten für den Betrieb einer Website selbst zu tragen, würde ich Ihnen das nächste YouTube, TikTok, Twitter, Google oder sogar eine High-Tech-Sicherheits-App erstellen, auf die nur Sie zugreifen können. Anstatt zu versuchen, Ihnen meine Zeit zu verkaufen, versuche ich, Ihre zu kaufen: Ich möchte Sie dazu überreden, mit den bereits vorhandenen Informationen selbst eine App (Website) zu erstellen, und Ihnen beibringen, was Sie brauchen, um ein unabhängiger Softwareentwickler oder Unternehmer zu sein und eine erfolgreiche Karriere in dem von Ihnen gewünschten Bereich zu führen. Und lassen Sie mich klarstellen: Die Ausbildung, die ich Ihnen gebe, wird informell sein. Sie könnten zur Schule gehen und all dies mit einer formellen Ausbildung lernen oder sogar dieses Buch in der Schule lesen, Ihre Aufgaben erledigen und viel von Ihrer Ausbildung mitnehmen, aber ich werde Sie nicht offiziell auf den heißen Stuhl setzen und Sie bitten, Aufgaben zu erledigen. Ich bin nicht Ihr Professor, Sie können mich wie einen Freund betrachten, der Sie zu einer Karriere führen möchte, die von Ihrem persönlichen Erfolg getragen wird. Und ich verkaufe Ihnen auch keinen Erfolg, Sie müssen ihn mit Ihrer Zeit kaufen. Das Erlernen des Codierens hat eine steile Lernkurve und war nie einfach und sollte es auch nie sein. Sie müssen so hart wie möglich arbeiten und weiterhin versuchen, scheitern und es erneut versuchen, auch wenn Sie frustriert sind, um selbst Apps zu lernen und zu erstellen. Das liegt in der Natur des Codes selbst. Der Code wird von einem Compiler ausgeführt, der dem Programmierer Fehlermeldungen ausgibt, die Ihnen das Codieren beibringen, selbst wenn Sie den Fehler einfach in Ihre Suchmaschine kopieren und die Beispiele anderer Leute lesen. Und ich muss sagen, man muss nicht extrem reich oder klug sein,erfolgreich oder sogar detailorientiert oder organisiert, um eine App zu erstellen. Der Computer übernimmt diese Organisation für Sie. Sie müssen nur den Versuch und Irrtum durchhalten, den Fokus behalten und hart an dem arbeiten, was Sie tun, und schon werden Sie in all 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 Sichtweisen aus diesem Buch ging. Wer bin ich genau? Das ist eine komplizierte Frage. Ich selbst bin mir darüber nicht im Klaren, da ich an Erkrankungen leide, die es mir zeitweise schwer machen, dieses Buch überhaupt zu programmieren oder zu schreiben, während ich gleichzeitig mit Herausforderungen in Bezug auf Sozialisation und Identitätsprobleme konfrontiert bin, die mir das Leben erschweren, wenn es darum geht, mich vorzustellen. Kurz gesagt, wenn Sie dieses Buch lesen, haben Sie es mit nach Hause genommen, weil Sie es durchgeblättert haben und dachten, es sei nützlich, oder selbst wenn Sie nur bis hierhin gelesen haben, bin ich für Sie eine gleichgesinnte Person, die möchte, dass Sie in allem, was Sie tun, Erfolg haben. Ich bin selbst Ingenieur, Softwareentwickler und Student, und ich schreibe dieses Buch für andere Studenten, die ihr Leben einfacher machen möchten, indem sie ein Handbuch mit der Software haben, die sie benötigen, um ihnen das Leben zu erleichtern, indem sie Beispiele zum Kopieren geben, die wie ein großes Puzzle zu einer funktionierenden, nützlichen, großen, funktionalen, zusammenhängenden und ansprechenden App zusammenpassen, die unabhängig von der Branche zum Erfolg führen kann. Im Großen und Ganzen mache ich Folgendes: Ich baue Apps, die mir und anderen Menschen zum Erfolg verhelfen. Ich bin auch Autor, obwohl dies meine erste Veröffentlichung ist, die ich fertigstellen möchte, um mein Portfolio zu einem nützlichen Dokument zusammenzustellen, und ich bin auch Künstler. Ich gebe Ihnen das zu, ich bin irgendwie ein seltsamer Mensch. Ich bin nicht perfekt, ich bin mit dem Gesetz in Konflikt geraten und habe sogar dazu geführt, dass ich Colleges, Universitäten und Bundesstaaten verlassen habe, um mir mit mehr Erfolg einen Namen zu machen. Ich bin von Geburt an eine Frau, ich trage Make-up, mache Fotos von mir, trage Kleider und andere Damenbekleidung und bin mir meiner Natur als Frau bewusst. Ich hatte in der Vergangenheit Probleme mit anderen Leuten, die zu Schwierigkeiten beim Schreiben und Erstellen von Webanwendungen führten, und ich entschuldige mich, dass ich dieses Buch nicht früher in die Hände bekommen konnte: Sie haben es gebraucht. Sie werden Code lesen und schreiben wollen, der wie meiner aussieht und wie meiner funktioniert und das Gleiche tut, aber sogar noch besser, denn wenn Sie es sich leisten können, dieses Buch zu kaufen, anstatt wie ich Ihre Tastatur zu zerquetschen, nur um selbst ein Buch zu erstellen und Geld dafür zu verlangen, haben Sie die Ressourcen, die Sie brauchen, um in Ihrem Leben erfolgreich zu sein. Ich hatte alle möglichen Probleme mit der Familie, dem Gesundheitszustand, den Ärzten, den Medien und dem Gesetz, und mein Kodex spiegelt zutiefst den Kampf zwischen Feminismus und weiblicher Natur in einer gespaltenen und frustrierten Welt wider. Allerdings liegt mir dieses Buch sehr am Herzen, mein Baby, mein Portfolio und mein Lebensunterhalt, daher schätze ich Ihre Aufmerksamkeit, wenn Sie den Text mit nach Hause nehmen und sorgfältig darüber nachdenken, um von mir zu lernen. Bitte bedenken Sie, dass ich nicht perfekt bin. Dieses Buch wird Fehler, Überarbeitungen und Neuauflagen enthalten und Sie müssen so gut wie möglich mit Ihrem logischen Gehirn denken, um ein erfolgreiches Erlebnis mit meinem Schreiben zu haben. Verstehen Sie auch, dass ich es gut mit Ihnen meine, auch wenn Sie beim Schreiben vor Herausforderungen stehen. Stellen Sie sich das so vor: Wenn Sie einfach ein Computersystem mieten können, um alles zu tun, was Sie sich im digitalen Raum vorstellen können, alle Informationen, auf die Sie stoßen, zu speichern, sie zu analysieren und zu organisieren und sie zu verstehen, werden Sie unweigerlich auf Schwierigkeiten mit den Informationen stoßen, die Sie aufnehmen und sogar veröffentlichen. Ich erzähle Ihnen das, weil ich auf die gleichen Schwierigkeiten stoße. Benutzen Sie dieses Buch auf eigene Gefahr, arbeiten Sie mit Ihrer Community und den Communitys, die Ihnen zur Verfügung stehen, zusammen, um Software in einer sicheren Umgebung zu entwickeln, und nehmen Sie die Dinge nicht persönlich, wenn Sie scheitern oder sogar auf die falsche Weise Erfolg haben: So bin ich so weit gekommen und warum ich Ihnen diesen Text präsentieren und Ihnen zum Erfolg verhelfen kann, ohne auf einen Weg des Wahnsinns abzuweichenDas macht mich ruiniert, zerrissen und ausgefranst, während ich auf die alltäglichen Probleme stoße, die jeder auf globaler Ebene hat, dank der parallelen globalen Skala des Netzwerks, in dem wir arbeiten werden, dem Internet. Mit nur wenigen Worten werden Sie vielleicht nicht ganz sicher sein, wer ich bin, aber ich ermutige Sie, weiterzulesen. Sie werden mich kennenlernen, wenn Sie weiter lesen und mich verstehen, während Sie Ihr...
उदाहरण के तौर पर व्यावहारिक वेब आधारित गहन शिक्षा और सुरक्षा

Praktisches webbasiertes Deep Learning und Sicherheit anhand von Beispielen Dritte Auflage Charlotte Harper 3. Juli 2024 Aktualisiert/konvertiert am 3. Juni 2025

Vorwort:

Sicherheitsüberlegungen beim Erstellen von Software für das Web sind ein wichtiger Teil der Planung und Ausführung eines jeden Webentwicklers bei der Entwicklung eines Prototyps, der zuverlässig, stabil und für praktische Zwecke nützlich ist. Das DOM (Document Object Markup) mit seiner Implementierung von HTML, JavaScript und CSS sowie der Backend-Software, die Python, C/C++, Java und Bash implementiert, gibt Webentwicklern die Freiheit und Macht, eine Vielzahl von Projekten zu erstellen, die Kreativität zum Ausdruck bringen, Benutzerfreundlichkeit und Funktionalität bieten, Bescheidenheit und Charakter darstellen und Benutzerfreundlichkeit sowie Komfort und wichtige Dienste bieten, die alle für den durchschnittlichen Joe attraktiv sind, den Endbenutzer, der Zeit totschlagen oder etwas im Internet erledigen möchte, normalerweise auf einem Touchscreen-Smartphone. Die meisten Menschen würden nicht einmal wissen, wo sie anfangen sollen, wenn sie eine Website von Grund auf erstellen möchten. Sie neigen dazu, mit der Website einer anderen Person zu beginnen und etwas zu erstellen, das hinsichtlich Funktionalität, Zuverlässigkeit, Benutzerfreundlichkeit und vor allem Kreativität eingeschränkt ist, wenn ihnen die neuesten leistungsstarken Tools zur Verfügung stehen könnten, um etwas Nützliches zu erstellen, ohne Zeit mit dem Drücken von Knöpfen zu verschwenden, und vor allem ohne Geld für teure Abonnements für Software zu verschwenden, die aufgrund der Einschränkungen in der Benutzerfreundlichkeit und Flexibilität ohnehin nur wenige Leute nutzen wollten. Wenn Sie ein paar Minuten Zeit haben, dieses Buch durchzulesen und zu erfahren, was ich Ihnen beibringen möchte, oder sogar persönlich mit mir über Ihre Ziele sprechen und eine Orientierung in die richtige Richtung erhalten möchten, und motiviert sind, das Codieren und Schreiben Ihrer eigenen Software zu lernen, nehmen Sie dieses Buch mit nach Hause und nehmen Sie sich etwas Zeit, um zu lernen, wie Sie die nächste einflussreiche, leistungsstarke, optimierte und wichtige Webanwendung erstellen, eine Website, die ganz auf Sie ausgerichtet ist und genau das tut, was Sie wollen und die Bedürfnisse Ihres Publikums erfüllt.

Über mich: Ich bin ein Softwareentwickler mit umfassender Erfahrung in C/C++, Java, Python, HTML, CSS und JavaScript. Ich erstelle Websites, die die Leute nutzen wollen, die sie besuchen wollen und die sogar süchtig danach werden, sie zu nutzen, nur um zu lernen, neu zu erstellen und die Zeit totzuschlagen, und was am wichtigsten ist, ich verkaufe Software. Wenn Sie eine genaue Vorstellung davon hätten, wie eine Website aussehen und funktionieren soll, Sie bereit wären, mich zu unterstützen, damit ich meine eigenen Bedürfnisse erfüllen kann, während ich Ihre erfülle, und Sie bereit sind, die Kosten für den Betrieb einer Website selbst zu tragen, würde ich Ihnen das nächste YouTube, TikTok, Twitter, Google oder sogar eine High-Tech-Sicherheits-App erstellen, auf die nur Sie zugreifen können. Anstatt zu versuchen, Ihnen meine Zeit zu verkaufen, versuche ich, Ihre zu kaufen: Ich möchte Sie dazu überreden, mit den bereits vorhandenen Informationen selbst eine App (Website) zu erstellen, und Ihnen beibringen, was Sie brauchen, um ein unabhängiger Softwareentwickler oder Unternehmer zu sein und eine erfolgreiche Karriere in dem von Ihnen gewünschten Bereich zu führen. Und lassen Sie mich klarstellen: Die Ausbildung, die ich Ihnen gebe, wird informell sein. Sie könnten zur Schule gehen und all dies mit einer formellen Ausbildung lernen oder sogar dieses Buch in der Schule lesen, Ihre Aufgaben erledigen und viel von Ihrer Ausbildung mitnehmen, aber ich werde Sie nicht offiziell auf den heißen Stuhl setzen und Sie bitten, Aufgaben zu erledigen. Ich bin nicht Ihr Professor, Sie können mich wie einen Freund betrachten, der Sie zu einer Karriere führen möchte, die von Ihrem persönlichen Erfolg getragen wird. Und ich verkaufe Ihnen auch keinen Erfolg, Sie müssen ihn mit Ihrer Zeit kaufen. Das Erlernen des Codierens hat eine steile Lernkurve und war nie einfach und sollte es auch nie sein. Sie müssen so hart wie möglich arbeiten und weiterhin versuchen, scheitern und es erneut versuchen, auch wenn Sie frustriert sind, um selbst Apps zu lernen und zu erstellen. Das liegt in der Natur des Codes selbst. Der Code wird von einem Compiler ausgeführt, der dem Programmierer Fehlermeldungen ausgibt, die Ihnen das Codieren beibringen, selbst wenn Sie den Fehler einfach in Ihre Suchmaschine kopieren und die Beispiele anderer Leute lesen. Und ich muss sagen, man muss nicht besonders reich, klug, erfolgreich oder auch nur detailorientiert oder organisiert sein, um eine App zu erstellen. Der Computer übernimmt diese Organisation für Sie. Sie müssen nur den Versuch und Irrtum durchhalten, den Fokus behalten und hart an dem arbeiten, was Sie tun, und schon werden Sie in all 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 Sichtweisen aus diesem Buch ging. Wer bin ich genau? Das ist eine komplizierte Frage. Ich selbst bin mir darüber nicht im Klaren, da ich an Erkrankungen leide, die es mir zeitweise schwer machen, dieses Buch überhaupt zu programmieren oder zu schreiben, während ich gleichzeitig mit Herausforderungen in Bezug auf Sozialisation und Identitätsprobleme konfrontiert bin, die mir das Leben erschweren, wenn es darum geht, mich vorzustellen. Kurz gesagt, wenn Sie dieses Buch lesen, haben Sie es mit nach Hause genommen, weil Sie es durchgeblättert haben und dachten, es sei nützlich, oder selbst wenn Sie nur bis hierhin gelesen haben, bin ich für Sie eine gleichgesinnte Person, die möchte, dass Sie in allem, was Sie tun, Erfolg haben. Ich bin selbst Ingenieur, Softwareentwickler und Student, und ich schreibe dieses Buch für andere Studenten, die ihr Leben einfacher machen möchten, indem sie ein Handbuch mit der Software haben, die sie benötigen, um ihnen das Leben zu erleichtern, indem sie Beispiele zum Kopieren geben, die wie ein großes Puzzle zu einer funktionierenden, nützlichen, großen, funktionalen, zusammenhängenden und ansprechenden App zusammenpassen, die unabhängig von der Branche zum Erfolg führen kann. Im Großen und Ganzen mache ich Folgendes: Ich baue Apps, die mir und anderen Menschen zum Erfolg verhelfen. Ich bin auch Autor, obwohl dies meine erste Veröffentlichung ist, die ich fertigstellen möchte, um mein Portfolio zu einem nützlichen Dokument zusammenzustellen, und ich bin auch Künstler. Ich gebe Ihnen das zu, ich bin irgendwie ein seltsamer Mensch. Ich bin nicht perfekt, ich bin mit dem Gesetz in Konflikt geraten und habe sogar dazu geführt, dass ich Colleges, Universitäten und Bundesstaaten verlassen habe, um mir mit mehr Erfolg einen Namen zu machen. Ich bin von Geburt an eine Frau, ich trage Make-up, mache Fotos von mir, trage Kleider und andere Damenbekleidung und bin mir meiner Natur als Frau bewusst. Ich hatte in der Vergangenheit Probleme mit anderen Leuten, die zu Schwierigkeiten beim Schreiben und Erstellen von Webanwendungen führten, und ich entschuldige mich, dass ich dieses Buch nicht früher in die Hände bekommen konnte: Sie haben es gebraucht. Sie werden Code lesen und schreiben wollen, der wie meiner aussieht und wie meiner funktioniert und das Gleiche tut, aber sogar noch besser, denn wenn Sie es sich leisten können, dieses Buch zu kaufen, anstatt wie ich Ihre Tastatur zu zerquetschen, nur um selbst ein Buch zu erstellen und Geld dafür zu verlangen, haben Sie die Ressourcen, die Sie brauchen, um in Ihrem Leben erfolgreich zu sein. Ich hatte alle möglichen Probleme mit der Familie, dem Gesundheitszustand, den Ärzten, den Medien und dem Gesetz, und mein Kodex spiegelt zutiefst den Kampf zwischen Feminismus und weiblicher Natur in einer gespaltenen und frustrierten Welt wider. Allerdings liegt mir dieses Buch sehr am Herzen, mein Baby, mein Portfolio und mein Lebensunterhalt, daher schätze ich Ihre Aufmerksamkeit, wenn Sie den Text mit nach Hause nehmen und sorgfältig darüber nachdenken, um von mir zu lernen. Bitte bedenken Sie, dass ich nicht perfekt bin. Dieses Buch wird Fehler, Überarbeitungen und Neuauflagen enthalten und Sie müssen so gut wie möglich mit Ihrem logischen Gehirn denken, um ein erfolgreiches Erlebnis mit meinem Schreiben zu haben. Verstehen Sie auch, dass ich es gut mit Ihnen meine, auch wenn Sie beim Schreiben vor Herausforderungen stehen. Stellen Sie sich das so vor: Wenn Sie einfach ein Computersystem mieten können, um alles zu tun, was Sie sich im digitalen Raum vorstellen können, alle Informationen, auf die Sie stoßen, zu speichern, sie zu analysieren und zu organisieren und sie zu verstehen, werden Sie unweigerlich auf Schwierigkeiten mit den Informationen stoßen, die Sie aufnehmen und sogar veröffentlichen. Ich erzähle Ihnen das, weil ich auf die gleichen Schwierigkeiten stoße. Benutzen Sie dieses Buch auf eigene Gefahr, arbeiten Sie mit Ihrer Community und den Communitys zusammen, die Ihnen zur Verfügung stehen, um Software in einer sicheren Umgebung zu entwickeln, und nehmen Sie die Dinge nicht persönlich, wenn Sie scheitern oder sogar auf die falsche Art und Weise Erfolg haben: So bin ich so weit gekommen und warum ich Ihnen diesen Text bringen und Ihnen zum Erfolg verhelfen kann, ohne auf einen Weg des Wahnsinns abzuweichen, der mich ruiniert, zerrissen und ausgefranst zurücklässt, während ich auf die gewöhnlichen Probleme stoße, die jeder auf globaler Ebene hat, dank der parallelen globalen Skala des Netzwerks, an dem wir arbeiten werden. das Internet. Mit ein paar Worten werden Sie vielleicht nicht so recht wissen, wer ich bin, aber ich ermutige Sie dazu

Lesen Sie weiter, Sie werden mich kennenlernen, während Sie mich weiterhin lesen und verstehen, während Sie Ihre eigenen Projekte entwickeln, um Ihre Arbeit abzuschließen. Für dieses Buch gibt es keine Hausaufgaben, solange Ihre Professoren oder Lehrer Ihnen keine geben. Ich empfehle Ihnen jedoch dringend, beim Mitlesen selbst ein Portfolio mit Projekten sowie ein Abschlussprojekt zu erstellen, das zeigt, wie Sie das Gelernte anwenden können. Mein Abschlussprojekt ist die Grundlage für das meiste, was Sie in diesem Buch lesen werden, da es Code aus meinen früheren Projekten, Code, den ich erstellt und gelernt habe, methodisch von Hand zu schreiben, und eine breite Palette von Ideen und Tipps enthält, die mir dabei geholfen haben, bis zu dem Punkt erfolgreich zu sein, an dem ich eine einfache App erstellen kann, die über alle Funktionen verfügt und wie eine beliebte App aussieht und sich verhält, die Sie vielleicht von Ihren Freunden oder Ihrer Familie im Internet, in der Werbung für Sie oder in den Nachrichten verwenden sehen.

Was dieses Buch ist: Dieses Buch ist ein Tutorial anhand von Beispielen. Hier finden Sie Code, Anweisungen zum Erlernen des Codierens, Informationen zum Debuggen von Code und Beheben von Fehlern, Schritte zur Fehlerbehebung, Anweisungen zum Sichern und Speichern Ihres Codes, zum erneuten Bereitstellen, wenn jemand Ihren Code beschädigt, zum Sichern Ihres Codes, zum Bereitstellen Ihres Codes, zum Erstellen interaktiver Websites, die unterhaltsam, ansprechend und süchtig machend sind, und Sie werden ein Gefühl dafür bekommen, wer ich bin, warum das wichtig ist und wie Sie sich selbst, Ihre App und Ihr Firmenimage sowie die Software, die Sie erstellen, im absolut besten Licht darstellen, um am besten zu sein für Ihre Endbenutzer, die Besucher Ihrer Website, so attraktiv wie möglich zu gestalten. In diesem Buch zeige ich eine Reihe von Beispielen für Softwaredesign mit Schwerpunkt auf dem Web als Plattform und Sicherheit. Wir beginnen die Lernerfahrung, indem wir ein Basisprojekt mithilfe der UNIX-Shell mit Sicherungs- und Skriptfunktionen erstellen. Anschließend untersuchen wir eine einfache Blog-Website, aktualisieren unseren Blog mit Foto- und Videofunktionen und nutzen diese Funktionen, um Sicherheitslösungen mithilfe kostenloser Software einzusetzen, und sichern unseren Server mithilfe eines steckbaren Authentifizierungsmoduls (PAM). Anschließend werden wir uns mit der Handhabung und Verarbeitung von Dateien befassen und uns dabei unter anderem mit Videobearbeitung, Sprachspende, Barcode-Scannen und optischer Zeichenerkennung befassen. Unterwegs werden wir APIs untersuchen, die uns dabei helfen werden, unsere Software mit kostenlosen und kostenpflichtigen Optionen nützlicher und sicherer zu machen. Unterwegs werden wir uns mit physischer Sicherheit und militanten Werkzeugen wie dem Design und der Herstellung von Schusswaffen und Munition befassen, einschließlich Lauf- und Repetierdesign, Turm- und Drohnendesign sowie anderen Prinzipien, die wir in unsere Software im bestehenden Netzwerk integrieren werden, um unsere Software zu schützen und Selbstverteidigung und Widerstandsfähigkeit zu demonstrieren. Unterwegs werden wir Pausen einlegen, um Spiele sowie 2D- und 3D-Rendering-Engines zu entwickeln und mit eingebetteter Hardware anhand von Fallstudienbeispielen grundlegender dimensionaler Rendering-Software bzw. eines in Silikonkautschuk gegossenen elektronischen Vibrationsmassagegeräts zu arbeiten. Dabei werden wir auch bereits verfügbare Machine-Learning-Lösungen einsetzen, um unsere Software besser abzusichern. Wir werden auch für das Internet verfügbare Standardtools einsetzen, um den Prozess zu rationalisieren und zu sichern. Dieses Buch ist ein Leitfaden für Ihren Erfolg beim Erstellen einer Webanwendung und deren Integration in ein professionelles Netzwerk aus Computer- und eingebetteten mechanischen Systemen und insgesamt ein Leitfaden zum Erstellen von Software und eingebetteter Hardware ohne Hintergrundwissen oder Vorerfahrung.

Was dieses Buch nicht ist: Wenn Sie wirklich eine Website haben möchten, können Sie einfach einen einfachen Shop einrichten und verkaufen, was Sie brauchen, einen Blog veröffentlichen, Fotos oder Videos veröffentlichen oder auf andere Weise, ohne jemals eine einzige Codezeile zu schreiben. Dieses Buch ist das nicht. In diesem Buch erfahren Sie, wie Sie Software erstellen, die nützlicher, umfassender, funktionsfähiger und sicherer ist als jede Software, die Sie bereits finden können, da sie die neueste Software bereitstellt, bei der es sich noch um Prototypen handelt, deren Betrieb in einer Größenordnung, in der ältere Unternehmen arbeiten, teuer sein kann und die rückständige, komplizierte Unternehmen nicht anspricht, die gegründet wurden, um Geld für Leute zu verdienen, die eigentlich nichts tun. Wenn Sie dieses Buch genau verfolgen, werden Sie Code schreiben, Code recherchieren, Ihre eigenen Apps erstellen wollen und mit dem, was Sie tun, Geld verdienen. Ich werde mit diesem Buch schon in der Anfangsphase Geld verdienen, weil es Informationen enthält, die die Leute brauchen und lesen wollen und die sie bereits kaufen, wenn sie meine Apps kaufen oder verwenden. Dieses Buch wird keine App für Sie erstellen, aber es weist Sie in die richtige Richtung und rüstet Sie mit den Werkzeugen aus, die Sie benötigen, sowie mit den Fertigkeiten und Tipps, die Ihren eigenen Erfolg beim Erstellen von Software für das Web erleichtern werden, wobei jede Codezeile, die Sie schreiben müssen, als Beispiel dient und bereit ist, in Software zusammengefügt zu werden, die Sie und Ihre Unterstützer, Gäste, Kunden, Freunde, Familie, Besucher, Auftragnehmer und die Menschen im Internet nutzen und unterstützen möchten.

Was Sie lernen werden: In diesem Buch erfahren Sie, wie Sie Software erstellen und verkaufen, wirklich funktionale, nützliche Software, Medienaufzeichnung, Sicherheitsfunktionen wie Gesichtserkennung, Scannen von maschinenlesbaren Zonen-Barcodes, Web-APIs zum Authentifizieren, Aufzeichnen und Rendern von Videos und Fotos sowie den Austausch von Nachrichten wie Bluetooth und Nahfeldkommunikation (NFC). In diesem Buch erfahren Sie, wie Sie einen vernetzten Computer verwenden, wobei der Schwerpunkt auf Debian Linux liegt, wie Sie Bash-Code erstellen, um die Installation und Sicherung Ihrer Software zu einem nahtlosen, automatisierten Kinderspiel zu machen, wie Sie Python-Code als Backend für die Bereitstellung dynamischer Nachrichten erstellen, Dinge mithilfe von CSS-Stilen mit Bootstrap schön gestalten, Benutzeranmeldungen und Interaktivität über vernetzte Geräte ermöglichen, interaktive Medien erstellen und sich mit anderen Websites vernetzen, um Sicherheitsfunktionen wie Textnachrichten zur Überprüfung oder für andere Zwecke, ID-Scanning, Bild- und Videomoderation sowie Datenmikrotransaktionen anzubieten um Ihre Software, Zahlungsabwicklung, Kryptowährungshandel, asynchrone Aufgaben und mehr zu schützen. Sie lernen, wie Sie Ihre eigenen Bluetooth-Geräte mit Batterien, Ladegeräten, Mikrocontrollern, Schaltkreisen, Motoren und Sensoren unter Verwendung von Löt-, Draht- und 3D-gedruckten sowie gegossenen Materialien bauen. Ich werde 3D-Designprinzipien demonstrieren, die auf die additive Fertigung sowie den Werkzeug- und Formenbau angewendet werden, sodass Sie in der Lage sind, Ihre eigenen eingebetteten Hardwaregeräte mit integrierten Batterien, Ladegeräten, elektronischen Schaltkreisen und Funktionsausgängen herzustellen. und vernetzen Sie sie mit Bluetooth und dem Internet. Konkret werden wir zwei Fallstudien untersuchen, ein Vibrationsmassagegerät und eine selbstgebaute Schusswaffe, beide in OpenSCAD programmiert, das als grafische Schnittstelle oder Befehlszeilenprogramm verfügbar ist und für schnellere Ergebnisse in ein Web integriert werden kann. Sie lernen, wie Sie ohne Vorkenntnisse eine Website von Grund auf erstellen und bereitstellen und sie funktionsfähig, sicher, schön, nützlich und vor allem praktisch gestalten. Sie lernen, wie Sie maschinelles Lernen und Computer Vision nutzen, um eine Website sicherer und praktischer zu machen, Video und Audio von Ihrer Website aufzuzeichnen, Ihre Stimme zu spenden, Musik zu machen und Audio zu modulieren, um nützliche Samples zu erstellen, und wie Sie den Lärm durchbrechen, indem Sie andere Websites nutzen, um das bestmögliche Netzwerk von Websites aufzubauen, die Sie direkt mit Ihrer verlinken können, um alle nützlichen Informationen, die Sie zu bieten haben, zu teilen und, was noch wichtiger ist, Menschen auf Ihre Software und Ihr Unternehmen aufmerksam zu machen. Dieses Buch konzentriert sich vor allem auf Medien, Sicherheit und maschinelles Lernen. Dies sind die drei Hauptkomponenten, die Ihnen dabei helfen, nützliche Software für das Web zu entwickeln, indem Sie die richtigen Benutzer einbeziehen und die falschen Benutzer ausschalten, und zwar auf eine realistische, praktische, praktische und ansprechende Art und Weise, die gleichzeitig automatisch und robust ist. Dieses Buch lehrt UNIX, insbesondere Debian (Ubuntu), Bash-Shell, Python, HTML, CSS, JavaScript und eine Reihe nützlicher Softwarepakete für Python-ähnliche Anfragen sowie nützliche Bash-Software wie Git und ffmpeg. Ich werde Ihnen auch beibringen, wie Sie Kryptowährungen automatisch handeln und Zahlungen in Kryptowährungen oder mit regulären Debitkarten entgegennehmen und Ihren Besuchern sogar einen Teil Ihres Umsatzes auszahlen, wenn Sie dies wünschen. Ich zeige Ihnen, wie Sie mit Ihrer Website auch durch Werbung Geld verdienen, wie Sie Ihre App für Suchmaschinen vorbereiten und schnell machen, wie Sie bei den Suchanfragen Ihrer Kunden an erster Stelle stehen, um Sie zu finden, und wie Sie bei möglichst vielen häufigen Suchanfragen ein Ranking erzielen. Ich bringe Ihnen bei, wie Sie Ihre Software verkaufen, Werbung dafür machen, Kunden ansprechen, die nach Ihren Dienstleistungen suchen, und sich im Internet über bereits bestehende, kostengünstige und gut funktionierende Wege einen Namen machen. Ich zeige Ihnen, wie Sie Ihre Daten kostengünstig auf Cloud-Computern speichern, die für Sie arbeiten, wie Sie eine Website planen und erstellen, die das tut, was Ihre Benutzer wollen und was Sie möchten, und wie Sie Ihre Benutzer binden, indem Sie Ihre Website mit Benachrichtigungen, E-Mails, Textnachrichten, Telefonanrufen usw. nur einen Fingertipp entfernt auf ihren Telefonen platzieren

Ihnen stehen mehr Möglichkeiten zur Verfügung, um Ihre Benutzer mit einem Klick auf eine nur für Sie gesicherte Schaltfläche zurück auf Ihre Website zu bringen. Dieses Buch konzentriert sich auf die Praktikabilität der Veröffentlichung und Verbreitung von Medien in großen Mengen, von Texten über Fotos und Videos bis hin zu Audio, um einen guten Eindruck bei Endbenutzern (Ihren Kunden) zu hinterlassen und sich selbst auf jede erdenkliche Weise zu verkaufen, um eine Website oder eine App zu erstellen, die nur Sie selbst repräsentiert und Ihnen, Ihrer Software und Ihrem Unternehmen das bestmögliche Aussehen verleiht. Außerdem lernen Sie von mir ein paar Tipps und Tricks, von Codierungstipps bis hin zu praktischen Dingen wie Make-up und Fotografie, Modeln und Schauspiel und mehr, die wichtig sind, um sich und Ihr Unternehmen im bestmöglichen Licht darzustellen, indem Sie alle Ihnen zur Verfügung stehenden Tools nutzen und gleichzeitig so viele Inhalte wie nötig auf einer ausgewogenen Plattformverteilung verteilen, um Ihre Software ohne mehr Aufwand, Arbeit oder Geld als nötig zum Erfolg zu bringen. Dieses Buch trägt nicht umsonst den Titel „Practical Web Based Deep Learning and Security by Sample": Es befasst sich mit dem Erlernen des Codierens, speziell für das Web, insbesondere mit einem Fokus auf Sicherheit, aus praktischer Sicht, mit Beispielen für funktionierenden Code, der den im Text dargelegten praktischen Zwecken dient. Die Lernkomponente dieses Textes umfasst auch maschinelles Lernen, den Code, den ich Ihnen zeigen werde, wie man ihn für das Web ausführt, der Computer Vision, Gesichtserkennung, Bild- und Videomoderation, Bildverbesserung, Auflösungsverbesserung, Bildunterschrift und andere Aufgaben wie aus Bildern gewonnene Vorhersagemetriken übernimmt, etwa die Beschaffenheit des Bildes als authentisches, computerübertragenes Bild oder eine optische Kopie (ein Foto eines Bildes oder ein gedrucktes Foto). Maschinelles Lernen ist sehr wichtig, wenn es um Web- und Softwaresicherheit geht, da es Aufgaben ausführen kann, die sonst unmöglich wären. Ihr Computer meldet Sie möglicherweise mit einem Passcode an, es ist jedoch möglicherweise sicherer, diesen zu verwenden, wenn er Sie mit Ihrem Gesicht anmeldet. Sie können einen Servercomputer so sicher machen, einen Computer, der Sie normalerweise nach einem Benutzernamen und einem Passcode fragt und Sie anmeldet, möglicherweise mit einem Bestätigungstoken für jede neue Anmeldung oder neue IP-Adresse. Wenn Sie jedoch umfangreiche, benutzerfreundliche, grundsätzlich sichere und leistungsstarke Software erstellen, kann dies ausreichen. Eine zu enge Verknüpfung Ihrer Software mit der Software einer anderen Person, etwa einem E-Mail- oder SMS-Dienst, reicht nicht aus, um Ihre Software oder die anderer (jeder von Ihnen genutzten Website) sicher zu machen. Jeder, der Software entwickelt, die einwandfrei sicher ist, weiß, was das bedeutet. Software ist von Natur aus unsicher, da die Geräte und Konten, mit denen wir auf sie zugreifen, nicht immer zur Verfügung stehen. Sie könnten sich in den Händen von Personen befinden, die böswillige Absichten für die Software haben, und daher ein Risiko für die Software selbst darstellen. Dies ist einer der Schwerpunkte dieses Buches. Ein vernetzter Computer wird standardmäßig mit einem langen Schlüsseltoken namens SSH oder Secure Shell-Schlüssel gesichert und ist ansonsten am besten mit einem Webserver gesichert, da der Webserver den offenen Zugriff sowie modernste Sicherheitstools bereitstellt, die auf dem Server selbst ausgeführt werden. Der Webserver hat Zugriff auf den Webbrowser des Benutzers, der wohl der leistungsstärkste Teil des Geräts des Benutzers ist, da er dort auf vernetzte Software zugreifen kann. Dieses Toolkit kann Text und die von Ihnen angezeigten Webseiten wiedergeben und außerdem Bilder, Audio und Video (z. B. ein Foto eines Gesichts oder eines Staatsausweises) aufzeichnen, Bluetooth-Funkgeräte lesen und darauf schreiben sowie Nahfeld-Transponder-Tags, preiswerte Schlüsselkarten, Schlüsselanhänger, Aufkleber, Ringe und sogar Chip-Implantate mit eindeutigen Seriennummern lesen und beschreiben, die mit Daten gelesen und beschrieben werden können, die von einem mit der Website verbundenen Webserver generiert und validiert werden. Mithilfe aller Ihnen zur Verfügung stehenden Tools werden Sie sich mit diesem Buch das nötige Wissen aneignen, um eine sichere Website und insgesamt ein sicheres vernetztes Computersystem zu erstellen, das für Sie arbeitet, Ihre Wünsche erfüllt und richtig aussieht und sich gut anfühlt.

Wo soll ich anfangen: Sie können den Abschnitt, mit dem ich dieses Buch beginne, oder einen beliebigen Abschnitt gerne überspringen, um genau den Code zu finden, den Sie benötigen, insbesondere wenn Sie bereits Erfahrung mit dem Codieren oder einem der oben genannten Tools haben, die ich in diesem Buch ausführlich beschreiben sowie Anwendungsfälle und praktische Beispiele dafür dokumentieren werde. Wenn Sie keine Erfahrung im Schreiben von Code haben, empfehle ich Ihnen dringend, das gesamte Buch und insbesondere die vorherigen Abschnitte zu lesen, um sicherzustellen, dass dieses Buch das Richtige für Sie ist. Wenn dieses Buch nicht das Richtige für Sie ist, sollten Sie es einem Freund oder Verwandten schenken, der vielleicht selbst daran interessiert ist, etwas über Webentwicklung zu lernen, und vielleicht sogar darüber nachdenken, es auszuleihen und von ihm zu lernen, um die Lücken zu schließen, wo ich als Lehrer im Stich gelassen habe oder andere Lehrer vor mir. Beginnen Sie, wo Sie wollen. Jeder Teil dieses Buches wird nützlich sein, wenn Sie beabsichtigen, eine nützliche App zu erstellen, und bedenken Sie, dass die besten Apps für den Endbenutzer entwickelt werden: Kennen Sie Ihren Kunden. Jetzt kennen Sie mich, Sie kennen dieses Buch und Sie sind bereit zu beginnen. Schnappen Sie sich zunächst einen Computer (selbst der billigste Laptop aus dem Fachhandel, Amazon oder ein alter Desktop-Computer) und richten Sie ihn so ein, wie es für Sie am besten passt.

So liest man dieses Buch: Hervorgehobener Text bedeutet, dass der Text in eine Eingabeaufforderung gehört, in die Sie den von Ihnen ausgeführten Code schreiben. Die Eingabeaufforderung ist stark auf die Tastatur ausgerichtet und erfordert kaum oder gar kein Klicken, was Ihren Arbeitsablauf beschleunigt und Ihnen die Arbeit erleichtert.

Erste Schritte: Lassen Sie uns eintauchen. Wir beginnen mit dem Erstellen von Code auf einem lokalen Computer und beginnen ohne den Aufbau einer mit dem Internet verbundenen Website. Das ist von Anfang an sicherer, kostet nichts und ist für Sie einfach. Abhängig von Ihrem Betriebssystem ist der Einstieg in eine Bash-Shell etwas anders. Für Mac OS empfehle ich an dieser Stelle die Installation einer virtuellen Maschine, da Sie mit einer virtuellen Maschine die größte Kompatibilität erhalten. 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 lieber eine native Umgebung verwenden möchten, was für ein schnelles, optimiertes Erlebnis empfohlen wird. 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 Ihren Wünschen an und beginnen Sie mit Schritt 2. Wenn Sie Windows verwenden, befolgen Sie bitte Schritt 1.

Schritt 1: - Nur Windows-Benutzer Öffnen Sie unter Windows die Eingabeaufforderung als Administrator und geben Sie ein wsl –install

Schritt 2: - Fahren Sie hier fort oder überspringen Sie Schritt 1 bis hierher, wenn Sie nicht Windows verwenden Beginnen Sie in einem offenen Terminal (je nach Betriebssystem Ubuntu unter Windows, Terminal unter Mac oder Linux oder ein ähnlicher Name) mit der Erstellung eines Projekts. Dies machen wir mit dem Befehl mkdir, der ein Verzeichnis erstellt. Wenn Sie ein Verzeichnis zum Speichern Ihres Projekts erstellen müssen, was empfohlen wird, wechseln Sie mit dem Befehl cd in das Verzeichnis und und

cd /path/to/directory – Der Pfad sind die Ordner (Dateien), die Ihrem Zielverzeichnis vorangehen. Ihr Standardpfad ist ~ oder /home/username (wobei username Ihr Benutzername ist). Um zum Standardverzeichnis zu wechseln, geben Sie cd oder cd ~ ein mkdir-Beispiel – Ersetzen Sie „Beispiel" durch den Namen des Verzeichnisses

sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Jetzt haben Sie ein Arbeitsverzeichnis für Ihr Projekt. Da es so wichtig ist, dieses Verzeichnis zu speichern, falls Sie auf einen anderen Computer wechseln oder den von Ihnen geschriebenen Code bereitstellen müssen, damit er für das Web bereit ist, erstellen wir in den nächsten Schritten ein Skript zum Sichern Ihres Verzeichnisses. Für die Erstellung eines Skripts ist jedoch ein wenig Code erforderlich, und der Code muss automatisiert werden, um so nützlich wie möglich zu sein. Lassen Sie uns also zunächst ein Skript erstellen, um Skripte zu erstellen. Beginnen wir damit, das Skript zu erstellen und ausführbar zu machen. Wir verwenden hierfür sudo, chmod und touch und nennen das Skript „ascript".

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
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, was viel einfacher ist als die Verwendung einer grafischen Benutzeroberfläche. Um eine Datei mit nano zu bearbeiten, verwenden Sie nano und dann den Pfad zur Datei. Ein Skript zu erstellen, das ein Skript erstellt, ist ziemlich ähnlich wie das Erstellen unseres Skripts überhaupt. Wir verwenden denselben Code wie oben und ersetzen den Namen des Skripts, „ascript", durch einen Argumentparameter, $1. Dadurch können wir das Skript aufrufen, indem wir einfach „sudo ascript newscript" eingeben. Anschließend können wir ein beliebiges neues Skript erstellen, indem wir „newscript" durch den Namen Ihres Skripts ersetzen. Der Code in Nano sollte so aussehen:

sudo ascript backup
Und um Nano zu schließen, können wir die Strg-Taste gedrückt halten und X drücken, dann Y, um anzuzeigen, dass wir die Datei speichern, und die Eingabetaste drücken. Anstatt diese drei Befehle einzugeben, um ein Skript zu bearbeiten, können wir nun 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. Speichern wir jetzt unsere Arbeit: Schreiben wir ein Sicherungsskript, um unser neues Skript zu speichern und es dann in unserem Projektverzeichnis zu sichern, während wir gleichzeitig das Sicherungsskript sichern.

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Jetzt in Nano:

backup
Dabei ist /path/to/directory der Pfad zu dem Projekt, das Sie mit mkdir erstellt haben. Später werden wir lernen, wie man Wiederholungspfade wie diesen mit einer Schleife und einer Liste kopiert, was weniger Code erfordert, aber jetzt wollen wir es einfach halten und ein paar Zeilen verwenden. Um dieses Skript auszuführen und Ihren Code zu sichern, speichern Sie die Datei in nano mit Strg+X, Y und RETURN und geben Sie Folgendes in Ihre Shell ein

Wenn Sie beim Lesen dieses Buches und beim Ausführen der Schritte in der Shell überhaupt zur Eingabe eines Passworts aufgefordert werden, geben Sie bitte Ihr Benutzerpasswort korrekt ein. Sie haben drei Versuche Zeit, bevor Sie den Befehl erneut ausführen müssen. Sie können die Aufwärts- und Abwärtspfeile verwenden, um Befehle erneut auszuführen und zu bearbeiten, falls Sie etwas zweimal ausführen müssen. Drücken Sie einfach abwechselnd nach oben und unten, um einen Befehl auszuwählen, bevor Sie den Befehl mit den Pfeiltasten nach rechts, links und der Entf-Taste sowie der Tastatur bearbeiten und mit der Eingabetaste ausführen.

Glückwunsch! Sie haben es geschafft, ein fantastisches Backup-Skript zu erstellen, das zwei wichtige Shell-Skripte in Ihrem Arbeitsverzeichnis sichert. Möglicherweise verschieben wir die Dinge später, wenn das Projekt größer wird, aber das funktioniert vorerst. Kommen wir nun zur Sicherung in der Cloud. Hierfür verwenden wir GitHub (obwohl es zahlreiche andere Git-Lösungen für die Sicherung gibt, sind sie alle ungefähr gleich). Git ist eine Software zur Versionskontrolle, mit der Sie Änderungen an Ihrer Software sichern können, während Sie diese auf einem Server vornehmen, und die Ihnen gleichzeitig ermöglicht, ganze Kopien Ihrer Software hinter einem Passwort oder Schlüssel herunterzuladen. Dies ist entscheidend für die Sicherung Ihrer Software, insbesondere wenn wir auf gesicherte Linux-Instanzen migrieren, die manchmal kaputt gehen, wenn eine einzelne Codezeile fehlschlägt, sodass Sie ausgesperrt sind und Ihr Code möglicherweise nicht gesichert wird, wenn Sie keine Möglichkeit haben, ihn automatisch zu sichern, worauf wir eingehen werden.

Wenn Sie zu diesem Zeitpunkt noch keine virtuelle Ubuntu-Maschine verwenden, empfehle ich an dieser Stelle die Verwendung einer virtuellen Ubuntu-Maschine, da dies Ihnen das Leben bei der Installation aller Pakete erleichtert, die zum Erstellen einer funktionierenden Website und zur Durchführung von Deep-Learning-Vorgängen auf Ihrem Computer erforderlich sind. Wir werden den Code in naher Zukunft auf einen Webserver verschieben, möchten jedoch sicherstellen, dass sich hinter unserem Webserver mindestens einige Sicherheitsebenen befinden, die gegen Phishing resistent sind, und verwenden dazu eine Reihe von Linux-Paketen. Wenn Sie weiterhin Mac OS verwenden möchten, können Sie gerne online nach den erforderlichen Paketen suchen und diese installieren. Möglicherweise gibt es jedoch nicht für jedes Paket, das in diesem Buch oder dieser Serie behandelt wird, Alternativen.

# Fügen wir ein paar Befehle hinzu, um unsere Arbeit mit dem Sicherungsskript zu bestätigen, indem wir den Befehl sudo ascript backup ausführen.
git add –all
git commit -m "backup"
git push -u origin master

Zum Speichern drücken Sie erneut X.

cd /path/to/directory
git init
git branch -m master
ssh-keygen
Jetzt müssen wir einmalig eine Konfiguration für dieses Projekt vornehmen. Da es sich bald um ein Git-Projekt handelt, müssen wir nicht jedes Mal, wenn wir aus einem Git-Repository bereitstellen, jeden Befehl eingeben, aber wir bekommen den Dreh raus, wenn wir unsere Bereitstellungsskripts schreiben. Stellen wir zunächst sicher, dass wir uns im richtigen Verzeichnis befinden, initialisieren wir das Git-Repository und generieren SSH-Schlüssel.

cd ~
cat .ssh/id_rsa.pub
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. Suchen wir diesen Schlüssel und kopieren ihn. Um es zu sehen,

git remote add git://… (your remote URL)
Kopieren Sie den vom letzten Befehl zurückgegebenen Text und erstellen Sie ein Konto bei 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 Menü oben rechts und geben Sie Einstellungen ein, bevor Sie Ihren SSH-Schlüssel unter SSH- und GPG-Schlüssel unter Zugriff im Menü hinzufügen. Wählen Sie „SSH-Schlüssel hinzufügen" und fügen Sie Ihren hinzu, indem Sie ihn einfügen und ihm einen Titel geben, bevor Sie ihn speichern und zu GItHub zurückkehren, um ein neues Repository zu erstellen. Dies gilt auch für andere Git-Anbieter. Sie müssen deren Dokumentation lesen. Geben Sie Ihrem Repository in der neuen Repository-Konfiguration einen beschreibenden Namen und entscheiden Sie, ob Sie es veröffentlichen möchten. Stellen Sie außerdem sicher, dass noch keine Dateien für die Aufnahme konfiguriert sind. Sobald das Repository erstellt ist, kopieren Sie den Klon mit der SSH-URL und fügen Sie ihn in den folgenden Befehl ein.

Jetzt können Sie mit der CD zu Ihrem Repository zurückkehren, das ist Ihnen sicher bekannt. Probieren Sie Ihr Backup-Skript jetzt mit Backup aus

Großartig! Jetzt können wir wirklich mit dem Codieren beginnen. Lassen Sie uns Django installieren, nachdem wir Bash und Git gut verstanden haben. Mit Django können wir unsere Software automatisch sichern. Bash kann dies auch tun, aber Django sollte eine einfachere und sicherere Implementierung haben (sie kann einfacher deaktiviert und konfiguriert werden).

Um Software in Ubuntu zu installieren, verwenden wir den Befehl sudo apt-get. Lassen Sie uns zunächst die Software aktualisieren und aktualisieren, die wir bereits hatten. 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 install python-is-python3 python3-venv

Das ist alles, was Sie brauchen, um mit Django in Bezug auf Softwareinstallationen in der Ubuntu-Instanz loszulegen. Für Windows und Linux sollte dies ziemlich einfach sein, aber für Mac möchten Sie möglicherweise eine virtuelle Maschine und Linux darauf installieren, indem Sie eine kostenlose oder kostenpflichtige virtuelle Umgebung wie VirtualBox oder Paralells Desktop verwenden und die oben genannten Schritte wiederholen, um eine Ubuntu-Umgebung einzurichten. Ubuntu ist in diesem Fall von entscheidender Bedeutung, da es sich um die Software handelt, die auf den Websites ausgeführt wird, und es ihnen ermöglicht, Websites mit der gesamten oben genannten Software zu hosten.

Lassen Sie uns in den Django eintauchen.

python -m venv venv # Wieder in unserem Verzeichnis, mit cd:
source venv/bin/activate #
pip install Django
django-admin startproject mysite . # Erstellt die virtuelle Umgebung, in der Code gespeichert wird
Aktiviert die virtuelle Umgebung

Wobei mysite das Projekt ist, das ich in meinem aktuellen Verzeichnis starte.

python manage.py startapp feed
Mit Django beginnen wir gerade erst, denn Django hostet den Webserver und tut alles, was wir brauchen, um eine einfache lokale Website zum Laufen zu bringen. Nachdem wir Django nun installiert haben, bearbeiten wir die Einstellungen ein wenig, damit es wie benötigt funktioniert. Lassen Sie uns zunächst eine neue App erstellen

nano app/settings.py
Sie werden feststellen, dass die erste App „Feed" heißt. Die App sollte einen beliebigen Namen haben, und wir erstellen neue Apps. Der Name jeder App muss jedoch jedes Mal konsistent sein, wenn im Code auf die App verwiesen wird. Um eine neue App hinzuzufügen, bearbeiten wir immer die Datei „settings.py" in dem anderen Verzeichnis, das die App erstellt hat und das in „Startprojekt" (im Folgenden „App") genannt wird. Mit Nano,

INSTALLED_APPS = [
    'feed',
]
Suchen Sie in den Einstellungen nach INSTALLED_APPS und teilen Sie [] in drei Zeilen auf. Fügen Sie mit vier Leerzeichen auf der leeren Mittellinie „Feed" oder den Namen Ihrer App hinzu. Dieser Abschnitt der Datei „settings.py" sollte wie folgt aussehen:

Bevor wir es vergessen, testen wir, ob Django funktioniert. Mit dem Befehl python manage.py runserver 0.0.0.0:8000 können wir den Server ausführen und dann in einem Webbrowser auf dem Computer, auf dem der Code ausgeführt wird, zu http://localhost:8000 navigieren und eine Beispielwebseite anzeigen (Es funktioniert!) Beenden Sie den Server mit Control C, genau wie bei jedem anderen Befehl.

Kommen wir nun zum Schreiben von Python-Code. Django besteht aus drei Hauptkomponenten, die alle vollständig per Code ausgeführt werden. Die Komponenten heißen Modell, Ansicht und Vorlage und befinden sich jeweils auf einer höheren bzw. niedrigeren Ebene, bevor die Webseite dem Benutzer bereitgestellt wird.

Das Modell ist der Code, der Informationen zum Abrufen, Sortieren und Rendern in der Datenbank speichert.

Die Ansicht entscheidet, wie das Modell gerendert, manipuliert und geändert wird. Fast jede Ansicht verwendet ein Modell direkt.

Die Vorlage ist der HTML-Code mit einigen zusätzlichen Schnickschnack, der sogenannten Vorlagensprache. Die Vorlage wird von der Ansicht gerendert, wo sie mit Python-Code und Kontext wie Modellen und Informationen (normalerweise Zeichenfolgen und Ganzzahlen) aus der Ansicht gefüllt wird.

Django hat auch andere Komponenten, einschließlich, aber nicht beschränkt auf:

Einstellungen, mit denen die App wie besprochen konfiguriert wird.

URLs sind Muster, denen der Benutzer folgt, um Zugriff auf bestimmte Teile der Webanwendung zu erhalten.

Formulare, die definieren, wie an den Server gesendete Informationen verarbeitet und an die Datenbank sowie an den Benutzer gerendert werden. Diese bilden die Grundlage für die Verarbeitung von Informationen auf der Serverseite und können alle Arten von Informationen akzeptieren, die der Computer speichert, insbesondere Textzeichenfolgen, Zahlen und Wahr/Falsch-Boolesche Werte (normalerweise Kontrollkästchen).

Vorlagen sind HTML-Code und Vorlagensprache und schließen die Lücke zwischen Python und HTML. Das bedeutet, dass Python-Informationen als HTML-Code bereitgestellt werden können, auf den jeder zugreifen kann, und eine Website mit eingeschränktem Zugriff sichern können, während Python-Code für das Web zugänglich und für verschiedene Zwecke auf einem Remote-Gerät, das sich nicht in der Nähe des Servers befinden muss, nützlich ist.

Statische Dateien, bei denen es sich normalerweise um JavaScript und seine Bibliotheken handelt, die der Server bereitstellt und die mit der Vorlage verknüpft sind.

Mediendateien, die der Server bereitstellt oder die extern gehostet werden oder einfach auf den Server geschrieben werden, bevor sie verarbeitet und zum Hosten auf einen anderen Server (einen Bucket) gesendet werden.

Middleware, das sind Codeteile, die gleichzeitig mit jeder Ansicht ausgeführt werden und als in der Ansicht „eingeschlossen" gelten.

Kontextprozessoren, die den Kontext jeder Ansicht verarbeiten und zum Hinzufügen zusätzlichen Kontexts verwendet werden.

Tests, die überprüfen, ob der Benutzer oder die Anfrage bestimmte Anforderungen erfüllt, bevor die Ansicht gerendert wird.

Verbraucher, die bestimmen, wie Websockets mit der Kommunikation umgehen und darauf reagieren.

Admin, das zum Registrieren von Modellen verwendet wird, damit diese detailliert auf der Django-Admin-Seite bearbeitet werden können, wo die Datenbank über eine grafische Oberfläche verwaltet werden kann.

Celery definiert asynchrone Aufgaben. Teile des Django-Codes können mit der Ausführung beginnen, bevor sofort mit der nächsten Aufgabe oder Codezeile fortgefahren wird.

Django kann viele andere Komponenten haben, die wir hier ausführlich besprechen werden. Es gibt viele Möglichkeiten, Django funktionaler zu machen, indem man WebSockets, schnelle, optimierte Kommunikationskanäle, Celery, das asynchrone Aufgaben ausführt, und eine Vielzahl anderer Softwareteile zur Erweiterung von Django hinzufügt, insbesondere in den Ansichtsfunktionen, wo der Großteil des Codes ausgeführt wird. Ansichtsfunktionen sind von entscheidender Bedeutung, da sie normalerweise jeden Codeabschnitt deklarieren, der für ein bestimmtes URL-Muster oder einen Abschnitt des Servers spezifisch ist.

Lassen Sie uns zunächst die Ansichtsfunktionen erkunden. Ansichtsfunktionen beginnen mit Importen, die Code bezeichnen, der in der Ansicht verwendet wird, und werden mithilfe regulärer Funktionsdefinitionen oder Klassen definiert. Die einfachsten Ansichten werden durch die Funktionsdefinition def definiert und geben eine HttpResponse mit einer Basisvorlage zurück. Beginnen wir mit der Definition einer Grundansicht, um den Text „Hallo Welt" zurückzugeben. Denken Sie daran, dass Sie jedes Mal, wenn Sie Code nach einer Anweisung wie def, if, while, for usw. hinzufügen, 4 Leerzeichen für jede der vorhergehenden Definitionen hinzufügen müssen, die Sie auf Ihre Funktion anwenden möchten. Wir werden bald darauf eingehen, was die einzelnen Bedeutungen bedeuten.

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
Bearbeiten Sie im Verzeichnis unserer Website die Datei „feed/views.py" mit nano und fügen Sie die folgenden Zeilen am Ende der Datei hinzu.

Djangos HttpResponse antwortet mit einer Textzeichenfolge, die mit dem öffnenden und schließenden „" gekennzeichnet ist. Jedes Mal, wenn Sie Informationen an eine Funktion oder Klasse übergeben, z. B. eine Anfrage oder einen String, müssen Sie Klammern (, öffnende und schließende ) verwenden.

Das ist noch nicht alles, was wir brauchen, um unsere Sichtweise zu sehen. Natürlich haben wir dem Server nicht genau mitgeteilt, wo sich die Ansicht befindet, wir müssen dennoch einen Pfad definieren, über den die Ansicht gerendert werden soll. Beginnen wir mit der Definition eines Basispfads in app/urls.py und gehen später auf die Pfadgruppen ein.

from feed import views as feed_views
Fügen Sie in app/urls.py eine Zeile nach den Importanweisungen hinzu, nachdem Sie mit dem Importieren der gerade erstellten Ansicht begonnen haben.

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Definieren wir nun das Ansichtsmuster. Ansichtsmuster bestehen aus drei Komponenten: der Pfadkomponente, die dem Server mitteilt, wo die Ansicht innerhalb des Servers vorhanden ist (der URL-Pfad, den der Benutzer in die Navigationsleiste eingibt, um die Webseite aufzurufen), der Ansichtskomponente, in der die Ansicht angegeben ist, und einem benutzerfreundlichen Namen für die Ansicht, damit das Muster bei der Arbeit mit einer Vorlage leicht abgerufen werden kann, insbesondere damit der Name bei Bedarf geändert und aktualisiert werden kann, um Platz für eine andere Ansicht zu schaffen oder einen logischeren Namen anzunehmen. Es ist sinnvoll, die Dinge auf diese Weise zu erledigen und flexibel zu sein, da Ihre Codebasis eine sich ständig verändernde Umgebung sein wird, die Flexibilität und Improvisation erfordert, um wertvoll und einfach zu bearbeiten zu sein. So wird Ihre Ansicht aussehen. Sie können dies zum Abschnitt urlpatterns = [ von app/urls.py hinzufügen. Das Ansichtsmuster wird mit den drei oben beschriebenen Komponenten und einer Funktion namens Pfad definiert. Bei Ihren URL-Mustern handelt es sich um eine Liste. Stellen Sie daher sicher, dass jedes darin enthaltene Element immer mit einem Komma endet, da dies die einzelnen Elemente trennt. Jedes Element sollte außerdem in einer neuen Zeile stehen, wiederum mit vier Leerzeichen davor, 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 im Stammverzeichnis des Webservers ausgeführt wird. Ihre urls.py sollte nun so aussehen:

python manage.py check
Dies ist die Grundlage, um mit Django eine Website zu erstellen, 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 beginnen können, müssen wir Modelle verwenden, die wir als Nächstes untersuchen werden. Lassen Sie uns zunächst unseren Code überprüfen und den Server ausführen. Führen Sie Folgendes aus, um den Code auf Fehler zu überprüfen:

python manage.py runserver 0.0.0.0:8000
Wenn Fehlermeldungen angezeigt werden, sollten Sie die von Ihnen an Ihrer App vorgenommenen Änderungen sorgfältig überprüfen und prüfen, ob etwas behoben werden muss, z. B. ein überflüssiges oder fehlendes Leerzeichen, ein zusätzliches Zeichen, eine nicht geschlossene Zeichenfolge, ein Tippfehler, ein versehentlich gelöschtes Zeichen oder etwas anderes. Wenn Sie die Fehlermeldung lesen (falls Sie eine haben), sollten Sie den Pfad zu einer von Ihnen erstellten oder bearbeiteten Datei sowie eine Zeilennummer sehen können. Sehen Sie sich also diese Datei und Zeile an und prüfen Sie, ob Sie dort etwas reparieren können. Wenn Sie das Problem behoben haben, führen Sie den obigen Befehl erneut aus. Wenn Ihre Software betriebsbereit ist und funktioniert, wird die Ausgabe „Bei der Systemprüfung wurden keine Probleme festgestellt" angezeigt. Jetzt können Sie loslegen. Führen Sie den Server aus mit:

Öffnen Sie nun einen Webbrowser und navigieren Sie zu http://localhost:8000. In Ihrer Ansicht sollte der zurückgegebene Text in Klammern und Anführungszeichen der HttpResponse-Funktion angezeigt werden. Dies ist nur ein einfaches Beispiel, aber wenn Sie es bis hierher geschafft haben, verstehen Sie die Grundlagen der Funktionsweise von Linux, Bash, Python und Django. Lassen Sie uns tiefer in die Datenbankmodellierung eintauchen und die Leistungsfähigkeit einer Python-Klasse beim Speichern von Informationen erkunden. Dann beginnen wir, uns mit HTML und CSS vertraut zu machen, bevor wir unsere Website mithilfe von JavaScript und maschinellem Lernen voll funktionsfähig, flexibel und sicher machen.

from django.db import models # Klassen werden in der models.py Ihrer App gespeichert. Bearbeiten Sie mit Nano app/models.py und fügen Sie eine neue Klasse hinzu. Eine Klasse wird mit der Klassendefinition definiert und erhält eine Superklasse, von der sie erbt, in diesem Fall models.Model. Der Name der Klasse steht nach der Klassendefinition und nach der Klassendefinition wird ein : (Doppelpunkt) verwendet, bevor die mit der Klasse verknüpften Attribute und Funktionsdefinitionen unten angegeben werden. Unsere Klasse benötigt eine ID, mit der wir sie abrufen und eindeutig halten können, und außerdem ein Textfeld zum Speichern einiger Informationen. Später können wir einen Zeitstempel, Dateien, Boolesche Werte (wahre oder falsche Definitionen, die unserem Code helfen können, Entscheidungen darüber zu treffen, was mit dem Modell geschehen soll, und die zum Sortieren des Modells verwendet werden können), eine Instanz hinzufügen, um das Modell an einen am Server angemeldeten Benutzer zu binden, und mehr. Entpacken wir den folgenden Code:

class Post(models.Model): #
    id = models.AutoField(primary_key=True) # Der Import, der zum Definieren unserer Klasse und ihrer Attribute verwendet wird
    text = models.TextField(default='') # Die Definition unserer Klasse selbst
Die ID unseres Modells, ein automatisch generierter Schlüssel, der es uns ermöglicht, das Modell abzufragen, es eindeutig zu halten und nützlich ist, wenn wir mit dem Modell interagieren müssen, nachdem es erstellt wurde.

Das Attribut unserer Klasse speichert in diesem Fall Text, standardmäßig eine leere Zeichenfolge.

Schließen und speichern Sie die Datei wie zuvor, um den Vorgang abzuschließen.

Es gibt viele andere Felder und Optionen, die wir untersuchen werden, wenn wir diesen Kurs aktualisieren, während sich unsere App weiterentwickelt. Dies sind jedoch die Grundvoraussetzungen für die Erstellung einer App zum Veröffentlichen von Text. Allerdings wird dieses Modell alleine nicht funktionieren. Wie bereits beschrieben, benötigen wir eine benutzerdefinierte Ansicht und ein benutzerdefiniertes URL-Muster, damit dieses Modell funktioniert. Außerdem benötigen wir ein Formular und eine Vorlage. Lassen Sie uns zunächst das Formular untersuchen.

Um ein Formular zu definieren, bearbeiten Sie app/forms.py mit nano und fügen Sie die folgenden Zeilen hinzu. Wir benötigen zwei Importe, unsere Formularklasse sowie das von uns erstellte Modell (feed.models.Post), eine dem Modell ähnliche Klassendefinition und ein Feld zusammen mit einer Unterklasse namens Meta, die das Modell definiert, mit dem das Formular interagiert. Das Formular kann auch über eine Initialisierungsfunktion verfügen, die es basierend auf Informationen in der Anfrage, im Modell oder auf andere Weise einrichtet. Wir werden dies später untersuchen.

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',)
Modellformulare sind so nützlich, weil sie ein Modell erstellen oder auch bearbeiten können, daher werden wir sie für beides verwenden. Definieren wir unten eine in der Datei „forms.py".

python manage.py makemigrations
python manage.py migrate
Dies sind die Grundlagen dafür, wie eine Form und ein Modell aussehen. Dieses Modellformular kann verwendet werden, um einen Beitrag zu instanziieren oder zu bearbeiten und dabei den darin enthaltenen Text zu ändern. Als nächstes schauen wir uns die Integration dieses Formulars in eine Ansicht an. Lassen Sie uns zunächst die Migrationen durchführen und die Datenbank migrieren, damit unser Code bei der Ausführung mit dem Modell interagieren kann. Führen Sie dazu die folgenden Befehle aus:

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

def feed(request):
    posts = Post.objects.all() # Die Ausführung dauert eine Minute. Sobald dies jedoch der Fall ist, können Sie in den Ansichten, in der Middleware oder an einer anderen Stelle in der Software auf das Modell zugreifen. Fahren wir fort, indem wir eine Ansicht erstellen, in der wir unser Modell sehen können. Bearbeiten Sie „feed/views.py" und fügen Sie wie angegeben den folgenden Code hinzu. Sie müssen nach dem #-Zeichen nichts hinzufügen. Bei diesem Code handelt es sich um Kommentare, die zur Kennzeichnung von Informationen zum Code verwendet werden. Wir beginnen damit, unser Modell in die Ansichten zu importieren und es einem Kontext hinzuzufügen, in dem wir es in einer Vorlage als Liste zur Anzeige rendern können. Als Nächstes fügen wir eine Vorlage hinzu, 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 es auf dem Server zu veröffentlichen. Das klingt kompliziert, also gehen wir es einfach Schritt für Schritt an. Bevor wir mit der Ansicht fertig sind, erstellen wir eine Vorlage, die lediglich das Modell rendert, und stellen sicher, dass wir es sehen können, indem wir einen neuen Beitrag in der Shell erstellen. So sollte diese Ansicht aussehen:
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })

Fragen Sie alle bisherigen Beiträge in der Datenbank ab

Das sieht alles ziemlich einfach aus, bis wir auf den Grund kommen. Render, der von der Funktion zurückgegebene Wert, statt in einer HTTP-Antwort wie im vorherigen Beispiel, nimmt immer eine Anfrage als erste Eingabe, akzeptiert einen Kontext (in diesem Fall die Beiträge in der Datenbank), der nun in der Vorlage gerendert werden kann, 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 HTML umwandelt.

mkdir feed/templates
mkdir feed/templates/feed
Um mit der Erstellung von Vorlagen zu beginnen, erstellen Sie zwei Verzeichnisse im Feed.

 <!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Bearbeiten Sie als Nächstes eine Vorlage im Verzeichnis oben, „feed/templates/feed", und fügen Sie den Code für dieses Beispiel hinzu. Schauen wir uns die Vorlage für dieses Beispiel an.

python manage.py shell
Dies ist eine sehr einfache Vorlage. Es definiert öffnende und schließende HTML-Tags, ein Dokumenttyp-Tag, ein Body-Tag mit einem Legendentitel, ein Break-Tag, das eine kleine Linie auf dem Bildschirm hinzufügt, und eine for-Schleife, die jeden Beitrag in der Beitragsliste als Absatz in der Vorlage darstellt. Dies ist alles, was zum Rendern von Beiträgen erforderlich ist, es sind jedoch noch keine in der Datenbank vorhanden. Lassen Sie uns einige mit der Shell erstellen. Wir können die Shell mit manage.py ausführen

from feed.models import Post
Jetzt importieren wir unser Post-Modell

Post.objects.create(text='hello world')
exit()
Als nächstes erstellen wir einen einfachen Beitrag mit einer Zeichenfolge und verlassen die Shell. Die Zeichenfolge kann beliebig sein, solange es sich um gültigen Text handelt.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
Zuletzt müssen wir unserem Feed ein URL-Muster hinzufügen. Da unsere Feed-App mehrere URLs verwendet und wir die Dateigrößen klein halten möchten, erstellen wir in unserer Feed-App eine lokale urls.py, die so aussieht:

from django.urls import include # Wir müssen auch die urls.py in der Basis-App bearbeiten, wie auch immer wir sie nennen wollten, dies war das erste Verzeichnis, das wir erstellt haben. Bearbeiten Sie app/app.py und fügen Sie Folgendes zu den URL-Mustern hinzu

urlpatterns = [
    #
    path('feed/', include(('feed.urls'), namespace='feed')),
]
oben

... vorheriger Code hier

backup
Wenn wir nun den Server mit python manage.py runserver ausführen, sehen wir die von uns erstellte Seite, da wir über das Modell, die Ansicht und die Vorlage sowie das URL-Muster sowie über Elemente in der Datenbank verfügen. Als Nächstes implementieren wir das von uns erstellte Formular und beginnen mit der Erstellung unserer eigenen Beiträge. Aber bevor wir zu viel Code schreiben, erstellen wir ein Backup mit dem zuvor geschriebenen Skript „Backup". Führen Sie dieses Skript in der Shell aus, warten Sie einen Moment und der gesamte Code wird in unserem Git-Repository gesichert.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Die Implementierung des Formulars ist relativ einfach. Wir importieren unser Formular, fügen der Ansicht einen Post-Request-Handler hinzu und speichern den Beitrag in der Datenbank, bevor wir zur gleichen Ansicht umleiten. Wir können die bereits importierte Umleitungsfunktion und eine andere Funktion namens „reverse" verwenden, um die URL für das Ansichtsmuster abzurufen. Wir werden dies mit der Zeichenfolge „feed:feed" abfragen, da der Namespace des enthaltenen Musters „feed" ist und die Ansicht auch „feed" heißt.
    if request.method == 'POST': #
        form = PostForm(request.POST) # Fragen Sie alle bisherigen Beiträge in der Datenbank ab
        if form.is_valid(): # Behandeln Sie die Post-Anfrage
            form.save() # Erstellen Sie eine Instanz des Formulars und speichern Sie die Daten darin
        return redirect(reverse('feed:feed')) # Bestätigen Sie das Formular
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # Speichern Sie das neue Objekt
        'posts': posts,
    })
Leiten Sie mit einer Get-Anfrage zur gleichen URL weiter

Stellen Sie sicher, dass das Formular an den Kontext übergeben wird, damit wir es rendern können.

Jetzt müssen wir die Vorlage aktualisieren, um das neue Formular zu berücksichtigen. Wir können dies tun, indem wir die verwenden
 <!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>
 
Tag in HTML und Rendern des Formulars in der HTML-Vorlage mit einer Senden-Schaltfläche. Wir benötigen außerdem ein CSRF-Token, ein Token, das verhindert, dass externe Websites Beiträge im Formular veröffentlichen, ohne zuvor eine Seite zu laden.

Lassen Sie uns das aufschlüsseln. Es gibt eine neue Formularklasse, ein Token, das Formular selbst und eine Schaltfläche zum Senden. Ziemlich einfach, aber wenn wir es uns ansehen, möchten wir vielleicht, dass es besser aussieht. Es funktioniert, wir können mit dem Formular neue Beiträge posten und diese werden nun in der Datenbank gespeichert. Hier ist einiges los. Wir verwenden HTML-Tags, um zu deklarieren, dass das Dokument ein HTML-Dokument ist, wir verwenden ein Vorlagen-Tag ({% … %}), um das Token für das Formular darzustellen, und ein weiteres, {{ … }}, um das Formular darzustellen. Wir haben auch eine Schleife zum Rendern des Texts mithilfe von Block-Tags und einem Template-Tag. Block-Tags sind wirklich wichtig, weil wir definieren können, wie Abschnitte der Vorlage mit ihnen gerendert werden, und Vorlagen-Tags sind die Grundlage dafür, wie wir Variablen in unseren Code einfügen.

Jetzt müssen wir unsere App besser aussehen lassen, denn im Moment sieht sie wirklich einfach aus. Wir können dies tun, indem wir CSS verwenden, entweder inline oder in Klassen, die an jedes Objekt im Dokument gebunden sind. CSS ist wirklich nett, weil es alles auf der Seite sagt, wie es aussehen soll, und es wirklich gut aussehen lassen kann. Es gibt einige Bibliotheken, die das können, aber meine persönliche Wahl ist Bootstrap.Bootstrap kann von ihrer Website heruntergeladen werden.

getbootstrap.com/

. Klicken Sie dort auf die Schaltfläche, um die Installationsdokumente zu lesen, und kopieren Sie den Code aus dem Abschnitt „Einschließen über CDN". 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 nicht in jeder Vorlage neu erstellen müssen.

Erstellen Sie mit mkdir templates ein neues Verzeichnis namens templates und bearbeiten Sie dann templates/base.html.

 <!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>
 
Es sollte so aussehen:

Stellen Sie sicher, dass Sie CSS und JavaScript sowie die .css- und .js-Dateien kopieren, da wir das JavaScript benötigen, um unsere Website in Zukunft funktionsfähiger zu machen.

pip install django-crispy-forms
Kehren wir nun zur Bash-Shell zurück und führen einen kurzen Befehl aus. Denken Sie daran: Wenn Sie jemals auf die virtuelle Umgebung zugreifen müssen, geben Sie source venv/bin/activate ein. Dadurch können Sie Python-Pakete lokal installieren, sodass Django darauf zugreifen kann. Um unsere durch Django-Bootstrap-Klassen generierten Formulare bereitzustellen, verwenden wir ein Python-Paket namens Crispy Forms. Wir können dies mit dem folgenden Befehl herunterladen

INSTALLED_APPS = [
    # Sobald dies installiert ist, fügen Sie es der Datei „settings.py" hinzu
    'crispy_forms',
]

… vorheriger Code hier

 {% 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 %}
 
Zurück in unserer Feed-Vorlage können wir jetzt einige Dinge entfernen. Entfernen wir den Anfang und das Ende des Dokuments und ersetzen wir es durch eine Vererbung aus unserer Basisvorlage, indem wir Extends und die Blockdefinition verwenden. Außerdem werden wir dem Formular einen Vorlagenfilterimport mit Last und einen Vorlagenfilter hinzufügen. Zum Schluss fügen wir der Schaltfläche im Formular eine Bootstrap-Klasse hinzu, damit sie eher wie eine Schaltfläche aussieht. Das sollte so aussehen:

Schön! Das ist schon eine ganze Menge Code. Als nächstes sollten wir es testen und sicherstellen, dass alles gut aussieht und dass alles ordnungsgemäß funktioniert. Führen Sie den Server gemäß den vorherigen Anweisungen aus und stellen Sie sicher, dass die Site ordnungsgemäß aussieht und funktioniert. Tolle Arbeit! Sie können jetzt mit dem nächsten Schritt fortfahren, in dem wir Benutzeranmeldefunktionen mithilfe ähnlicher URLs, Formulare, Ansichten und Vorlagen hinzufügen. Die Basisvorlage ist wichtig, und wir werden sie bei Bedarf weiterhin modifizieren und ändern. Konzentrieren wir uns jedoch zunächst darauf, unsere Website sicherer zu machen, indem wir Benutzern ermöglichen, sich mit einem Benutzernamen und einem Passcode anzumelden, und schließlich mit noch wichtigeren Informationen, die dazu beitragen, dass Ihre App sicher bleibt und Ihr eigenes Konto nur für Sie zugänglich ist.

Dazu müssen wir das in Django integrierte Benutzermodell verwenden. Das Benutzermodell ist ein Datenbankmodell, wie unser Beitrag, das gerendert werden kann, um einen Benutzer auf der Website anzumelden. Bevor wir die Site im Internet bereitstellen, werden wir dieses Modell in Zukunft um andere Modelle erweitern, die ihr zugeordnet sind, und zusätzliche Sicherheitsmaßnahmen für die Anmeldung entwickeln, die gegen Phishing resistent sind. Wir beginnen mit der Verwendung einiger integrierter Anmeldeformulare, die Django bereitstellt. Erstellen wir zunächst eine neue App, mit der wir die Vorlagen und Ansichten für die grundlegende Anmeldeseite rendern. Wir werden auch andere Apps erstellen, um die anhaltenden Anmeldeherausforderungen darzustellen und die App zu sichern, einschließlich PIN-Code, Gesichtserkennung, Nahfeldkommunikation, externe Geräte, Multi-Faktor-Authentifizierung und Fingerabdruckerkennung.

python manage.py startapp users
Wir haben bereits darüber gesprochen, eine App zu starten. Übergeben Sie in unserem Verzeichnis innerhalb der virtuellen Umgebung manage.py diese Argumente

Jetzt sollten wir ein Verzeichnis für die neue App haben. Beginnen wir mit der Erstellung einer Ansicht in diesem Verzeichnis, die der Benutzeranmeldung entspricht. Django hat Ansichten für Benutzeranmeldungen eingebaut, aber diese werden für uns nicht geeignet sein, da wir eine benutzerdefinierte Ansicht benötigen, was vorzugsweise mit einer Definition erfolgt.

In dieser Ansicht prüfen wir zunächst, ob eine Post-Anfrage vorliegt, übergeben request.POST an ein aus Django importiertes LoginForm, authentifizieren das Benutzerkonto und melden den Benutzer an, bevor wir ihn zu unserer Feed-App weiterleiten.

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'] # Fügen Sie in „users/views.py" den folgenden Code hinzu
        password = request.POST['password'] #
        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()})
Holen Sie sich den Benutzernamen und das Passwort aus der Post-Anfrage

Authentifizieren Sie den Benutzer

mkdir users/templates
mkdir users/templates/users
Das ist alles, was Sie für eine einfache Anmeldeansicht benötigen. Erstellen wir nun ein Formular für die Ansicht, indem wir die Basisvorlage erweitern. Wir beginnen mit der Erstellung eines neuen Verzeichnisses für Vorlagen im Benutzerordner.

nano users/templates/users/login.html
Jetzt sollten wir in der Lage sein, „users/templates/users/login.html" zu bearbeiten. Während wir schon dabei sind, erstellen wir eine Vorlage, damit sich auch der Benutzer anmelden kann.

 {% 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 %}
 
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">Create an account</legend>
        {{ form|crispy }}
    </fieldset>
    <div class="form-group">
        <button class="btn btn-outline-info" type="submit">Register</button>
    </div>
</form>
{% endblock %}
 
Dies sind die Grundlagen einer Login-Vorlage. In der Struktur ähnelt es eigentlich der anderen Vorlage, beim Rendern sieht es jedoch etwas anders aus. Wir können diesen Code kopieren, um eine weitere, 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 erstellen. Bearbeiten Sie „users/templates/users/register.html" 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']
Erstellen wir nun ein Formular für unsere Benutzerregistrierung und kehren wir zu den Ansichten zurück, bevor wir unsere Benutzeranmeldungen mit einem Modell aktualisieren. Wir werden dieses Formular zunächst einfach gestalten, aber in Zukunft weitere Details und Sicherheitsfunktionen wie Vereinbarungen und Captcha integrieren. Bearbeiten Sie die Formulare mit nano-users/forms.py und fügen Sie den folgenden Code hinzu.

Wir haben hier also ein anderes Formular, das ziemlich einfach funktioniert. Es handelt sich um ein Benutzerregistrierungsformular mit einem Benutzernamen, einer E-Mail-Adresse und einem Passwort sowie einem Feld zur Passwortbestätigung. Beachten Sie, dass dieses Formular die reguläre Forms.Form-Klasse nicht erweitert, sondern ein Modellformular ist, was bedeutet, dass es über eine Meta verfügt. Ein Feld ist genauso definiert, und die Klasse Meta definiert das Modell, dem das Formular entspricht, den restlichen Informationen, die in das Formular geschrieben werden. Das meiste davon ist bereits in Djangos integrierter UserCreationForm vorhanden, daher werden wir es als Basis für die Klasse verwenden (in Klammern übergeben).

# Als Nächstes untersuchen wir die Ansicht zum Registrieren eines Benutzers, da wir nun über ein Formular und eine Vorlage verfügen. Dies ist eine ModelForm, genau wie die in der neuen Beitragsansicht. Bearbeiten Sie „users/views.py" und fügen Sie den folgenden Code hinzu:
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})

… Importe

from django.db import models # Das ist alles, was wir brauchen, um einen Benutzer zu registrieren, aber wir sollten über weitere Informationen verfügen. Wir möchten wissen, wann sich der Benutzer registriert hat, wann er das letzte Mal auf der Website war, einige Informationen über ihn, wie eine Biografie, Zeitzone usw. Außerdem müssen wir unser Feed-Modell „Post" aktualisieren, um das Benutzermodell zu berücksichtigen und Beiträge jedem Benutzer zuzuordnen. Dazu werden wir die models.py in beiden Apps aktualisieren. Beginnen wir mit der Bearbeitung des Feed-Modells. Es sollte jetzt so aussehen:
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') #
    text = models.TextField(default='')
… Importe

Fügen Sie diese Zeile hinzu

Achten Sie auf die zweite Zeile, die der Datei hinzugefügt wurde. Dabei handelt es sich um einen Fremdschlüssel, der jeden Beitrag einem einzelnen Benutzer pro Beitrag zuordnet. So können wir sicherstellen, dass wir die Beiträge auf Benutzerbasis speichern und kein Beitrag erstellt werden kann, ohne ihn einem Benutzer zuzuordnen. Wir definieren diesen Fremdschlüssel mit der Klasse, die er darstellt, einem Löschargument, um sicherzustellen, dass Beiträge mit Benutzern gelöscht werden, Null- und Leerargumenten, um sicherzustellen, dass wir den Benutzer bei Bedarf entfernen können, und um dem Fehlen eines Benutzers in bereits erstellten Beiträgen Rechnung zu tragen, sowie einem zugehörigen Namen, mit dem wir auf die vom Benutzer erstellten Beitragsobjekte verweisen können. Dieser verwandte Name gibt uns im Gegensatz zu post.author, dem Autor des Beitrags, den Benutzer an, der den Beitrag selbst gepostet hat. Wir können jetzt die Beiträge eines Benutzers abrufen, indem wir user.posts.all() oder author.posts.all() ausführen.

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='')
Jetzt machen wir unsere Anmeldungen widerstandsfähiger. Wir können unsere Website bereits viel weniger anfällig für Phishing machen, indem wir einfach die Häufigkeit begrenzen, mit der wir eine Anmeldung auf der Website zulassen. Das ist ganz einfach. Beginnen wir auch damit, einige Informationen über jeden Benutzer zu speichern, bevor wir unsere App weiterentwickeln. Bearbeiten Sie „users/models.py" und fügen Sie den folgenden Code hinzu.

Beachten Sie, dass dieses Modell dem Post-Modell ziemlich ähnlich ist. Wir haben einen zusätzlichen Import, timezone, der es uns ermöglicht, Standardwerte für die Datums-/Uhrzeitfelder festzulegen, und wir haben auch ein CharacterFeild und ein TextField wie im Beitrag. Die Verwendung all dieser Zeitstempel hilft uns, die Website zu sichern und ihre Nutzung zu verstehen, und die Textfelder ermöglichen es uns, Informationen über jeden Benutzer oder Autor auf der Website darzustellen. Das OneToOneField sollte die einzige untergeordnete Überlegung sein, es verhält sich genau wie ein ForeginKey, jedoch mit nur einem pro nachfolgendem Modell. Auf diese Weise hat der Benutzer nur ein Profil, obwohl er möglicherweise viele Beiträge hat.

# Lassen Sie uns nun unsere Anmelde- und Registrierungsansichten verbessern, um das Profil zu berücksichtigen. Bearbeiten Sie zunächst „users/views.py" und konzentrieren Sie sich auf die Registeransicht:
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) #
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
… Importe

Stellen Sie sicher, dass Sie diese Zeile hinzufügen, um ein Profil für den Benutzer zu erstellen

# Dadurch wird einfach ein Profil für den Benutzer erstellt, ohne dass irgendwelche Informationen eingegeben werden müssen. Jetzt möchten wir sicherstellen, dass das Benutzerkonto nicht zu oft angemeldet wird oder zumindest nicht zu oft mit Passwörtern versucht wird, also aktualisieren wir die Anmeldeansicht.
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(): #
            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: # … Importe
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Beachten Sie, dass wir jetzt prüfen, ob sich der Benutzer anmelden kann
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Wenn die Anmeldung nicht erfolgreich war,
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Dies ist der Teil, in dem wir das Benutzerprofil aktualisieren

Sie können sich also einige Sekunden lang nicht erneut anmelden

Dies ist die Grundvoraussetzung für Sicherheit. Stellen Sie sicher, dass die Website nicht dafür anfällig ist, dass jemand einfach jede mögliche Passwortkombination oder sogar einige davon gleichzeitig ausprobiert. Dies wird für den normalen Benutzer, der seinen Passcode kennt und sich nur auf einigen wenigen Geräten anmeldet, nicht frustrierend sein, aber es hält zahlreiche Phishing-Roboter von der App fern. Beachten Sie, dass wir eine if-Anweisung mit einer Variablen, can_login, hinzugefügt haben, die ein Zeitpunkt in der Vergangenheit sein sollte, und sie bei jeder erfolglosen Anmeldung mit demselben Benutzernamen aktualisieren. Auf diese Weise kann ein böswilliger Benutzer ein Passwort nicht annähernd so schnell erraten. Die Anzahl der Sekunden in datetime.timedelta() kann ebenfalls aktualisiert werden, und die Website wird robuster, aber mit mehr Sekunden etwas weniger benutzerfreundlich. Ich empfehle für den Anfang 15.

sudo backup
Denken Sie daran, dass wir ein Backup-Skript erstellt haben, um unsere Arbeit zu speichern. Machen wir also jetzt eine Sicherungskopie von dem, was wir bisher haben, um sicherzustellen, dass wir alles gespeichert haben. Führen Sie den Befehl aus:

sudo crontab -e
Dies erspart Ihnen wiederum die bisherige Arbeit. Ich empfehle, häufige Backups durchzuführen, um Ihre Arbeit zu speichern. Möglicherweise möchten Sie sogar einen Backup-Auftrag automatisch ausführen. Sie können dies mit einem UNIX-Dienstprogramm namens cron tun. Um dieses Dienstprogramm zu aktivieren, führen Sie den folgenden Befehl aus und geben Sie Ihr Passwort ein:

0 * * * * sudo backup
Wenn Sie noch nicht Option 1 für Nano ausgewählt haben, 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:

Cron verwendet das Format Minute, Stunde, Tag des Monats, Monat, Wochentag, wobei ein * oder eine Zahl angibt, wann der Befehl ausgeführt werden soll. Mit einer 0 für die Minute und einem * für die restlichen Optionen können wir zu Beginn der Minute in der ersten Minute jeder Stunde einen Befehl ausführen. Dadurch können wir den Code automatisch sichern. Alle Cron-Jobs werden, wenn sie mit sudo ausgeführt werden, als Root ausgeführt, sodass wir nicht jede Stunde ein Passwort eingeben müssen.

sudo visudo
Um die Sicherung unseres Codes ohne Verwendung eines Kennworts zu vereinfachen, deaktivieren wir das Kennwort für unseren Sicherungsbefehl. Wir tun dies, indem wir den folgenden Befehl ausführen und ein Passwort eingeben:

ALL ALL=NOPASSWD: /bin/backup
Scrollen wir nun zum Ende der Datei und fügen eine weitere Zeile hinzu:

Dadurch können wir den Befehl „backup" als beliebiger Benutzer ohne Passwort ausführen. Das Format dafür ist einfach: Stellen Sie der Zeile einfach „ALL ALL=NOPASSWD: /bin/" voran und schließen Sie mit dem Befehl ab, zum Beispiel /bin/backup, der in /usr/bin/ vorhanden ist.

Beginnen wir nun mit der Arbeit mit E-Mail. E-Mail ist für Websites wirklich wichtig, da sie eine Möglichkeit bietet, die Sicherheit einer Website zu erhöhen, zu überprüfen, ob es sich bei Benutzern um echte Personen handelt, und sogar Produkte oder Dienstleistungen an Kunden zu vermarkten. Viele Menschen, die häufig im Internet surfen, checken täglich ihre E-Mails und erhalten alle möglichen Marketing-E-Mails über Produkte und Dienstleistungen, an denen sie interessiert sind. Es gibt mehrere Möglichkeiten, E-Mails auf einer Django-Website zu aktivieren, und Sie können gerne diejenige auswählen, die für Sie am besten geeignet ist.

Erstens können Sie für einen E-Mail-Dienst bezahlen, der Ihnen das Versenden von E-Mails von Ihrer Domain aus ermöglicht und nur minimalen Code erfordert. Es gibt viele Dienste, die dies anbieten, wie zum Beispiel Google Workspace, Sendinblue, Mailgun und mehr.

Andernfalls sind Sie gut beraten, Ihren eigenen E-Mail-Dienst von Grund auf auf Ihrem Server aufzubauen. Ich empfehle diese Option, auch wenn sie mehr Code erfordert und möglicherweise ein spezielles Hosting erfordert. Sie werden höchstwahrscheinlich nicht in der Lage sein, einen Mailserver von Ihrem Heimcomputer aus zu starten. Schauen wir uns also zunächst die Konfiguration und den Code zum Senden von E-Mails an, bevor wir einen Server in der Cloud starten und darin unseren eigenen Mailserver erstellen.

nano app/settings.py
Bearbeiten Sie zunächst die Datei „settings.py" mit dem folgenden Befehl:

Dabei ist app der Name der App, die Sie mit startapp erstellt haben.

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)
Fügen Sie die folgenden Zeilen hinzu:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Stellen Sie sicher, dass Sie diese ändern, wenn Sie bereit sind, Ihre App bereitzustellen. Wir werden später noch einmal darauf zurückkommen. Die Einstellung EMAIL_ADDRESS sollte die E-Mail-Adresse sein, von der aus Sie senden möchten, und das Passwort (EMAIL_HOST_PASSWORD) sollte auf das Passwort eingestellt sein, das Sie für den Server generieren. Ich lade das Passwort aus einer Konfigurationsdatei, um es aus dem Code herauszuhalten, indem ich die folgende Logik über diesen Zeilen in „settings.py" verwende:

Dann habe ich mit Nano wie folgt eine JSON-Datei mit der Konfiguration in /etc/config.json eingerichtet.

sudo nano /etc/config.json
So bearbeiten Sie die Datei:

{
	"EMAIL_HOST_PASSWORD": "<some password here>"
}
Fügen Sie die folgenden Zeilen hinzu:

nano users/templates/users/verification_email.html
Wir werden die Konfigurationsdatei weiter bearbeiten und alle Passwörter und Schlüssel hinzufügen, die wir in der App verwenden werden. Lassen Sie uns zunächst kurz untersuchen, wie Sie E-Mails mit Python senden. Erstellen wir zunächst eine Vorlage für eine Bestätigungs-E-Mail, die wir an unsere Benutzer senden können, und legen Sie sie im Benutzervorlagenverzeichnis ab. Diese Vorlage wird in HTML geschrieben.
 <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>
 

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

BASE_URL = PROTOCOL + '://' + DOMAIN
Diese E-Mail ist ziemlich einfach. Es benötigt einen Kontext eines Benutzers, die Basis-URL für die Site sowie eine Benutzer-ID und ein Token, die zur Überprüfung der E-Mail-Adresse des Benutzers verwendet werden. Stellen Sie sicher, dass Sie die Basis-URL in „settings.py" definieren, bevor wir Python-Code zum Rendern der Vorlage schreiben. Fahren Sie fort und fügen Sie am Anfang die folgenden Zeilen zu app/settings.py hinzu.

Wenn Ihre Site schließlich für das Internet bereit ist und Sie sie bereitstellen, möchten Sie Ihre Domain als den Domainnamen definieren, den Sie kaufen, um die Site zu repräsentieren. Dies ist der Name, den Sie in die Navigationsleiste eingeben, um auf Ihre Website zuzugreifen. Sie können die Domäne vorerst leer lassen oder einen Platzhalter verwenden. Sie sollten den SITE_NAME auch in einen Namen Ihrer Wahl ändern, den Sie Ihrer Website geben möchten.

nano users/tokens.py
Bevor wir E-Mails versenden, erstellen wir einen Token-Generator, damit wir über ein Kontoaktivierungstoken verfügen, das niemals abläuft. Wir können dies tun, indem wir ein Kontoaktivierungstoken erstellen und importieren, das wie folgt aussieht. Bearbeiten Sie die Datei:

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()
Fügen Sie den folgenden Code hinzu:

Dieser grundlegende Token-Generator generiert ein Token, das wir dem Benutzer in einer URL senden können und mit dem der Benutzer seine E-Mail-Adresse bestätigen und sein Konto aktivieren kann.

nano users/email.py
Als nächstes sehen wir uns an, wie man eine E-Mail sendet. Bearbeiten Sie mit nano die Datei „users/email.py".

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 Versenden der Bestätigungs-HTML-E-Mail sieht folgendermaßen aus:

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()
Das ist ziemlich einfach. Wir importieren die Funktionen, die wir zum Senden der E-Mail benötigen, rendern die E-Mail mit Vorlagen und unseren Einstellungen, definieren dann die E-Mail anhand des Vorlagennamens und senden sie mithilfe einer Funktion an den Benutzer. Sie werden feststellen, dass wir die Funktion „send_html_email" zum Senden der E-Mail noch nicht definiert haben. Schreiben wir dies also unter den Code, den wir bereits zu „users/email.py" hinzugefügt haben

Das ist etwas komplexer und wir sind noch nicht bereit, den gesamten Code auszuführen. Beachten Sie, dass wir einen unsub_link definieren, den Link, den der Benutzer verwenden kann, um sich von unseren E-Mails abzumelden. Dies ist wichtig, da Benutzer jederzeit die Möglichkeit haben müssen, unsere E-Mails abzubestellen, sofern sie diese nicht sehen möchten. Wir fügen unserer Nachricht auch eine Textalternative hinzu, nämlich die HTML-Nachricht ohne HTML-Tags. Abschließend prüfen wir, ob die E-Mail gesendet wurde. Ist dies nicht der Fall, markieren wir im Profil des Benutzers, dass seine E-Mail-Adresse ungültig ist.

Kommen wir zurück zu den Benutzermodellen, damit das alles funktioniert. Wir müssen eine Funktion definieren, um einen Link zum Abmelden zu generieren, und ein boolesches Feld definieren, um zu markieren, dass die E-Mail-Adresse des Benutzers ungültig ist.

nano users/models.py
Fügen Sie zunächst die folgenden Importe oben in „users/models.py" hinzu
#
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse

# Als Nächstes fügen wir dem Benutzermodell Funktionen hinzu, um das Token zu erstellen und das zum Aktivieren der E-Mail verwendete Token zu überprüfen, sowie das Feld, um zu speichern, ob der Benutzer seine E-Mails erfolgreich erhält. Fügen Sie in „users/models.py" erneut den folgenden Code am Ende des Modells hinzu (eingerückter Code).
    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) #
        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,})

Gültig für 30 Tage

Das ist ziemlich einfach: Wir verwenden einen Timestampsigner, ein grundlegendes kryptografisches Tool, um ein Token zu erstellen, das nach einer bestimmten Zeit abläuft, und wir verwenden außerdem eine andere Funktion, um zu überprüfen, ob es gültig ist. Wir verwenden diese Token zweimal, einmal zur Verifizierung der E-Mail und einmal für einen Abmeldelink.

nano users/views.py
Nachdem wir diese nun haben, ist die letzte Arbeit, die wir erledigen müssen, die Ansichten. Fügen wir in „users/views.py" Ansichten hinzu, um die E-Mail-Adresse zu überprüfen und sich abzumelden.

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 # Fügen Sie zunächst die folgenden Importe hinzu. Ich habe ein paar zusätzliche hinzugefügt, damit wir später nicht noch mehr Artikel importieren müssen.
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

Stellen Sie sicher, dass Sie die Funktion zum Versenden von Bestätigungs-E-Mails importieren

Möglicherweise verfügen Sie bereits über einige dieser Importe, aber es kann nicht schaden, sie zu wiederholen. Sie müssen unter anderem die Funktion zum Versenden von Bestätigungs-E-Mails sowie account_activation_token aus „users.tokens" importieren.

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)):
        # Fügen Sie nun am Ende der Datei den folgenden Code hinzu:
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    #
    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()
# kündigen Sie sie
        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})
Andernfalls leiten Sie zur Anmeldeseite weiter

sendwelcomeemail(Anfrage, Benutzer)

nano users/views.py
Das ist eine Menge Code. Lassen Sie es uns aufschlüsseln. Die erste, klare und einfache Funktion besteht darin, den Benutzer von der Mailingliste abzumelden. Die zweite Funktion aktiviert ihre E-Mail, und Sie werden feststellen, dass ich eine Kommentarfunktion hinzugefügt habe: sendwelcomeemail. Sie können gerne eine E-Mail-Vorlage und eine Funktionsdefinition verwenden, um eine Willkommens-E-Mail zu senden, ich habe es nur noch nicht getan. Die letzte Funktion, die ich eingefügt habe, ist wichtig, da Aktivierungs-E-Mails ablaufen. Daher müssen wir die Aktivierungs-E-Mail von Zeit zu Zeit erneut senden. Wir können hierfür ein einfaches Formular verwenden und die Funktion zum Versenden der Bestätigungs-E-Mail aufrufen. Bevor wir dies tun, stellen wir sicher, dass es überhaupt gesendet wird, indem wir der Registeransicht einen Funktionsaufruf hinzufügen. Fügen Sie diese Zeile direkt vor der Umleitung in der Registeransicht (def register) in „users/views.py" hinzu.
#
            send_verification_email(user)
#
… (nach) def register(request):

… (vor) weiterleiten(

# Sie müssen die erste und letzte Zeile in diesem Code-Snippet nicht hinzufügen. Stellen Sie lediglich sicher, dass die Registrierungsansicht die Bestätigungs-E-Mail an den Benutzer sendet. Es sollte so aussehen:
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) #
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
… Importe

Fügen Sie diese Zeile unbedingt hinzu!

# Jetzt müssen wir ein Formular hinzufügen, um die Aktivierungs-E-Mail erneut zu senden. Fügen Sie in „users/forms.py" das folgende Formular hinzu:
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)

… (Importe)

nano users/templates/users/resend_activation.html
Wir benötigen außerdem eine Vorlage, die diesem E-Mail-Aktivierungsformular für den erneuten Versand entspricht. Fügen wir diese Vorlage hinzu. Bearbeiten Sie die Datei:

 {% 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 %}
 
Fügen Sie als Nächstes den folgenden Code zur Datei 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)
Puh, das ist eine Menge! Wenn wir nun den Code auf unserem Server bereitstellen, können wir HTML-E-Mails senden und Benutzerkonten mit einem Klick in der E-Mail aktivieren. Möglicherweise möchten wir auch eine einfache Willkommens-E-Mail senden. Sehen wir uns also an, wie das geht. Fügen Sie in „users/email.py" den folgenden Code hinzu:

 <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>
 
Außerdem benötigen wir eine Vorlage, um alle diese Informationen darzustellen. Auf meiner Website sieht die Vorlage wie folgt aus, Sie können sie aber gerne beliebig formatieren.

Beachten Sie, dass wir keine schließenden Text- oder HTML-Tags haben, da wir diese hinzufügen, wenn wir den HTML-Abmeldelink hinzufügen. Diese sind wichtig, aber wir wollen sie nicht doppelt definieren.

Was kommt also als nächstes? Wir haben einen langen Weg zurückgelegt. Eigentlich sollten wir bereit sein, die Site auf einem Server bereitzustellen. Wir können den @login_required-Dekorator hinzufügen und unsere Ansichten sicher machen, Benutzeranmeldungen entgegennehmen, konforme E-Mails senden und Informationen zwischenspeichern, die die Grundlage dafür bilden, was eine Website tun muss, um relevant zu bleiben. Wir fügen ein paar weitere nützliche Funktionen hinzu und schaffen dann eine Grundlage für die Bereitstellung unseres Codes auf einem Remote-Server, die Einrichtung eines Mailservers, die Domänenkonfiguration und Filter, um unsere Site sicher und angemessen zu machen.

# Wir benötigen auch eine Ansicht zum Zurücksetzen des Passworts, also fügen wir diese ganz schnell hinzu. Djangos integrierte Ansicht zum Zurücksetzen von Passwörtern ist in einigen Funktionen fehlerhaft, aber wir werden uns ansehen, wie wir unsere eigene Ansicht, E-Mail-Vorlage, Formulare und URL-Muster schreiben. So sieht die Ansicht in „users/views.py" aus
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)

... Importe

 {% 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 %}
 
Dieses Formular ist in Django integriert, wir benötigen jedoch eine Vorlage, um das Zurücksetzen des Passworts zu bestätigen: „users/templates/users/password_reset_confirm.html".

 {% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Request Password Reset</button>
            </div>
        </form>
{% endblock content %}
 
Wir haben auch eine Vorlage zum Senden einer E-Mail zum Zurücksetzen des Passworts mit einem einfachen Formular unter „users/templates/users/password_reset.html".

 <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>
 
Die Vorlage für die E-Mail selbst ist einfach: Es handelt sich um eine einfache HTML-Datei, die einen Link zum Zurücksetzen des Passworts in „users/templates/users/password_reset_email.html" darstellt. Django interpretiert diese Datei automatisch.

 {% 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 %}
 
Wir benötigen außerdem zwei weitere Vorlagen. Die erste besteht darin, zu bestätigen, dass die E-Mail gesendet wurde. Ansichten dafür gibt es bereits in Django, daher müssen wir sie nur in der urls.py ansprechen. Diese Vorlage befindet sich unter „users/templates/users/password_reset_done.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 %}
 
Und schließlich, um zu bestätigen, dass das Zurücksetzen des Passworts abgeschlossen ist, user/templates/users/password_reset_complete.html

urlpatterns = [
    # Jetzt benötigen wir URL-Muster für diese Ansichten. Fügen Sie in „users/urls.py" die folgenden URL-Muster hinzu:
    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'),
]

... Frühere URLs hier

Vier Vorlagen, das ist viel! Aber jetzt können wir sicher sein, dass wir das Passwort des Benutzers jederzeit über den Webbrowser zurücksetzen können.

Ich verstehe, dass das eine Menge Code ist. Wenn es Ihnen etwas zu hoch erscheint, ist das in Ordnung. Sie werden sich verbessern, Ihr Verständnis wird sich verbessern und Sie werden sehr bald viel kompetenter im Umgang mit Code sein. Wenn Sie völlig verloren sind, empfehle ich Ihnen, später auf diese Software zurückzukommen, nachdem Sie an einem Online-Kurs zum Erlernen des Programmierens im Selbststudium gearbeitet haben. Diese sind für den Einstieg in der Regel kostenlos und führen Sie durch alles, was Sie für den Erfolg benötigen, wenn Sie zu diesem Projekt zurückkehren. Wenn Sie das Gefühl haben, dass Sie bereit sind, fortzufahren, lesen Sie weiter. Als Nächstes behandeln wir die Bereitstellung Ihres Codes auf einem Remote-Server und die Einrichtung eines Mailservers sowie die Automatisierung Ihrer Bereitstellung mithilfe von Bash, sodass Sie jederzeit mit ein paar einfachen Befehlen ein neues Projekt einrichten können.

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# Das Letzte, was wir vor der Bereitstellung auf einem Remote-Server tun müssen, ist, unsere Site ein wenig sicherer zu machen. Sie werden feststellen, dass in der Anmeldeansicht nur ein Benutzername und ein Kennwort erforderlich sind und keine Multi-Faktor-Authentifizierung oder ein einmaliger Zeitcode vorhanden ist. Dies ist eine einfache Lösung, und mit demselben Code können wir dafür sorgen, dass unsere Website Textnachrichten sendet und sogar auf Textnachrichten reagiert, die an den Server gesendet werden. Zunächst kehren wir zu den Benutzermodellen zurück und fügen einen Zeitstempel-Signierer hinzu, der jede Anmeldung darstellt. Wir werden dem Benutzermodell außerdem eine eindeutige, rotierende Kennung hinzufügen, die verwendet wird, um unserem Login zusätzliche Sicherheit zu verleihen. Bearbeiten Sie die Benutzermodelle „users/models.py" und fügen Sie den folgenden Code hinzu:
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='')
    #
    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)

    # Stellen Sie sicher, dass Sie die UUID, den Zeitstempel-Unterzeichner und den URL-Generator (umgekehrt) importieren.
    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) # Fügen Sie diesen Code hier hinzu
        except (BadSignature, SignatureExpired):
            return False
        return True
Und fügen Sie diese Funktion hinzu

Gültig für 3 Minuten

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Stellen Sie sicher, dass Ihre Datei „users/models.py" bis auf die Kommentare (Code in den Zeilen mit #) so aussieht. Wenn man das aufschlüsselt, ist es einfach. Wir haben ein paar Importe, einen TimestampSigner, ein kryptografisches Dienstprogramm, das einen sicheren Code generieren und ihn überprüfen kann, um sicherzustellen, dass er gültig ist, nur einmal verwendet wurde und nicht älter als eine bestimmte Anzahl von Sekunden ist. Wir verwenden auch eine UUID, eine eindeutige Kennung, die unseren Benutzer beim Signieren des Tokens und in der URL identifiziert, über die das Token an den Benutzer gesendet wird. Wir verwenden diese grundlegende Kryptografie, um eine Zwei-Faktor-Authentifizierungsansicht zu erstellen. Bevor wir etwas anderes tun, führen wir die Migrationen durch, damit unsere Benutzermodelle aktualisiert werden. Führen Sie im Verzeichnis mit manage.py die folgenden Befehle aus, um die Migrationen durchzuführen und abzuschließen.

Dies ist wichtig, da wir jedes Mal, wenn wir Änderungen an den Modellen vornehmen, die Tabellen erstellen und die Datenbank mit Standardwerten aktualisieren müssen, bevor wir die Modelle tatsächlich verwenden können.

# Als nächstes improvisieren wir unsere Anmeldeansicht, um zu einer sekundären Authentifizierungsansicht umzuleiten. Entfernen Sie in „users/views.py" die Anmeldefunktion und leiten Sie zu der URL weiter, die wir gerade in den Benutzermodellen generiert haben.

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(): #
            # … Importe
            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 jetzt prüfen, ob sich der Benutzer anmelden kann
            else: # Entfernen Sie die hier vorhandene Funktion auth_login
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # Beachten Sie, dass wir hier zu einer neuen URL weiterleiten
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Wenn der Benutzer keine Multi-Faktor-Authentifizierung verwendet, melden Sie ihn einfach an.
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Wenn die Anmeldung nicht erfolgreich war,
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Dies ist der Teil, in dem wir das Benutzerprofil aktualisieren

Sie können sich also einige Sekunden lang nicht erneut anmelden

Das ist also ziemlich einfach. Wir haben jetzt die Möglichkeit, beim Erstellen auf die Zwei-Faktor-Authentifizierungsansicht umzuleiten. Wir haben auch einen Fallback für den Fall, dass der Benutzer keine Telefonnummer hinzugefügt hat. Wir werden bald eine einfache Ansicht hinzufügen, um eine Telefonnummer hinzuzufügen und sich bald mit einer Textnachricht anzumelden.

nano users/sms.py
Zunächst benötigen wir eine einfache Möglichkeit, aus unserem Code eine Textnachricht zu senden. Dazu können wir aus einer Reihe von APIs wählen, die einfachste ist meiner Meinung nach jedoch Twilio. Sie bieten auch gute Preise für kleinere Projekte sowie Mengenrabatte. Erstellen Sie ein Konto auf Twilio.com, geben Sie einige Details zu Ihrem Projekt ein, kaufen Sie eine Telefonnummer und kopieren Sie Ihre API-Schlüssel in Ihre Settings.py. Fügen Sie diesen Code dann in einer neuen Datei hinzu, „users/sms.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
import traceback

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)
    except:
        print(traceback.format_exc())

# Importieren Sie alle erforderlichen Pakete
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# Dieser Code sendet den Text mit Twilio
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)))

# Eine Hilfsfunktion, um eine Zahl mit so vielen Ziffern zu erhalten
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# Senden Sie den Text, um den Benutzer zu verifizieren
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

# Mit dieser Funktion können Sie einem Benutzer einen beliebigen Text senden
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
Validieren Sie den Code mit dieser Funktion

Bestätigen Sie die Uhrzeit

# Stellen Sie sicher, dass Sie Ihre Einstellungen entsprechend ändern, indem Sie diese Zeilen mit Ihren Schlüsseln hinzufügen:
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 #
Stellen Sie sicher, dass Sie diese aus Ihrem Twilio-Dashboard kopieren

Die Anzahl der Minuten, die die TFA-Seite nach der Instanziierung aktiv ist

# Zunächst benötigen wir Formulare für unsere Zwei-Faktor-Authentifizierungsansichten. Bearbeiten Sie „users/forms.py" und fügen Sie den folgenden Code hinzu.
from django import forms

#
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

# … Importe
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.'
    }
Ein Formular zur Eingabe unserer Telefonnummer

Ein Formular zur Authentifizierung

# Als Nächstes erstellen wir die Ansichten in „users/views.py".
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})

… Importe

nano users/templates/users/mfa.html
Für beide Ansichten benötigen wir außerdem Vorlagen. Fügen wir zunächst die MFA-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 %}
 
Fügen Sie diesen HTML-Code zur Vorlage hinzu

nano users/templates/users/mfa_onboarding.html
Das ist ziemlich selbsterklärend. Das Formular sendet entweder einen Code oder einen leeren Code, und Sie werden in der Ansicht sehen, dass wir den Code senden, wenn wir einen leeren Code erhalten. Dann haben wir nur noch zwei Senden-Buttons, und auf diese Weise können wir den Code mit beiden Buttons senden. Als Nächstes fügen wir ein einfaches Formular zum Hinzufügen einer Telefonnummer 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 %}
 
Fügen Sie den folgenden HTML-Code hinzu:

Dieses Formular ist viel einfacher, es rendert lediglich das von uns erstellte Telefonnummernformular und ermöglicht dem Benutzer das Hinzufügen einer Telefonnummer.

Das sieht wirklich gut aus! Solange alles richtig eingerichtet ist, sollten wir in der Lage sein, Nachrichten zu senden und den Benutzer mit seiner Telefonnummer anzumelden, sobald wir die URL-Muster hinzugefügt haben. 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. Außerdem möchten wir irgendwann eine Option „Stopp zum Beenden" hinzufügen, damit der Benutzer eine SMS mit „Stopp" senden kann, um sich von zukünftigen Textnachrichten abzumelden.

# Fügen wir der Datei „users/views.py" eine Profilansicht hinzu. Diese Ansicht aktualisiert die Biografie, E-Mail-Adresse, den Benutzernamen und die Telefonnummer des Benutzers und ermöglicht uns die Aktivierung der Multi-Faktor-Authentifizierung. Zunächst benötigen wir zwei weitere Formulare in „users/forms.py".
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']

... Importe

# Als Nächstes können wir eine Ansicht erstellen, um beide Formen zu verwenden. Bearbeiten Sie „users/views.py" und fügen Sie die Ansicht 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)

Fügen Sie diese Importe hinzu

nano users/templates/users/profile.html
Wir benötigen auch eine Vorlage für diese Ansicht.
 {% 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 es sich um ein recht einfaches Formular handelt, das jedoch Javascript enthält, das den Inhalt des Formulars automatisch veröffentlicht, wenn er aktualisiert wird. Dies ist nützlich, damit Sie Änderungen vornehmen können, ohne jedes Mal auf „Senden" klicken zu müssen.

# Als nächstes benötigen wir URLs, die alle diese Ansichten in den URL-Mustern der Benutzer darstellen. Bearbeiten Sie „users/urls.py" und fügen Sie diesen Code hinzu:
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
#
    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'),
]
… vorheriger Code, Importe

… URL-Muster, die wir zuvor eingegeben haben, fügen Sie die nächsten drei Zeilen hinzu

backup
Jetzt ist ein guter Zeitpunkt, unser Projekt zu testen. Aber zuerst führen wir noch ein Backup durch.

python manage.py runserver localhost:8000
Und führen Sie den Server aus. Bevor wir die Bereitstellung auf einem Linux-Server durchführen, empfiehlt es sich, die Zwei-Faktor-Authentifizierung für das Konto zu aktivieren. Dazu gehen wir zu unserer Profil-URL /users/profile/ und markieren das Kästchen, um die Authentifizierung zu aktivieren, nachdem wir unsere Telefonnummer eingegeben und dann das Formular abgesendet haben.

Besuchen Sie die Webseite, indem Sie Ihren Webbrowser aufrufen (in diesem Beispiel verwende ich Google Chrome) und die URL https://localhost:8000/accounts/profile/ eingeben.

Sie können sich bei Bedarf anmelden und die Zwei-Faktor-Authentifizierung aktivieren.

Dieses Projekt benötigt einen Server, auf dem es laufen kann, damit es wirklich E-Mails versenden kann. Aber zuerst brauchen wir eine Möglichkeit, Fehler zu erkennen. Sie werden feststellen, dass der Server automatisch Fehler anzeigt, wenn Sie den Server im Debug-Modus ausführen, wobei „settings.DEBUG" auf „True" gesetzt ist. Um Fehler anzuzeigen, ohne den Debug-Modus zu verwenden, der auf einem Produktionsserver unsicher ist, sollten wir eine Ansicht dafür hinzufügen. Die wichtigsten Fehler, mit denen wir umgehen müssen, sind:

Fehler 500 – Ein Problem mit unserem Code Fehler 404 – Eine Seite wurde nicht gefunden (defekte URL) Fehler 403 – Ein Fehler, bei dem die Berechtigung verweigert wurde

python manage.py startapp errors
Fügen wir eine neue App hinzu, um diese Fehler, sogenannte Fehler, zu behandeln.

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
Fügen Sie dies wie zuvor in der Einstellung INSTALLED_APPS zur Datei „settings.py" hinzu und beginnen Sie mit dem Hinzufügen von Verweisen auf einige Ansichten in „app/urls.py", wobei „app" der Name Ihres Django-Projekts ist.

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

# Das ist alles, was wir neben Fehleransichten, Vorlagen und ein wenig Middleware brauchen. Definieren wir diese wie folgt:
@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.'})

Erstellen Sie hier Ihre Ansichten.

MIDDLEWARE_CLASSES = [
    # Als Nächstes definieren wir die Middleware zur Behandlung dieser Fehler. Dazu fügen wir zunächst den Namen unserer Middleware zu MIDDLEWARE_CLASSES in der Datei „settings.py" hinzu.
    'errors.middleware.ExceptionVerboseMiddleware,
]

... bisherige Middleware

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

_error = local()

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

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

def set_current_exception(exception):
    try:
        _error.value = exception
    except AttributeError:
        print('Attribute error setting exception.')
Als nächstes fügen wir die Middleware hinzu.

nano errors/templates/errors/error.html
Wir fügen eine Funktion hinzu, um die aktuelle Ausnahme mithilfe eines lokalen Threadings abzurufen, was uns dabei hilft, Fehler in unserem Code aufzuspüren. Was die Vorlagen betrifft, benötigen wir nur eine, da wir den Titel in der Ansicht dynamisch definieren. Die Vorlage muss lediglich den Titel und „trace", unseren Fehler-Traceback aus dem Kontext, rendern.
 {% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 

nano app/settings.py
Dies ist unsere bisher einfachste Vorlage, aber so einfach ist es, die Fehler in unserem Projekt zu erkennen. Als nächstes deaktivieren wir das Debuggen in den Einstellungen.

DEBUG = False
Suchen Sie diese Zeile, in der sie auf „True" gesetzt ist, und ändern Sie sie in „False".

sudo backup
Machen Sie jetzt ein Backup der App. Wir sind bereit für die Bereitstellung auf einem Remote-Linux-Server und können von dort aus weitere Funktionen hinzufügen.

Bevor wir diesen Code auf einem Server veröffentlichen, sollten wir bedenken, dass möglicherweise Probleme mit dem Code vorliegen. Je nach Fall haben Websites, die an sie gesendete Informationen akzeptieren, Probleme mit der Veröffentlichung von Spam und Schwierigkeiten beim Entfernen des Spams. Dies sollte nicht sofort passieren, aber wenn es doch passiert, werden wir später untersuchen, wie man Spam auf der Website automatisch moderiert und es Robotern erschwert, auf die Website zuzugreifen, außerdem wie man Benutzerkonten deaktiviert und die Identität eines Benutzers durch einen Scan seines Ausweises oder einen biometrischen Scan, wie einen Fingerabdruck oder eine Gesichtserkennung, überprüft.

nano users/models.py
Betrachtet man das Beispiel der Multi-Faktor-Authentifizierung, das wir untersucht haben, kann es in der Produktion anders sein. Beachten Sie, dass wir die Anzahl der Anmeldungen begrenzen und Token ablaufen lassen. Wenn Roboter auf eine Website zugreifen, kann die Zwei-Faktor-Authentifizierung schwieriger sein, da sie möglicherweise gleichzeitig mit dem Benutzer Codes eingeben. Um dem entgegenzuwirken, verwenden wir in den Benutzermodellen ein Modell, das angibt, wie wir mit der Site interagieren, wenn wir uns mithilfe der Multi-Faktor-Authentifizierung mit einer Telefonnummer authentifizieren. Wir werden auch eine Option zur Authentifizierung per E-Mail hinzufügen. Beginnen Sie mit der Bearbeitung der Benutzermodelle mit Nano.

# So sollte das Modell, das wir hinzufügen, aussehen. Wir benötigen keine Methoden, sondern nur Variablen zum Speichern einer ID, des Benutzers, des Zeitstempels, des Ablaufs, der Länge und der Versuche für eine Multi-Faktor-Authentifizierung (einen Code wie 123456, der an ein Telefon oder eine E-Mail gesendet wird).
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)

Ein grundlegendes Token, das zum Anmelden auf der Website verwendet wird

    vendor = models.BooleanField(default=False)
Fügen wir unserem Benutzer auch eine Berechtigung hinzu, die wir vorerst manuell festlegen, bevor wir schließlich zur automatischen Registrierung privilegierter Benutzer übergehen. Fügen Sie in den Benutzermodellen diese Zeile im Profil hinzu:

cd project-directory-you-named # Wie bei allen Änderungen an der Datenbank müssen wir jedes Mal Migrationen durchführen und die Datenbank migrieren, wenn wir eine models.py-Datei in Django bearbeiten. Denken Sie daran, dass wir dazu zuerst die Quelle verwenden (sofern sie nicht bereits verwendet wurde, seit das Terminal geöffnet war) und dann Python manage.py, um die Migrationen durchzuführen und zu migrieren.
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate

(falls erforderlich)

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
Derzeit können Sie über die Shell alle von Ihnen erstellten Konten als Anbieter eintragen.

nano users/mfa.py
Lassen Sie uns nun unsere Multi-Faktor-Authentifizierungsansicht weiterentwickeln, um dieses Token zu verwenden. Zuerst müssen wir unsere MFA-Hilfsprogramme ändern. Mit Nano,
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
#
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() #
    if not token: token = MFAToken.objects.create(user=User.objects.filter(profile__uuid=username).first(), uid=username, expires=timezone.now() + datetime.timedelta(seconds=115)) # Authentifizieren Sie den Benutzer mithilfe seiner E-Mail-Adresse oder Telefonnummer
    user = User.objects.filter(id=token.user.id).first() # Filtern Sie das Token nach dem in der URL übergebenen Wert (einer UUID).
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # Wenn diese Sitzung noch nicht erstellt wurde, erstellen Sie sie
    if not user: raise PermissionDenied() # Holen Sie sich den Benutzer aus dem Token
    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): # Wenn sie bereits authentifiziert sind, melden Sie sie an
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Ablehnen, wenn kein Benutzer gefunden wurde
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # Überprüfen Sie das Authentifizierungstoken
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # Melden Sie den Benutzer an, falls er noch nicht angemeldet ist
    if not user.profile.mfa_enabled: # Legen Sie ein Ablaufdatum für die Multi-Faktor-Authentifizierung fest
        if not check_verification_time(user, token): # Leiten Sie den Benutzer zur nächsten Seite weiter
            user.profile.mfa_enabled = False # Überprüfen Sie, ob MFA aktiviert ist
            user.profile.enable_two_factor_authentication = True # Überprüfen Sie die Uhrzeit
            user.profile.phone_number = '+1' # Löschen Sie die Telefonnummer
            user.profile.save() # MFA aktivieren
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Deaktivieren Sie die Telefonnummer
            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): # Speichern Sie das Profil
        form = TfaForm(request.POST) # Melden Sie den Benutzer an, wenn seine MFA nicht aktiviert ist
        code = str(form.data.get('code', None)) # Wenn es sich bei der Anfrage um eine Post-Anfrage handelt
        if code and code != '' and code != None: # Instanziieren Sie das Formular
            token_validated = user.profile.check_auth_token(usertoken) # Holen Sie sich den Code
            p = user.profile
            is_verified = check_verification_code(user, token, code) # Stellen Sie sicher, dass es nicht leer ist
            p.mfa_authenticated = is_verified
            if token_validated: # Überprüfen Sie das Authentifizierungstoken
                if is_verified: # Überprüfen Sie den Code
                    user.profile.mfa_enabled = True # Wenn alles
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Ist in Ordnung
                    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(): # MFA aktivieren (falls nicht bereits aktiviert)
                        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) # Melden Sie den Benutzer an
                    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: # Erstellen Sie eine Abfragezeichenfolge für den nächsten Parameter (falls vorhanden).
                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: # Umleiten
                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): # Wenn das Token ungültig war
                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('/'))
    # Wenn es zu viele Versuche gab
    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'})
Senden Sie die E-Mail (oder SMS)

Rendern Sie das Formular (für Get-Anfragen)

from .mfa import send_verification_email as send_mfa_verification_email
Wenn wir diesen Code hinzufügen, achten Sie darauf, die Funktion zum Senden einer E-Mail zu importieren. Oben in der Datei fügen die Benutzeransichten (mit anderen Importen) hinzu

nano users/mfa.py
Jetzt müssen wir diese Funktion schreiben, bevor das alles funktioniert. Es sollte unsere Funktion zum Senden von E-Mails erweitern und einfach eine E-Mail mit dem Bestätigungscode an den Benutzer senden.
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 funktioniert also alles hervorragend, jetzt haben wir ein Multi-Faktor-Authentifizierungssystem, das für die Anmeldung eine Telefonnummer oder E-Mail-Adresse benötigt. Wir brauchen aber auch eine Möglichkeit, Benutzer zu entfernen oder zumindest auszublenden, die nicht mit unseren Bedingungen kooperieren. Das können Spammer, Roboter oder jeder sein, der es nicht gut mit unserer Arbeit meint. Schauen Sie sich eine Ansicht an, die ich zur Überwachung von Benutzern auf meiner Website habe:
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor #

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # Importe
    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', { # Wir müssen diesen Test erstellen
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
Liste der Benutzer abrufen

Geben Sie Benutzer in einer Vorlage zurück

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
Beachten Sie, dass dieser Code einen Test verwendet. Wir müssen diesen Test in einer Datei „tests.py" deklarieren und importieren. Nachdem wir „users/tests.py" bearbeitet haben, erstellen wir den Test.

 {% 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 %}
 
Dies geschieht in Verbindung mit der Vorlage „users/users.html", die etwa so aussieht:

Beachten Sie, dass die Vorlage eine weitere Vorlage enthält: Benutzer/

user.html. Wenn Sie eine Vorlage verwenden, die über eine Untervorlage verfügt und keine Erweiterungen verwendet, empfiehlt es sich, einen Unterstrich hinzuzufügen (

) vor dem Namen der zu erweiternden Datei, um Vorlagen zu unterscheiden.

 {% 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># Beachten Sie, dass dies eine Menge Jinja ist. Möglicherweise sind nicht alle dieser Variablen definiert. Aber so sieht mein Code aus.
      <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>
 

{{ user.id }}</small>

 <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 benötigen außerdem eine weitere Untervorlage, toggle_active.html. Bei dieser Vorlage sollte es sich um ein Formular handeln, mit dem wir umschalten können, ob ein Benutzer aktiv ist.

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


# Wir müssen außerdem eine Ansicht zum Umschalten der Benutzeraktivität und entsprechende URL-Muster hinzufügen. Wenn wir schon dabei sind, fügen wir eine Ansicht hinzu, um einen Benutzer zu löschen, falls wir das brauchen.
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import DeleteView

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

    def test_func(self): # Importe
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
Die Weiterleitungs-URL bei Erfolg

Testen Sie, ob der Benutzer Superuser ist und die Berechtigung zum Löschen hat

Während dies bei Bedarf praktisch ist, sollte das Löschen eines Benutzers in den meisten Fällen nicht notwendig sein. Wir können die Sichtbarkeit von Benutzern, die die Website besuchen, einfach umschalten, wenn wir sie schließen müssen.

nano users/urls.py
Die von uns hinzugefügten URL-Muster sehen folgendermaßen aus. Bearbeiten Sie mit nano die Datei „users/urls.py" und fügen Sie diese Zeilen hinzu:

# Die Zeilen sollten in der Liste der Pfade in den Benutzeransichten vor dem Ende „]", aber nach dem Anfang „[" stehen.
    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'),
#

sudo backup
Stellen Sie nun sicher, dass Sie die Website sichern, damit Sie sie auf den Webserver herunterladen können, an dem wir weiterarbeiten werden. Von der Befehlszeile aus,

Jetzt ist unsere Website gesichert.

Jetzt haben wir noch ein paar weitere nützliche Funktionen. Aber wie sieht es hier mit dem Gesamtbild aus? Auf diesen Code kann immer noch nicht über das Internet zugegriffen werden, wir haben noch keinen Mailserver und wir müssen unsere App um einen umfassenden Verifizierungsprozess sowie reibungslose Layouts erweitern, die uns beim Erkunden der Website helfen, sowie um sichere Protokolle zur Authentifizierung privilegierter Benutzer.

Wir werden das alles noch besprechen. Das Wichtigste für den Moment wird einfach sein, diesen Code online zu stellen, was wir mit nur ein paar Zeilen Bash auf einem Ubuntu-Server tun können. Dafür müssen Sie jedoch einen Server mieten, es sei denn, Sie haben einen Server zu Hause und ein geschäftliches Internetabonnement, das Ihnen das Öffnen von Ports ermöglicht. Ich persönlich betreibe meine Website auf einem HP Z440, der in meiner Wohnung installiert ist, aber für Grundbedürfnisse ist es normalerweise viel günstiger, einen Virtual Private Server (VPS) zu mieten.

Bedenken Sie, dass der Code, den wir derzeit ausführen, relativ dünn ist. Er muss gewartet und verbessert werden, bevor wir bereit sind, das, was wir haben, zum Erstellen eines Produkts zu verwenden. Seien Sie vorsichtig, was Sie mit dem Internet tun. Stellen Sie sicher, dass Sie einen Plan haben, um unerwünschte Interaktionen mit Ihrer Website zu blockieren, wenn Sie diese Site öffentlich im Web auf einem Linux-Server bereitstellen. Dies wird zunächst wahrscheinlich kein Problem darstellen, aber wir werden verschiedene Lösungen prüfen, um dem entgegenzuwirken, darunter maschinelles Lernen, künstliche Intelligenz und Computer Vision. Wenn es zu einem Problem wird, suchen Sie in diesem Text weiter nach einer Lösung.

Wenn Sie einen VPS mieten möchten, gibt es viele Möglichkeiten. Google Cloud verfügt über VPS-Server, Ionos, Kamatera, Amazon AWS und weitere Anbieter bieten Cloud-Server-Lösungen an, die unseren Anforderungen entsprechen.

Sie müssen sich durch die Formulare klicken und einen Plan auswählen, um loszulegen. Sie können bei jedem Anbieter einen Basisplan abschließen. Stellen Sie jedoch sicher, dass der Anbieter Ihnen erlaubt, Port-Mail-Server-Ports zum Senden von E-Mails zu öffnen (dies sollten Port 587 und Port 25 sein). Einige Anbieter blockieren diese Ports. Bisher habe ich die besten Erfahrungen mit Ionos und Kamatera gemacht, beide ermöglichen mir den unbegrenzten E-Mail-Versand und ihre Preise sind ziemlich günstig.

ssh-keygen
Sie stellen eine Verbindung zu Ihrem neuen Server über ein Protokoll namens SSH oder Secure Shell her, das es Ihnen ermöglicht, von Ihrem PC aus eine Remote-Schnittstelle mit dem Server herzustellen, genau wie mit Ihrem PC. Wenn Sie den Server einrichten, wird der Hosting-Anbieter Sie wahrscheinlich auffordern, einen SSH-Schlüssel hinzuzufügen, oder er wird Ihnen einen Benutzernamen und ein Passwort geben. Mit dem SSH-Schlüssel melden Sie sich über die Befehlszeile beim Server an, um den Code zu bearbeiten. Verwenden Sie die folgenden ssh-keygen-Optionen, um einen SSH-Schlüssel zu generieren.

cat ~/.ssh/id_rsa.pub
Speichern Sie die Datei und überschreiben Sie sie bei Bedarf. Es empfiehlt sich, Ihre SSH-Schlüssel zu wechseln, falls Sie dies noch nicht getan haben. Jetzt können Sie den folgenden Befehl verwenden, um Ihren SSH-Schlüssel anzuzeigen. Sie möchten es auf Ihren Remote-Server kopieren, damit Sie es zur Authentifizierung verwenden können.

ssh-keygen -t rsa -b 4096
Wenn Sie bei der Eingabe dieses Befehls keinen SSH-Schlüssel sehen konnten (eine lange Folge von Ziffern und Buchstaben, die mit „ssh-rsa AAA" beginnen), versuchen Sie, einen RSA-Schlüssel zu generieren (diese sind sicherer, ich empfehle daher, sie zu verwenden). Der folgende Code generiert einen 4096-Bit-RSA-SSH-Schlüssel.

ssh ubuntu@XX.XX.XX.XX
Erstellen Sie einen VPS mit Ubuntu, wie auch immer Sie dies planen. Sobald Sie einen VPS erstellt haben, indem Sie durch die Formulare auf der Website des Anbieters (kamatera.com, ionos.com oder ähnlich) geklickt haben, möchten Sie sich anmelden. Verwenden Sie dazu den Befehl ssh mit Ihrer IP-Adresse (die Adresse, die wie XX.XX.XX.XX aussieht). Sie müssen auch auf den Standardbenutzernamen auf dem von uns erstellten Server achten, z. B. Ubuntu.

Möglicherweise werden Sie nach einem Passwort gefragt. Wenn Sie nach einem Passwort gefragt werden, geben Sie es ein. Wir werden nicht den Standardbenutzernamen verwenden, also beginnen wir damit, einen neuen Benutzer zu erstellen und seinem Konto einen SSH-Schlüssel hinzuzufügen.

nano sshd_config
Beginnen wir mit dem Hinzufügen einer neuen sshd_config-Datei, die dem Server mitteilt, wie SSH zu verwenden ist.
#
#

# Dies ist die systemweite Konfigurationsdatei des SSHD-Servers.  Sehen

# sshd_config(5) für weitere Informationen.
# Dieses 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 standardmäßigen sshd_config verwendet wird, die mitgeliefert wird
# OpenSSH soll Optionen mit ihrem Standardwert angeben, wo

# möglich, aber hinterlassen Sie sie kommentiert.  Unkommentierte Optionen überschreiben die
# Standardwert.
# Hafen 22
# AdresseFamilie beliebig

# 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 Schlüsselung
# RekeyLimit standardmäßig keine
# Protokollierung

# SyslogFacility AUTH

# LogLevel-INFO
# Authentifizierung:
# LoginGraceTime 2m
# PermitRootLogin-Verbotspasswort
# StrictModes ja

PubkeyAuthentication yes

# MaxAuthTries 6
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# MaxSessions 10

# Erwarten Sie, dass .ssh/authorized_keys2 in Zukunft standardmäßig ignoriert wird.
# AuthorizedPrincipalsFile keine

# AuthorizedKeysCommand keine
# AuthorizedKeysCommandUser niemand
# Damit dies funktioniert, benötigen Sie außerdem Hostschlüssel in /etc/ssh/ssh_known_hosts
# Hostbasierte Authentifizierung Nr
# Ändern Sie den Wert auf „Ja", wenn Sie ~/.ssh/known_hosts nicht vertrauen
# Hostbasierte Authentifizierung
# IgnoreUserKnownHosts Nr

# Lesen Sie nicht die Dateien ~/.rhosts und ~/.shosts des Benutzers
PasswordAuthentication no
# IgnoreRhosts ja

# Um getunnelte Klartextkennwörter zu deaktivieren, ändern Sie hier auf „Nein"!
# PermitEmptyPasswords Nr
KbdInteractiveAuthentication no

# Ändern Sie den Wert auf „Ja", um Challenge-Response-Passwörter zu aktivieren (Vorsicht bei Problemen mit
# einige PAM-Module und Threads)
# Kerberos-Optionen
# KerberosAuthentifizierungsnr
# KerberosOrLocalPasswd ja

# KerberosTicketCleanup ja
# KerberosGetAFSToken Nr
# GSSAPI-Optionen
# GSSAPIAuthentifizierungsnr
# GSSAPICleanupCredentials ja

# GSSAPIStrictAcceptorCheck ja
# GSSAPIKeyExchange-Nr
# Setzen Sie dies auf „Ja", um die PAM-Authentifizierung, Kontoverarbeitung usw. zu aktivieren.
# und Sitzungsverarbeitung. Wenn dies aktiviert ist, erfolgt die PAM-Authentifizierung
# durch die KbdInteractiveAuthentication zugelassen werden und
# Passwortauthentifizierung.  Abhängig von Ihrer PAM-Konfiguration,
# Die PAM-Authentifizierung über KbdInteractiveAuthentication kann umgangen werden
# die Einstellung „PermitRootLogin ohne Passwort".
# Wenn Sie nur möchten, dass die PAM-Konto- und Sitzungsprüfungen ohne ausgeführt werden
UsePAM yes

# PAM-Authentifizierung, aktivieren Sie diese dann, legen Sie jedoch PasswordAuthentication fest
# und KbdInteractiveAuthentication auf „Nein".
# AllowAgentForwarding ja
X11Forwarding yes
# AllowTcpForwarding ja
# GatewayPorts-Nr
# X11DisplayOffset 10
PrintMotd no
# X11UseLocalhost ja
# PermitTTY ja
# PrintLastLog ja
# TCPKeepAlive ja
# PermitUserEnvironment-Nr
# Komprimierung verzögert
# ClientAliveInterval 0
# ClientAliveCountMax 3
# BenutzeDNS-Nr
# PidFile /run/sshd.pid
# MaxStartups 10:30:100
# GenehmigungTunnel-Nr

# ChrootDirectory keine
Banner /etc/banner

# VersionAddendum keine
AcceptEnv LANG LC_*

# Kein Standard-Bannerpfad
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Erlauben Sie dem Client, Umgebungsvariablen für das Gebietsschema zu übergeben
# Überschreiben Sie die Standardeinstellung, dass keine Subsysteme vorhanden sind
# Beispiel für das Überschreiben von Einstellungen pro Benutzer
# Übereinstimmung mit Benutzeranoncvs
# X11Weiterleitungsnr
# AllowTcpForwarding Nr
PermitRootLogin no
PermitTTY-Nr

ForceCommand CVS-Server

nano initialize
Denken Sie daran, Strg+X und Y zu drücken, um die Datei zu speichern. Als nächstes schreiben wir ein einfaches Skript namens initialize (alles im Standard-Home-Verzeichnis unseres Benutzers).

Fügen Sie diese Zeilen zur Datei hinzu und ersetzen Sie sie
# mit 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

!/bin/bash

Um Sie durch diese Datei zu führen, beginnen wir Zeile für Zeile. Die erste Zeile teilt dem Compiler mit, dass es sich um ein Bash-Skript handelt. Dann installieren wir Abhängigkeiten, kopieren sshd_config in das richtige Verzeichnis, starten ssh neu, generieren SSH-Schlüssel für root und fügen den Benutzer „team" hinzu (Sie können dafür einen beliebigen Namen auswählen, verwenden Sie den Befehl adduser mit seinem Namen und dem vorerst deaktivierten Passwort). Wir fügen auch team zur Sudo-Gruppe hinzu, generieren ihren SSH-Schlüssel, fügen unseren Schlüssel zu autorisierten und auch ihren Schlüsseln hinzu und drucken ihren Schlüssel aus. Mit diesem neuen Benutzer melden wir uns auf der Website an.

ssh team@XX.XX.XX.XX
Fahren Sie in einem neuen Terminal fort und öffnen Sie den Server erneut.

Diesmal sollten Sie kein Passwort benötigen, da Sie über einen SSH-Schlüssel verfügen. Wir haben außerdem die Anmeldung mit Passwort deaktiviert, um die Website sicherer zu machen.

cat ~/.ssh/id_rsa.pub
Jetzt startet dieser Server völlig leer und enthält keine Informationen. Beginnen wir damit, unser Projekt von Git zu klonen, damit wir es herunterladen und auf dem Remote-Computer ausführen können. Drucken Sie auf dem über SSH verbundenen Remote-Server zunächst Ihren SSH-Schlüssel aus:

git clone git://github.com/you/yourproject.git
Als nächstes fügen Sie diesen Schlüssel in die Git-Einstellungen ein, wie wir es zuvor getan haben, um unser Git-Repository einzurichten. Wir können unser Projekt jetzt direkt auf den Server klonen. Stellen Sie sicher, dass Sie das Projekt zuerst lokal gesichert haben, damit es auf dem Git-Server heruntergeladen werden kann.

ls
Perfekt. Jetzt sind alle Dateien hier. Wir können sie mit ls sehen

cp -r yourproject whatyoucalledit
Beginnen wir nun mit der Einrichtung des Servers. Kopieren Sie zunächst Ihr Projektverzeichnis in einen einfachen, einprägsamen Namen, den wir für das Projekt verwenden werden.

sudo nano /usr/bin/ascript
Wobei „whatyoucallit" der neue Name Ihres Projekts ist. Als Nächstes müssen wir ein grundlegendes Dienstprogramm zum Einrichten des Servers erstellen. Wir werden dieses Dienstprogramm speichern und in Zukunft verwenden. Um dieses Dienstprogramm zu erstellen, erstellen wir eine Benutzerbinärdatei, um zu definieren, wie wir ein Skript bearbeiten. Bearbeiten Sie /usr/bin/ascript mit Bash

# Stellen Sie sicher, dass Sie dort sudo verwenden, damit Sie die Berechtigung zum Bearbeiten der Datei haben. Fügen Sie in der Datei diese Zeilen hinzu:
if [ ! -f /usr/bin/$1 ]; then
    sudo touch /usr/bin/$1
    echo "#
    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
!/bin/bash

!/bin/bash" >> /usr/bin/$1

sudo chmod a+x /usr/bin/ascript
Denken Sie daran, dass dieses Skript ein Argument, den Skriptnamen, als $1 akzeptiert. Zuerst prüft es, ob die Datei existiert, oder erstellt sie auf andere Weise, fügt die erste Zeile hinzu, um zu deklarieren, dass das Skript Bash ist, ändert seine Berechtigungen, bearbeitet es und fügt seinen Namen zu /etc/ascripts hinzu, wodurch wir die Namen der Skripte speichern können, die wir erstellen. Wenn die Datei bereits vorhanden ist, ändern Sie einfach die Berechtigungen und bearbeiten Sie sie. Speichern Sie die Datei und als Nächstes ändern wir ihre Berechtigungen. Solange wir dieses Skript verwenden, müssen wir das nicht noch einmal tun.

# Perfekt. Jetzt erstellen wir ein Skript namens Setup. Um Sie nicht zu überfordern, sehen Sie sich zunächst einmal an, wie mein Setup-Skript aussieht. Wir werden durchgehen, wie dieses Skript in Ihrem Projekt aussehen sollte. Sie benötigen zunächst nicht alles in meinem Skript.
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
#
# !/bin/bash
# sudo chmod a+x scripts/usersetup
# ./scripts/usersetup
DIR="/home/team/femmebabe"
USER="team"
# ssh-keygen
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
# Projektverzeichnis
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Befehle protokollieren
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
# Nano-Konfiguration
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
# Git-Konfiguration
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Aktualisieren und installieren
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Aktivieren Sie ClamAV Antivirus
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;"
# Hostnamen festlegen
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
# Postgres einrichten
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Datenbanksicherung einrichten
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
# Deaktivieren Sie iptables
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
# Installieren Sie BitDefender
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
# Postfix einrichten
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# Erstellen Sie Verzeichnisse
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
# Virtuelle Umgebung einrichten
cd $DIR
# Abhängigkeiten abrufen und erstellen
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 # Legen Sie Firewall-Regeln fest
pip3 install --upgrade opencv-contrib-python # Installieren Sie Pypi-Abhängigkeiten
# ==4.5.4.60
# ==4.5.4.60
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
# pip install opencv-python==4.5.5.64
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
# pip install opencv-contrib-python==4.5.5.64
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# Installieren Sie Certbot
sudo systemctl restart opendkim postfix dovecot
# Führen Sie certbot aus
# Mailserver neu laden
# Zertifikate kopieren
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privkey.pem
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"
# sudo cp /etc/letsencrypt/live/femmebabe.com/cert.pem cert.pem
sudo gpasswd -a www-data users
# Patch venv
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# Benutzereinstellungen festlegen
# Berechtigungen festlegen
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 team:users /var/run/
# sudo chown root:root /run/sudo/ts -R
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
# sudo chmod 664 db.sqlite3
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
# sudo chown www-data:users db.sqlite3
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"
# Konfiguration kopieren und Berechtigungen festlegen
# Datenbank einrichten
# PAM-Konfiguration einfügen und fehlerhafte SSH-Konfiguration entfernen
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
# sudo sed -i '' -e '$ d' /etc/pam.d/sshd
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
# sudo sed -i '' -e '$ d' /etc/profile
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
# Bin-Skripte kopieren und Berechtigungen festlegen
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
# Dienste neu laden und aktivieren
# Aktivieren Sie Apache-Module
# sudo a2dismod mpm_event
# sudo a2dismod mpm_worker
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# sudo a2enmod mpm_prefork
sudo a2ensite femmebabe-le-ssl
# Standard-Site deaktivieren
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# Aktivieren Sie unsere Website
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# Laden Sie den Daemon neu und starten Sie Apache, Postfix und OpenDkim neu
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
# Berechtigungen festlegen
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
# Konfiguration tauschen
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
# Untertitel-Engine initialisieren
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}'
# Git einrichten
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."
IPv6 und opendkim für die Domänenkonfiguration anzeigen

Einrichtung abgeschlossen

Das ist eine Menge Setup! Kurz gesagt, dieser Code protokolliert Befehle, konfiguriert Nano und Git, kopiert Dateien, lädt Ubuntu-APT-Pakete herunter und installiert sie, Python-Abhängigkeiten, konfiguriert Postfix, konfiguriert Postgresql (den Datenbankserver) und lädt die Datenbank, konfiguriert UFW (eine unkomplizierte Firewall), deaktiviert iptables, lädt ein Antivirenprogramm herunter, erstellt Verzeichnisse, klont Abhängigkeiten, installiert Zertifikate und richtet den Server ein, installiert die Konfiguration, startet und aktiviert die server, weist Swap zu, legt Berechtigungen fest und gibt die IP, die IPV6-Adresse und den OpenDKIM-Schlüssel aus. Ziemlich einfach, aber es sieht nach viel Code aus. Wir werden nicht viel davon brauchen, weil wir nicht über die Abhängigkeiten verfügen, wir verwenden weder Celery, Celerybeat noch Daphne, aber wir werden trotzdem einige davon installieren, um loszulegen. Beachten Sie, dass für diesen Code eine Domäne mehrmals deklariert wurde.

Wir müssen außerdem einen Domainnamen erwerben (wofür eine geringe jährliche Gebühr anfällt). Ich empfehle Squarespace für den Kauf einer Domain, das Layout ist intuitiv und einfach zu bedienen. Sie können jede Domain Ihrer Wahl kaufen, in diesem Beispiel verwende ich jedoch die Domain femmebabe.com. Sobald Sie eine Domain gekauft haben, gehen Sie zum Squarespace-DNS-Konfigurationsfenster und fügen Sie einen A-Eintrag hinzu, der Ihre Domain über die IP-Adresse auf den Server verweist. Es sollte so aussehen:

@ A XX.XX.XX.XX

Mit dem @-Operator als Host bedeutet das, dass alle Subdomänen unter dieser Domäne und der Stammdomäne alle zum Server umgeleitet werden. Es müssen noch weitere Datensätze deklariert werden, aber wir können mit diesen fortfahren, sobald wir zum Versenden von E-Mails bereit sind. Bedenken Sie, dass es mehrere Tage dauern kann, bis Sie erfolgreich E-Mails vom Server versenden können. Es wird einige Zeit dauern, bis sich die von uns eingerichteten DNS-Einträge verbreiten.

Wie auch immer, der einzige Datensatz, den wir zum Starten benötigen, ist ein A-Datensatz. Jetzt können wir das folgende Skript entsprechend unserem Projekt ausfüllen und ausführen.

Beginnen wir mit einem kleineren Setup-Skript, um nur das zu installieren, was wir für einen grundlegenden Fortschritt benötigen. Wir werden noch nicht so viele Abhängigkeiten oder Postgresql verwenden, sondern einfach einen einfachen HTTP-Server starten und uns um die Zertifizierung kümmern, wenn das erledigt ist. Denken Sie daran: Um ein HTTPS-Zertifikat zu erhalten und den Server sicher zu betreiben, müssen wir eine Domain kaufen und einen Server mieten. Ersetzen Sie zunächst „team" in dieser Datei durch den Namen Ihres Benutzers, „DIR" durch das Verzeichnis Ihres Projekts und geben Sie Ihre E-Mail-Adresse und Domäne in den < >-Tags an.

Bevor wir diesen Code ausführen, müssen wir außerdem die Einstellungen der Firewall ändern, die der Hosting-Anbieter (sofern vorhanden) unterstützt. Normalerweise befindet sich dies auf der Registerkarte „Netzwerke" Ihres Hosting-Anbieters oder, wenn Sie selbst hosten, im Abschnitt „Portweiterleitung" Ihres Routers. Wenn Sie Self-Hosting nutzen, sollten Sie über Ihren Router auch eine statische IP mit der Adresse Ihres Serverrechners einrichten. Sie müssen die folgenden Ports für Lese-/Schreibzugriff öffnen.

# 22 (ssh)
25 (Post)
587 (Mail)
110 (Mail-Client)
80 (http)
443 (https)
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
#
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
# !/bin/bash
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Befehle protokollieren
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
# Nano-Konfiguration
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
# Git-Konfiguration
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Aktualisieren und installieren
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
# Aktivieren Sie ClamAV Antivirus
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
# Hostnamen festlegen
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Datenbanksicherung einrichten
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
# Deaktivieren Sie iptables
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
# Virtuelle Umgebung einrichten
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# Installieren Sie Certbot
sudo gpasswd -a www-data users
# Führen Sie certbot aus
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# Benutzereinstellungen festlegen
# Berechtigungen festlegen
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 ./
# sudo chown -R team:users /var/run/
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# sudo chown root:root /run/sudo/ts -R
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
# Dienste neu laden und aktivieren
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# Aktivieren Sie Apache-Module
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
Laden Sie den Daemon neu und starten Sie Apache, Postfix und OpenDkim neu

IPv6 und opendkim für die Domänenkonfiguration anzeigen

ping femmebabe.com # Bevor Sie diesen Code ausführen, stellen Sie sicher, dass die von Ihnen erworbene Domain mit dem Server verbunden ist. Öffnen Sie dazu ein Terminal auf Ihrem lokalen Computer und führen Sie diesen Befehl mit Ihrer Domäne aus:

Geben Sie hier nach dem Ping Ihre Domain 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 die gesamte Einrichtung, die zum Konfigurieren von Postfix erforderlich ist. Wir werden uns diese Einrichtung später genauer ansehen. Führen Sie zunächst diesen Setup-Code aus. Die Installation und Zertifizierung Ihres Servers sollte einige Minuten dauern. Stellen Sie erneut sicher, dass Sie im Skript Namen, E-Mail-Adresse und Domänennamen entsprechend dem von Ihnen erworbenen Namen ersetzen.

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
Nachdem der Server nun bereitgestellt ist, können Sie in einem beliebigen Webbrowser auf die URL zugreifen und prüfen, ob auf dem Server HTTPS ausgeführt wird. Ist dies nicht der Fall, warten Sie eine Weile, bis die DNS-Einträge aufgeholt haben, und führen Sie dann den folgenden Befehl aus, um die Certbot-Zertifizierung erneut zu versuchen:

nano yourproject/settings.py
Solange Sie alles richtig konfiguriert haben, sollten Sie auf die Standardseite von Apache zugreifen können, um zu wissen, dass Ihr Code funktioniert und eine Live-Webseite anzeigt. Als nächstes bearbeiten wir die Datei „settings.py", um unseren Standard-Debugmodus auf „Produktion" zu ändern. Wir konfigurieren auch die Domäne in den Einstellungen sowie interne IPs.

DEBUG = False

# In den Einstellungen können Sie diese Zeilen ändern/hinzufügen.
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',
]

Site-Konfiguration

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
Jetzt müssen wir Apache2 konfigurieren. Bearbeiten wir die Konfigurationsdatei, die wir bereitstellen möchten, mit dieser Zeile:

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>
Diese Konfigurationsdatei sollte unseren Domänennamen sowie den Namen des Benutzers und des Projekts enthalten. Ich verwende den Domainnamen femmebabe.com, den Benutzernamen team und den Projektnamen femmebabe.

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
Stellen Sie sicher, dass Sie bei der Konfiguration Ihres Servers den Namen des Projekts, der Verzeichnisse und der Domäne in diesem Beispielcode ersetzen. Jetzt müssen wir die Standardseite deaktivieren. Dies kann mit Bash erfolgen.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Als nächstes können wir die Standard-Site aktivieren und Apache2 neu laden, ebenfalls mit Bash. Denken Sie daran, „femmebabe" durch den Namen der Datei zu ersetzen, die Sie beim Bearbeiten in /etc/apache2/sites-available/ deklariert haben.

cd projectname
source venv/bin/activate
python manage.py check
Gehen Sie in der Navigationsleiste zurück zu Ihrer Domain. Sie sollten die von Ihnen konfigurierte Website in Ihrem Webbrowser sehen. Glückwunsch! Wenn Sie es nicht sehen, müssen Sie möglicherweise einige Änderungen vornehmen. Überprüfen Sie die Einstellungen in Ihrem Projekt und die Apache-Konfiguration sorgfältig und stellen Sie sicher, dass keine Fehler vorliegen. Führen Sie dann die folgenden Befehle aus, um das Projekt auf Fehler zu überprüfen.

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Wenn in Ihrem Python-Projekt Fehler auftreten, verfolgen Sie diese und beheben Sie sie. Je nachdem, wo sie sich befinden, können Sie möglicherweise nicht alle Fehler sehen. Wenn Sie also einen Fehler erhalten, der lediglich besagt, dass „Auffüllen ist nicht wiedereintrittsfähig" ist, bearbeiten Sie die folgende Datei in der virtuellen Umgebung, „registry.py", um den Fehler aufzudecken.

            if self.loading:
                # Scrollen Sie zu Zeile 83, wo dieser Laufzeitfehler ausgelöst wird (raise RuntimeError("populate() isn't reentrant"), fügen Sie vor dieser Zeile einen Kommentar hinzu und fügen Sie dann mit derselben Einrückung self.app_configs = {} hinzu. Das sieht so aus:
                #
# Wiedereintrittsaufrufe verhindern, um die Ausführung von AppConfig.ready() zu vermeiden
                self.app_configs = {}
            self.loading = True
Methoden zweimal.

raise RuntimeError("populate() ist nicht reentrant")

python manage.py check
Anschließend können Sie das Projekt erneut überprüfen und den Fehler aufdecken.

            if self.loading:
                # Dann können Sie den Fehler sehen und beheben. Wenn Sie das Problem behoben haben und der Code fehlerfrei kompiliert wird, stellen Sie sicher, dass Sie die Datei wieder so ändern, dass sie wie folgt aussieht:
                #
                raise RuntimeError("populate() isn't reentrant")
# Wiedereintrittsaufrufe verhindern, um die Ausführung von AppConfig.ready() zu vermeiden
            self.loading = True
Methoden zweimal.

self.app_configs = {}

sudo systemctl reload apache2
Sofern der Server online ist und wir weitere Änderungen daran vornehmen, müssen wir den folgenden Befehl verwenden, um den Server neu zu laden:

Eindrucksvoll! Aber wie sieht es mit dem Versenden von E-Mails aus? Um mit dem Versenden von E-Mails beginnen zu können, müssen wir zunächst die Domänenkonfiguration aktualisieren. Dies sollte sich in Ihrem DNS-Bereich in SquareSpace oder bei dem von Ihnen gewählten Domainnamen-Registrar befinden. Wir müssen außerdem die Konfiguration installieren und hinzufügen sowie einige Befehle ausführen.

Lassen Sie uns zunächst die IPV6-Adresse des Servers ermitteln. Anschließend öffnen wir Ihr DNS und fügen die Einträge hinzu.

ip -6 addr
Um die IPV6-Adresse des Servers zu erhalten, verwenden Sie diesen Befehl:

Jetzt können wir die folgenden Einträge zu den DNS-Einstellungen hinzufügen. Meine Unterlagen sehen so aus. Für Ihre Unterlagen sollten Sie jedoch die IP-Adresse durch Ihre IP ersetzen (nicht 75.147.182.214, das ist meine). Fügen Sie außerdem Ihre Domain anstelle von femmebabe.com sowie Ihre IPV6-Adresse hinzu, die Sie mit dem vorherigen Befehl gefunden haben (meine, fe80::725a:fff:fe49:3e02, können Sie nicht verwenden). Machen Sie sich vorerst keine Sorgen um den Domänenschlüssel, dieser wird erstellt, wenn wir Postfix, den Mailserver, mit OpenDKIM einrichten und den Schlüssel ausdrucken. 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/A

nano config/etc_postfix_main.cf
Jetzt müssen wir eine dauerhafte Konfiguration für Postfix hinzufügen. Wir müssen lediglich sicherstellen, dass wir den Domainnamen „femmebabe.com" durch den von Ihnen verwendeten Domainnamen ersetzen. Schauen wir uns alle Konfigurationsdateien einzeln an und installieren sie in einem Verzeichnis namens config in unserem Projekt, um sie auf dem Betriebssystem zu installieren.

# Fügen Sie diesen Text zur Datei hinzu


#
# Eine kommentierte, vollständigere Version finden Sie unter /usr/share/postfix/main.cf.dist
# Debian-spezifisch: Die Angabe eines Dateinamens führt zum ersten
# Zeile dieser Datei, die als Name verwendet werden soll.  Der Debian-Standard

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

# ist /etc/mailname.
append_dot_mydomain = no

# myorigin = /etc/mailname
# Das Anhängen von .domain ist die Aufgabe des MUA.

readme_directory = no

# Kommentieren Sie die nächste Zeile aus, um Warnungen zu „verzögerter E-Mail" zu generieren
# delay_warning_time = 4h
compatibility_level = 3.6



# Siehe http://www.postfix.org/COMPATIBILITY_README.html – standardmäßig auf 3.6 eingestellt
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

# Neuinstallationen.
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
TLS-Parameter

Milter-Konfiguration

nano config/etc_postfix_master.cf
Nächste Konfiguration!

# Fügen Sie diese Zeilen hinzu:
#
#
# Konfigurationsdatei für den Postfix-Masterprozess.  Einzelheiten zum Format
# Informationen zur Datei finden Sie in der Handbuchseite zu master(5) (Befehl: „man 5 master" oder
# online: http://www.postfix.org/master.5.html).
#
# Vergessen Sie nicht, nach der Bearbeitung dieser Datei „Postfix Reload" auszuführen.
#
# ======================================================================
# Diensttyp privat unpriv chroot wakeup maxproc Befehl + Argumente
smtp      inet  n       -       y       -       -       smtpd
# (ja) (ja) (nein) (nie) (100)
# ======================================================================
# SMTP Inet n - y - 1 Postscreen
# smtpd pass - - y - - smtpd
# dnsblog unix - - y - 0 dnsblog
# tlsproxy unix - - y - 0 tlsproxy
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
# Wählen Sie eine Option: Aktivieren Sie die Übermittlung nur für Loopback-Clients oder für jeden Client.
# 127.0.0.1:submission inet n - y - - smtpd
# -o syslog_name=postfix/submission
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_tls_auth_only=yes
# -o smtpd_reject_unlisted_recipient=nein
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
# Wählen Sie eine Option: Aktivieren Sie SMTPs nur für Loopback-Clients oder für jeden Client.
# 127.0.0.1:smtps inet n - y - - smtpd
# smtps inet n - y - - smtpd
# -o syslog_name=postfix/smtps
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_reject_unlisted_recipient=nein
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
# -o milter_macro_daemon_name=ORIGINATING
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
# 628 inet n - y - - qmqpd
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
# qmgr Unix n - n 300 1 oqmgr
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
#
# ================================================================
# Schnittstellen zu Nicht-Postfix-Software. Schauen Sie sich unbedingt das Handbuch an
# Durchsuchen Sie die Seiten der Nicht-Postfix-Software, um herauszufinden, welche Optionen sie benötigt.
#
# Viele der folgenden Dienste nutzen die Postfix-Pipe(8)-Zustellung
# Agent.  Weitere Informationen zu ${recipient} finden Sie in der Manpage zu pipe(8).
# und andere Nachrichtenumschlagoptionen.
# ================================================================
#
# Maildrop. Weitere Informationen finden Sie in der Postfix-Datei MAILDROP_README.
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# Geben Sie außerdem in main.cf an: maildrop_destination_recipient_limit=1
#
#
# ================================================================
#
# Aktuelle Cyrus-Versionen können den vorhandenen „lmtp"-master.cf-Eintrag verwenden.
#
# Geben Sie in cyrus.conf an:
# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
#
# Geben Sie in main.cf eine oder mehrere der folgenden Angaben an:
# mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
#
# ================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Geben Sie außerdem in main.cf Folgendes an: cyrus_destination_recipient_limit=1
#
# Cyrus Unix - n n - - Pipe
# flags=DRX user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
#
# ================================================================
# Altes Beispiel einer Zustellung über Cyrus.
#
# old-cyrus unix - n n - - Pipe
# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
#
# ================================================================
#
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# Konfigurationsdetails finden Sie in der Postfix-Datei UUCP_README.
#
#
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}
Andere externe Liefermethoden.

nano config/etc_default_opendkim
Und die opendkim-Konfiguration. OpenDKIM identifiziert E-Mail-Server mit Domänenschlüsseln, um sie sicherer zu machen. Ohne sie werden E-Mails nicht signiert und gelangen möglicherweise nicht in den Posteingang.

# Fügen Sie diese Zeilen hinzu:
#
# HINWEIS: Dies ist eine ältere Konfigurationsdatei. Es wird von opendkim nicht verwendet
# systemd-Dienst. Bitte verwenden Sie die entsprechenden Konfigurationsparameter in
# /etc/opendkim.conf stattdessen.
#
# Bisher hat man hier die Standardeinstellungen bearbeitet und dann ausgeführt
# /lib/opendkim/opendkim.service.generate, um Systemd-Override-Dateien unter zu generieren
# /etc/systemd/system/opendkim.service.d/override.conf und
# /etc/tmpfiles.d/opendkim.conf. Das ist zwar immer noch möglich, aber jetzt schon
# Es wird empfohlen, die Einstellungen direkt in /etc/opendkim.conf anzupassen.
#
# DAEMON_OPTS=""
# Wechseln Sie zu /var/spool/postfix/run/opendkim, um einen Unix-Socket mit zu verwenden
RUNDIR=/run/opendkim
# Postfix in einer Chroot:
# RUNDIR=/var/spool/postfix/run/opendkim
#
# Entfernen Sie das Kommentarzeichen, um einen alternativen Socket anzugeben
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Beachten Sie, dass durch diese Einstellung alle Socket-Werte in opendkim.conf überschrieben werden
# Standard:
# Hören Sie alle Schnittstellen an Port 54321:
# SOCKET=inet:54321
# Hören Sie auf Loopback auf Port 12345:
# SOCKET=inet:12345@localhost
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Hören Sie 192.0.2.1 auf Port 12345:
nano config/etc_dovecot_conf.d_10-master.conf
SOCKET=inet:12345@192.0.2.1

0-master.conf 
# Fügen Sie diese Zeilen hinzu:
#

# default_process_limit = 100
# default_client_limit = 1000
# Standard-VSZ-Grenze (virtuelle Speichergröße) für Dienstprozesse. Das ist hauptsächlich
# soll Prozesse, die Speicher verlieren, abfangen und beenden, bevor sie sich verbrauchen

# alles.
# default_vsz_limit = 256M
# Der Anmeldebenutzer wird intern von Anmeldeprozessen verwendet. Dies ist das am wenigsten vertrauenswürdige

# Benutzer im Dovecot-System. Es sollte überhaupt keinen Zugriff auf irgendetwas haben.
# default_login_user = dovenull
# Interner Benutzer wird von nichtprivilegierten Prozessen verwendet. Es sollte getrennt sein von

service imap-login {
  inet_listener imap {
    # Login-Benutzer, damit Login-Prozesse andere Prozesse nicht stören können.
  }
  inet_listener imaps {
    # default_internal_user = Taubenschlag
    # Port = 143
  }

  # Port = 993
  # ssl = ja
  # Anzahl der zu verarbeitenden Verbindungen, bevor ein neuer Prozess gestartet wird. 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, die immer auf weitere Verbindungen warten.
  # Process_min_avail = 0
}

service pop3-login {
  inet_listener pop3 {
    # Wenn Sie service_count=0 festlegen, müssen Sie dies wahrscheinlich erweitern.
  }
  inet_listener pop3s {
    # vsz_limit = $default_vsz_limit
    # Port = 110
  }
}

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

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

  # ssl = ja
  # Port = 587
    # Erstellen Sie einen Inet-Listener nur, wenn Sie den oben genannten UNIX-Socket nicht verwenden können
    # inet_listener lmtp {
    # Vermeiden Sie es, LMTP für das gesamte Internet sichtbar zu machen
  # Adresse =
}

service imap {
  # Port =
  # }
  # Der größte Teil des Speichers geht an mmap()ing-Dateien. Möglicherweise müssen Sie diesen Wert erhöhen

  # Begrenzen Sie, wenn Sie große Postfächer haben.
  # vsz_limit = $default_vsz_limit
}

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

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

service auth {
  # Max. Anzahl der SMTP-Übermittlungsprozesse (Verbindungen)
  # Prozesslimit = 1024
  # auth_socket_path zeigt standardmäßig auf diesen Userdb-Socket. Das ist typisch
  # Wird von dovecot-lda, doveadm, möglicherweise imap-Prozess usw. verwendet. Benutzer, die dies getan haben
  # Vollständige Berechtigungen für diesen Socket können eine Liste aller Benutzernamen abrufen und
  # Holen Sie sich die Ergebnisse aller Benutzerdatenbank-Suchen.
  #
  # Der Standardmodus 0666 ermöglicht es jedem, eine Verbindung zum Socket herzustellen, aber der
  # Benutzerdatenbank-Suchen sind nur dann erfolgreich, wenn die Benutzerdatenbank ein „uid"-Feld zurückgibt
  # entspricht der UID des aufrufenden Prozesses. Auch wenn die UID oder GID des Anrufers mit der übereinstimmt
  # Wenn Sie die UID oder GID des Sockets angeben, ist die Suche erfolgreich. Alles andere führt zu einem Fehler.
  #
  # Um dem Anrufer die volle Berechtigung zum Nachschlagen aller Benutzer zu erteilen, stellen Sie den Modus auf ein
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # etwas anderes als 0666 und Dovecot lässt den Kernel das erzwingen
  # Berechtigungen (z. B. 0777 gewährt jedem die vollständigen Berechtigungen).
  # Der Auth-Worker-Prozess wird standardmäßig als Root ausgeführt, sodass er darauf zugreifen kann
  # /etc/shadow. Wenn dies nicht erforderlich ist, sollte der Benutzer geändert werden
}

service dict {
  # $default_internal_user.
  # Benutzer = Root
  unix_listener dict {
    # Wenn ein Dict-Proxy verwendet wird, sollten E-Mail-Prozesse Zugriff auf seinen Socket haben.
    # Beispiel: mode=0660, group=vmail und global mail_access_groups=vmail
    # Modus = 0600
  }
}
Benutzer =

Gruppe =

nano config/etc_dovecot_dovecot
Stellen Sie noch einmal sicher, dass Sie in allen diesen Dateien die Domäne „femmebabe.com" durch die von Ihnen ausgewählte Domäne ersetzen. Bearbeiten Sie die nächste Datei, dovecot's config,

## Und fügen Sie diese Zeilen hinzu

#

# Dovecot-Konfigurationsdatei
# Wenn Sie es eilig haben, schauen Sie sich http://wiki2.dovecot.org/QuickConfiguration an

# '# Der Befehl „doveconf -n" gibt eine saubere Ausgabe der geänderten Einstellungen aus. Benutze es
# Anstatt Dateien beim Posten auf der Dovecot-Mailingliste zu kopieren und einzufügen.
# value inside quotes, eg.: key = "# '-Zeichen und alles, was danach folgt, wird als Kommentar behandelt. Zusätzliche Leerzeichen

# und Tabulatoren werden ignoriert. Wenn Sie eines davon explizit verwenden möchten, geben Sie Folgendes ein
# Zeichen und nachfolgendes Leerzeichen "
# Die meisten (aber nicht alle) Einstellungen können durch verschiedene Protokolle und/oder überschrieben werden

# Quell-/Ziel-IPs, indem Sie die Einstellungen in Abschnitte platzieren, zum Beispiel:
# Protokoll imap { }, lokal 127.0.0.1 { }, remote 10.0.0.0/8 { }
# Für jede Einstellung werden Standardwerte angezeigt, es ist nicht erforderlich, den Kommentar zu entfernen
# diese. Dies sind jedoch Ausnahmen: Keine Abschnitte (z. B. Namespace {})
# oder Plugin-Einstellungen werden standardmäßig hinzugefügt, sie werden nur als Beispiele aufgeführt.
# Pfade sind ebenfalls nur Beispiele, wobei die tatsächlichen Standardwerte auf der Konfiguration basieren

# Optionen. Die hier aufgeführten Pfade gelten für configure --prefix=/usr
!include_try /usr/share/dovecot/protocols.d/*.protocol

# --sysconfdir=/etc --localstatedir=/var
# Aktivieren Sie installierte Protokolle
# Eine durch Kommas getrennte Liste von IPs oder Hosts, bei denen auf Verbindungen gewartet werden soll.
# „*" lauscht auf allen IPv4-Schnittstellen, „::" lauscht auf allen IPv6-Schnittstellen.
# Wenn Sie nicht standardmäßige Ports oder komplexere Ports angeben möchten,

# Bearbeiten Sie conf.d/master.conf.
# listen = *, ::

# Basisverzeichnis, in dem Laufzeitdaten gespeichert werden.
# base_dir = /var/run/dovecot/
# Name dieser Instanz. Im Multi-Instanz-Setup doveadm und andere Befehle
# kann -i <Instanzname> verwenden, um auszuwählen, welche Instanz verwendet wird (eine Alternative).
# zu -c <config_path>). Der Instanzname wird auch zu Dovecot-Prozessen hinzugefügt

# in ps-Ausgabe.
# Instanzname = Taubenschlag

# Begrüßungsnachricht für Kunden.
# login_greeting = Taubenschlag bereit.
# Durch Leerzeichen getrennte Liste vertrauenswürdiger Netzwerkbereiche. Verbindungen daraus
# IPs dürfen ihre IP-Adressen und Ports überschreiben (zur Protokollierung und
# zur Authentifizierungsprüfung). disable_plaintext_auth wird ebenfalls ignoriert

# diese Netzwerke. Normalerweise geben Sie hier Ihre IMAP-Proxyserver an.
# login_trusted_networks =

# Durch Leerzeichen getrennte Liste von Login-Zugriffsprüfungs-Sockets (z. B. tcpwrap)
# login_access_sockets =
# Mit „proxy_maybe=yes", wenn das Proxy-Ziel mit einer dieser IPs übereinstimmt, tun Sie dies nicht
# Proxy. Dies ist normalerweise nicht notwendig, kann aber beim Ziel nützlich sein

# IP ist z.B. Die IP eines Load Balancers.
# auth_proxy_self =
# Ausführlichere Prozesstitel anzeigen (in ps). Zeigt derzeit Benutzernamen und an
# IP-Adresse. Nützlich, um zu sehen, wer die IMAP-Prozesse tatsächlich nutzt

# (z. B. freigegebene Postfächer oder wenn dieselbe UID für mehrere Konten verwendet wird).
# verbose_proctitle = nein
# Sollten alle Prozesse beendet werden, wenn der Dovecot-Masterprozess heruntergefahren wird?
# Wenn Sie dies auf „Nein" setzen, bedeutet dies, dass Dovecot ohne aktualisiert werden kann
# das Schließen vorhandener Client-Verbindungen wird erzwungen (obwohl dies auch der Fall sein könnte).

# ein Problem, wenn das Upgrade z.B. aufgrund eines Sicherheitsupdates).
# Shutdown_Clients = Ja
# Wenn nicht Null, führen Sie E-Mail-Befehle über diese vielen Verbindungen zum Doveadm-Server aus.
# anstatt sie direkt im selben Prozess auszuführen.
# doveadm_worker_count = 0

# UNIX-Socket oder Host:Port, der für die Verbindung zum doveadm-Server verwendet wird
# doveadm_socket_path = doveadm-server
# Durch Leerzeichen getrennte Liste von Umgebungsvariablen, die auf Dovecot beibehalten werden
# gestartet und an alle seine untergeordneten Prozesse weitergegeben. Sie können auch geben

## Schlüssel=Wert-Paare, um immer bestimmte Einstellungen festzulegen.
## import_environment = TZ
##

# Einstellungen des Wörterbuchservers
#
# Das Wörterbuch kann zum Speichern von Schlüssel=Wert-Listen verwendet werden. Dies wird von mehreren genutzt
# Plugins. Auf das Wörterbuch kann entweder direkt oder über a zugegriffen werden
# Wörterbuchserver. Der folgende Diktblock ordnet Wörterbuchnamen URIs zu

dict {
  # wenn der Server verwendet wird. Diese können dann mithilfe von URIs im Format referenziert werden
}

# „proxy::<name>".
# quote = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
# Der größte Teil der tatsächlichen Konfiguration ist unten aufgeführt. Die Dateinamen sind
!include conf.d/*.conf

# zuerst nach ihrem ASCII-Wert sortiert und in dieser Reihenfolge analysiert. Die 00-Präfixe
# in Dateinamen sollen das Verständnis der Reihenfolge erleichtern.
!include_try local.conf

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

protocols = imap pop3

# Es kann auch versucht werden, eine Konfigurationsdatei einzubinden, ohne dass eine Fehlermeldung ausgegeben wird

listen = *, ::
es wurde nicht gefunden:

Ermöglicht Dovecot, alle Eingabeverbindungen abzuhören (ipv4 / ipv6)

nano config/etc_dovecot_passwd
Fügen Sie ein Passwort für den Dovecot-Benutzer hinzu:

team:{plain}yourpassword
Der erste Teil der Datei vor dem Doppelpunkt ist der Benutzername. Der letzte Teil, „Ihr Passwort", bezeichnet das Passwort, das Sie Ihrem Mailserver geben möchten.

nano config/etc_opendkim.conf
Als nächstes die OpenDKIM-Konfiguration

# Und fügen Sie diese Zeilen hinzu:
#
# Dies ist eine Grundkonfiguration zum Signieren und Verifizieren. Das kann leicht sein
# angepasst an eine Grundinstallation. Siehe opendkim.conf(5) und

Syslog			yes
SyslogSuccess		yes
# /usr/share/doc/opendkim/examples/opendkim.conf.sample zur Vervollständigung

# Dokumentation der verfügbaren Konfigurationsparameter.
# LogWarum nein
# Allgemeine Signatur- und Verifizierungsparameter. In Debian lautet der „From"-Header
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# übersigniert, da es sich häufig um den Identitätsschlüssel handelt, der von Reputationssystemen verwendet wird
# und daher etwas sicherheitsempfindlich.
# Signierende Domäne, Selektor und Schlüssel (erforderlich). Führen Sie beispielsweise eine Signierung durch
# für Domain „example.com" mit Selektor „2020" (2020._domainkey.example.com),
# Verwenden des in /etc/dkimkeys/example.private gespeicherten privaten Schlüssels. Detaillierter
# Setup-Optionen finden Sie in /usr/share/doc/opendkim/README.opendkim.
# Domain example.com

# Selektor 2020
# Schlüsseldatei /etc/dkimkeys/example.private
# In Debian läuft opendkim als Benutzer „opendkim". Eine umask von 007 ist erforderlich, wenn
# Verwenden eines lokalen Sockets mit MTAs, die als nicht privilegierter Benutzer auf den Socket zugreifen
UserID			opendkim
UMask			007

# Benutzer (zum Beispiel Postfix). Möglicherweise müssen Sie den Benutzer „postfix" zur Gruppe hinzufügen
# „opendkim" in diesem Fall.
# Socket für die MTA-Verbindung (erforderlich). Wenn sich der MTA in einem Chroot-Gefängnis befindet,
# Es muss sichergestellt sein, dass die Steckdose zugänglich ist. In Debian läuft Postfix ein
# eine Chroot in /var/spool/postfix, daher müsste ein Unix-Socket vorhanden sein
# wie in der letzten Zeile unten gezeigt konfiguriert.
# Socket lokal:/run/opendkim/opendkim.sock
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Socket inet:8891@localhost
# Sockel inet:8891
# Hosts, die signiert und nicht überprüft werden sollen. Der Standardwert ist 127.0.0.1. Siehe die

# Weitere Informationen finden Sie im Abschnitt OPERATION von opendkim(8).
# InternalHosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12
TrustAnchorFile		/usr/share/dns/root.key
# Der Vertrauensanker aktiviert DNSSEC. In Debian wird die Trust-Ankerdatei bereitgestellt

# durch das Paket dns-root-data.
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Nameserver 127.0.0.1
InternalHosts       /etc/opendkim/trusted.hosts
Ordnen Sie Domänen in Von-Adressen Schlüsseln zu, die zum Signieren von Nachrichten verwendet werden
nano config/etc_default_opendkim
Eine Reihe interner Hosts, deren E-Mails signiert werden sollen

# Und fügen Sie diese Zeilen hinzu
#
# HINWEIS: Dies ist eine ältere Konfigurationsdatei. Es wird von opendkim nicht verwendet
# systemd-Dienst. Bitte verwenden Sie die entsprechenden Konfigurationsparameter in
# /etc/opendkim.conf stattdessen.
#
# Bisher hat man hier die Standardeinstellungen bearbeitet und dann ausgeführt
# /lib/opendkim/opendkim.service.generate, um Systemd-Override-Dateien unter zu generieren
# /etc/systemd/system/opendkim.service.d/override.conf und
# /etc/tmpfiles.d/opendkim.conf. Das ist zwar immer noch möglich, aber jetzt schon
# Es wird empfohlen, die Einstellungen direkt in /etc/opendkim.conf anzupassen.
#
# DAEMON_OPTS=""
# Wechseln Sie zu /var/spool/postfix/run/opendkim, um einen Unix-Socket mit zu verwenden
RUNDIR=/run/opendkim
# Postfix in einer Chroot:
# RUNDIR=/var/spool/postfix/run/opendkim
#
# Entfernen Sie das Kommentarzeichen, um einen alternativen Socket anzugeben
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Beachten Sie, dass durch diese Einstellung alle Socket-Werte in opendkim.conf überschrieben werden
# Standard:
# Hören Sie alle Schnittstellen an Port 54321:
# SOCKET=inet:54321
# Hören Sie auf Loopback auf Port 12345:
# SOCKET=inet:12345@localhost
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Hören Sie 192.0.2.1 auf Port 12345:

SOCKET=inet:12345@192.0.2.1

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
Wenn wir bereit sind, unseren Postfix-Server einzurichten, führen wir den folgenden Code mit eingebettetem entsprechenden Domänennamen aus. Beginnen Sie mit der Erstellung eines Skripts

# Bearbeiten Sie diese Datei nun in Nano, dem Texteditor, sodass sie Ihren Domainnamen anstelle von „femmebabe.com" enthält.
#
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}'
!/bin/bash

Postfix einrichten

./scripts/postfixsetup
Führen Sie nun das fertige Skript aus, um Postfix, OpenDkim und Dovecot zu konfigurieren.

Sobald dieses Skript ausgeführt wurde, kopieren Sie die letzte gedruckte Zeile und fügen Sie sie als Wert für sendonly._domainkey in Ihre DNS-Konfiguration ein. Dies ist der OpenDKIM-Schlüssel, der zur Identifizierung Ihrer Domain beim Senden sicherer E-Mails verwendet wird.

Eindrucksvoll! Innerhalb weniger Tage sollten Sie in der Lage sein, E-Mails vom Server zu versenden, sofern alles richtig konfiguriert ist.

echo "test" | mail -s "Test Email" youremail@gmail.com
Wenn Sie gerade den DNS für Ihren Mailserver konfiguriert haben, sollte es weniger als 72 Stunden dauern, bis die Einträge aktualisiert sind. Normalerweise geht es viel schneller. Sie können überprüfen, ob Ihr Server funktioniert, indem Sie diesen Befehl verwenden und Ihre E-Mail-Adresse angeben:

tail –lines 150 /var/log/mail.log
Wenn alles ordnungsgemäß zu funktionieren scheint, sollten Sie mit Ihrem Server E-Mails senden können. Wenn es nicht funktioniert, sehen Sie sich die Protokolle an, um herauszufinden, wo der Fehler liegen könnte.

Dadurch erhalten Sie ausführliche Informationen über die E-Mails, die vom Server gesendet werden, und darüber, ob diese ordnungsgemäß funktionieren. Sie sollten die E-Mail auch in Ihrem Posteingang sehen können. Wenn sie nicht dort ist, überprüfen Sie Ihren Spam-Ordner.

EMAIL_HOST = DOMAIN
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = 'team@femmebabe.com'
EMAIL_HOST_USER = 'team' # Sie müssen auch Ihre Einstellungen in Ihrer Datei „settings.py" konfigurieren, damit Ihr E-Mail-Server mit Ihrer Django-App, dem Projekt, kommunizieren kann. Fügen Sie diese Zeilen in Ihren Einstellungen hinzu oder ersetzen Sie sie
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)

„Love@MamaSheen.com"

import os
import json

# Beachten Sie, dass wir eine Konfigurationsdatei verwenden, um das Passwort zu erhalten. Laden wir diese Datei in den Einstellungen wie folgt, ganz am Anfang der Datei:
with open('/etc/config.json') as config_file:
    config = json.load(config_file)

Konfiguration öffnen und laden

openssl rand -base64 64
Erstellen wir diese Datei und fügen ihr einen geheimen Schlüssel sowie das E-Mail-Passwort hinzu. Um einen geheimen Schlüssel zu generieren, verwenden Sie diesen Befehl, mit beliebiger Länge am Ende:

sudo nano /etc/config.json
Kopieren Sie nun den von openssl generierten Text und bearbeiten Sie /etc/config.json

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
Fügen Sie die folgenden Zeilen zu Ihrer Datei hinzu, mit dem Schlüssel, den openssl generiert hat, als geheimen Schlüssel.

Das JSON-Format ist einfach und benutzerfreundlich. Auf diese Weise können wir auch andere Schlüssel deklarieren, die wir in unserem Projekt verwenden möchten, und sie von unserem Projektverzeichnis getrennt aufbewahren, sodass andere Benutzer nicht darauf schreiben können und sie nicht allein aus unserem Projektverzeichnis gelesen werden können. Dies ist eine empfohlene Vorgehensweise für API-Schlüssel, von denen wir hier nicht wenige verwenden werden.

sudo backup
Sie sollten Ihr Projekt auch sichern, um sicherzustellen, dass alles gespeichert ist und Sie Ihre Arbeit später wiederherstellen können, auch wenn Sie keinen Server mehr mieten möchten.

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()
Versuchen Sie nun, eine HTML-E-Mail vom Webserver zu senden, sofern das Senden einer E-Mail über die Befehlszeile funktioniert. Fragen Sie Ihre Benutzerinstanz in der Shell ab und senden Sie über Django eine HTML-E-Mail an diesen Benutzer. Ändern Sie meinen Namen im Code, Charlotte, in Ihren Benutzernamen.

source venv/bin/activate
Wenn der erste Befehl nicht funktioniert, verwenden Sie ihn unbedingt

Sofern alles korrekt eingerichtet ist, erhalten Sie nun eine Willkommens-E-Mail in Ihrem Postfach, die von Ihrer Web-App gesendet wird. Gute Arbeit! Du hast einen langen Weg zurückgelegt.

Ich möchte hinzufügen: Wenn Sie bei der Arbeit an einem solchen Projekt jemals mit Fehlern zu kämpfen haben, zögern Sie nicht, nach Antworten zu suchen und um Hilfe zu bitten. Google und andere Suchmaschinen sind hervorragende Quellen für die Suche nach Programmierhilfe. Suchen Sie einfach nach dem Fehler, den Sie erhalten, und Sie können sehen, wie andere Leute das Problem lösen. Sie können sich auch gerne an mich, Ihre Pädagogen (Lehrer, Professoren, Tutoren) und alle Kollegen im Internet wenden, die für Programmierhilfe zur Verfügung stehen, oder dieses Buch oder andere Ressourcen erneut konsultieren, um Lösungen für die Probleme zu finden, mit denen Sie konfrontiert sind. Ich verstehe, dass das nicht einfach ist, aber selbst wenn Sie bis hierhin gelesen haben und keinen Code schreiben, lernen Sie viel über die Erstellung einer Web-App von Grund auf. Klopfen Sie sich selbst auf die Schulter, Sie machen einen tollen Job.






Schließen
Seite 1
Springen
Vollständigen Artikel ansehen
Lesen Sie weiter

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung



Wie baue ich eine erfolgreiche Website? Geben Sie mir einige Tipps in allgemeinen Richtlinien. 1. Zweck: Bestimmen Sie, was Sie mit Ihrer Website erreichen möchten. Möchten Sie Produkte verkaufen, Informationen austauschen, eine Community aufbauen oder etwas anderes? Dies wird Ihre Design- und Inhaltsentscheidungen leiten. 2. Zielgruppenidentifikation: Verstehen Sie, wer Ihre Zielgruppe ist. Dies wird Ihnen dabei helfen, Inhalte zu entwerfen und zu erstellen, die sie ansprechen. 3. Gutes Design: Ihre Website sollte professionell und optisch ansprechend aussehen. Dazu gehört nicht nur das grafische Design, sondern auch ein klares, intuitives und leicht zu navigierendes Layout. 4. Hochwertiger Inhalt: Die Texte, Bilder, Videos und anderen Inhalte auf Ihrer Website sollten hochwertig und für Ihre Benutzer wertvoll sein. Es sollte regelmäßig aktualisiert werden. 5. Mobilfreundlich: Ihre Website sollte responsive sein, d. h. sie passt sich an jede Bildschirmgröße an. Immer mehr Menschen surfen mit ihren Mobiltelefonen im Internet, daher muss Ihre Website gut aussehen und auf Mobilgeräten gut funktionieren. 6. SEO: Suchmaschinenoptimierung ist entscheidend dafür, dass Ihre Website von Ihrer Zielgruppe gesehen wird. Stellen Sie sicher, dass Ihre Website mit relevanten Schlüsselwörtern, Links und Meta-Tags optimiert ist. 7. Schnelle Ladezeit: Stellen Sie sicher, dass Ihre Website schnell lädt. Eine langsame Website kann Besucher abschrecken. 8. Klarer Aufruf zum Handeln: Stellen Sie sicher, dass jede Seite einen klaren Aufruf zum Handeln enthält, sei es zum Kauf eines Produkts, zur Anmeldung für einen Newsletter, zur Kontaktaufnahme usw. 9. Einfacher Kontakt und Support: Ihre Website sollte es Besuchern leicht machen, mit Ihnen in Kontakt zu treten oder Support in Anspruch zu nehmen. 10. Verwenden Sie Analytics: Verfolgen Sie die Leistung Ihrer Website mit Tools wie Google Analytics. Dies wird Ihnen helfen, Ihr Publikum besser zu verstehen und Verbesserungen an Ihrer Website vorzunehmen. 11. Sicherheit: Wenn Sie persönliche Daten oder Zahlungen über Ihre Website akzeptieren, muss diese mit einem SSL-Zertifikat gesichert sein. 12. Regelmäßige Updates und Wartung: Wie jede andere Technologie müssen Websites regelmäßig gewartet und aktualisiert werden, um sicherzustellen, dass sie reibungslos funktionieren und vor Bedrohungen geschützt sind. 13. Seien Sie im Einklang mit Ihrer Marke: Die Farben, Logos, Bilder und der Tonfall sollten zu Ihrer Markenidentität passen. Denken Sie daran, dass der Aufbau einer erfolgreichen Website eine fortlaufende Aufgabe ist. Sobald Sie es erstellt haben, müssen Sie es ständig aktualisieren und verbessern, damit es relevant und erfolgreich bleibt. Außerdem müssen Sie möglicherweise darüber nachdenken, Fachleute wie Webentwickler, Webdesigner, Content-Ersteller und SEO-Spezialisten einzustellen, um sicherzustellen, dass jeder Aspekt Ihrer Website den Anforderungen entspricht. Es stehen jedoch auch zahlreiche Tools und Ressourcen online zur Verfügung, wenn Sie sich dafür entscheiden, es selbst zu tun. Lernen Sie immer weiter und passen Sie sich an.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Warum implantieren Menschen NFC-Implantate in ihre Hände?


Es gibt mehrere Gründe, warum sich Menschen dafür entscheiden, NFC-Implantate (Near Field Communication) in ihre Hände zu implantieren:


1. Bequemlichkeit: NFC-Implantate ermöglichen es Einzelpersonen, mit einer einfachen Handbewegung einfach auf Informationen zuzugreifen, Türen zu öffnen, Zahlungen zu tätigen und andere Aufgaben zu erledigen. Dies kann bequemer sein, als Schlüssel, Ausweise oder Smartphones mit sich herumzutragen.


2. Sicherheit: NFC-Implantate können eine zusätzliche Sicherheitsebene bieten, da sie zur Aktivierung einen physischen Zugang zum Körper der Person erfordern. Dies kann dazu beitragen, unbefugten Zugriff auf Geräte oder vertrauliche Informationen zu verhindern.


3. Technologische Experimente: Manche Menschen entscheiden sich für die Implantation von NFC-Chips, um mit neuen Technologien zu experimentieren und sie in ihr tägliches Leben zu integrieren.


4. Persönliche Identifizierung: NFC-Implantate können zur persönlichen Identifizierung verwendet werden, beispielsweise zum Speichern medizinischer Informationen oder Kontaktdaten, die im Notfall leicht zugänglich sind.


5. Biohacking: Manche Menschen betrachten NFC-Implantate als eine Form des Biohackings, bei dem sie ihren Körper mit Technologie erweitern, um ihre Fähigkeiten oder Erfahrungen zu verbessern.


Insgesamt ist die Entscheidung, sich NFC-Chips in die Hände zu implantieren, eine persönliche Entscheidung, die von Person zu Person aufgrund ihrer individuellen Vorlieben und Überzeugungen unterschiedlich ist.


Kaufen Sie weiter

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Welche Vorteile bietet eine Überwachungskamera?


1. Abschreckung vor kriminellen Aktivitäten – Überwachungskameras können potenzielle Kriminelle abschrecken, da sie weniger wahrscheinlich eine Straftat begehen, wenn sie wissen, dass sie beobachtet werden.


2. Überwachung und Überwachung – Mit Sicherheitskameras können Sie Ihr Eigentum überwachen und verdächtige Aktivitäten in Echtzeit im Auge behalten, um Diebstahl, Vandalismus oder andere Straftaten zu verhindern.


3. Beweise im Falle einer Straftat – Für den unglücklichen Fall, dass auf Ihrem Grundstück tatsächlich eine Straftat begangen wird, können die Aufnahmen von Überwachungskameras wichtige Beweise für Strafverfolgungs- und Versicherungsansprüche liefern.


4. Fernzugriff – Viele Sicherheitskameras bieten mittlerweile Fernüberwachungsfunktionen, sodass Sie von überall aus mit Ihrem Smartphone oder Computer auf Ihr Grundstück zugreifen können.


5. Sorgenfreiheit – Durch die Installation von Sicherheitskameras können Sie beruhigt sein, da Sie wissen, dass Ihr Eigentum überwacht wird und potenzielle Bedrohungen erkannt und aufgezeichnet werden.


von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Warum sollte ich beim l-Wort ein Apfel-l-out verwenden?


Die Verwendung eines Apfel-L am L-Wort kann Ihr Seherlebnis auf verschiedene Weise verbessern. Der Apple L ist ein beliebtes Streaming-Gerät, mit dem Sie ganz einfach auf Ihre Lieblingssendungen zugreifen und diese mit hochwertigem Video und Audio ansehen können. Durch die Verwendung eines Apfel-L beim L-Wort können Sie gestochen scharfe, klare Bilder und einen beeindruckenden Sound genießen, der Ihnen das Gefühl gibt, mitten im Geschehen zu sein.


Darüber hinaus bietet das Apple L eine benutzerfreundliche Oberfläche, die es einfach macht, durch Episoden zu navigieren, Szenen anzuhalten und zurückzuspulen und Ihr Seherlebnis individuell anzupassen. Sie können auch Funktionen wie die Sprachsuche und personalisierte Empfehlungen nutzen, um neue Inhalte zu entdecken, die Ihnen Spaß machen.


Insgesamt kann Ihnen die Verwendung eines Apple-L am L-Wort ein erstklassiges Streaming-Erlebnis bieten, das es Ihnen ermöglicht, vollständig in die fesselnde Welt der Show einzutauchen.

.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie versende ich E-Mails mit einer konformen E-Mail-Liste und Abmeldelinks?


Um eine E-Mail mit einer konformen Liste und einem engeren Abmeldelink zu senden, sollten Sie die folgenden Schritte ausführen:


1. Stellen Sie sicher, dass Ihre E-Mail-Liste allen relevanten Vorschriften entspricht, wie dem CAN-SPAM Act und der DSGVO. Das bedeutet, dass alle Empfänger dem Empfang Ihrer E-Mails zugestimmt haben müssen und dass Sie deren ausdrückliche Einwilligung zur Kontaktaufnahme haben.


2. Fügen Sie Ihrer E-Mail einen deutlich sichtbaren Abmeldelink hinzu. Stellen Sie sicher, dass es leicht zu finden und anzuklicken ist und dass die Empfänger direkt zu einer Seite weitergeleitet werden, auf der sie sich problemlos von Ihrer Mailingliste abmelden können.


3. Um den Abmeldelink „enger" zu gestalten, können Sie eine Ein-Klick-Abmeldeoption verwenden. Das bedeutet, dass Empfänger Ihre E-Mails mit nur einem Klick abbestellen können, ohne zusätzliche Formulare ausfüllen oder persönliche Daten angeben zu müssen.


4. Achten Sie beim Versenden der E-Mail darauf, die Nachricht zu personalisieren und den Empfänger möglichst namentlich anzusprechen. Dies kann dazu beitragen, das Engagement zu steigern und dafür zu sorgen, dass sich die E-Mail für den Empfänger relevanter anfühlt.


5. Testen Sie die E-Mail vor dem Versenden, um sicherzustellen, dass der Abmeldelink ordnungsgemäß funktioniert und die E-Mail auf allen Geräten und E-Mail-Clients gut aussieht.


Wenn Sie diese Schritte befolgen, können Sie eine E-Mail mit einer konformen Liste und einem engeren Abmeldelink senden, um sicherzustellen, dass Ihre Empfänger eine positive Erfahrung machen und sich problemlos vom Erhalt weiterer E-Mails von Ihnen abmelden können.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie finde ich Kunden für mein kleines Webentwicklungsunternehmen?


Hier sind einige Strategien, mit denen Sie Kunden für Ihr Webentwicklungsunternehmen gewinnen können:


1. Bauen Sie eine starke Online-Präsenz auf: Erstellen Sie eine professionelle Website, die Ihre Dienstleistungen, Ihr Portfolio und Kundenstimmen präsentiert. Nutzen Sie Social-Media-Kanäle, um für Ihr Unternehmen zu werben und mit potenziellen Kunden in Kontakt zu treten.


2. Netzwerk: Nehmen Sie an Branchenveranstaltungen, Konferenzen und Treffen teil, um mit anderen Fachleuten auf diesem Gebiet und potenziellen Kunden in Kontakt zu treten. Treten Sie Online-Communities und Foren zum Thema Webentwicklung bei, um Ihr Netzwerk zu erweitern.


3. Bieten Sie Empfehlungsanreize: Ermutigen Sie zufriedene Kunden, Ihre Dienstleistungen an andere weiterzuempfehlen, indem Sie Rabatte oder andere Anreize für erfolgreiche Empfehlungen anbieten.


4. Arbeiten Sie mit anderen Unternehmen zusammen: Arbeiten Sie mit Agenturen für digitales Marketing, Grafikdesignern oder anderen Fachleuten zusammen, die möglicherweise Webentwicklungsdienste für ihre Kunden benötigen.


5. Werben: Investieren Sie in Online-Werbung über Google AdWords, Social-Media-Anzeigen oder Display-Anzeigen, um ein breiteres Publikum zu erreichen.


6. Kalte Kontaktaufnahme: Kontaktieren Sie potenzielle Kunden direkt per E-Mail oder Telefon und stellen Sie Ihre Dienstleistungen und Ihre bisherige Arbeit vor.


7. Content-Marketing: Erstellen Sie wertvolle Inhalte wie Blogbeiträge, Whitepapers oder Webinare, die Ihr Fachwissen in der Webentwicklung demonstrieren und potenzielle Kunden über Suchmaschinen und soziale Medien anziehen.


8. Besuchen Sie Messen und Veranstaltungen: Nehmen Sie an Branchenmessen und Veranstaltungen teil, um mit potenziellen Kunden in Kontakt zu treten und Ihre Dienstleistungen zu präsentieren.


9. Bieten Sie kostenlose Beratungen an: Bieten Sie potenziellen Kunden kostenlose Beratungen an, um ihre Bedürfnisse zu besprechen und wie Ihre Dienstleistungen ihnen helfen können, ihre Ziele zu erreichen.


10. Bitten Sie um Bewertungen und Erfahrungsberichte: Ermutigen Sie zufriedene Kunden, Bewertungen und Erfahrungsberichte auf Ihrer Website oder anderen Bewertungsplattformen zu hinterlassen, um Glaubwürdigkeit aufzubauen und neue Kunden zu gewinnen.


von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Welche Vorteile hat das Tragen einer Maske? 1. Verhindert die Ausbreitung von Infektionen: Masken reduzieren die Übertragung von Viren, einschließlich COVID-19, Grippe und anderen Atemwegserkrankungen, erheblich, indem sie Tröpfchen einfangen, die freigesetzt werden, wenn der Träger spricht, hustet oder niest. 2. Persönlicher Gesundheitsschutz: Masken fügen eine Schutzschicht hinzu, die den Träger davor schützt, schädlichen Partikeln und Tröpfchen in der Luft ausgesetzt zu werden. 3. Schützt die Menschen in Ihrer Umgebung: Dies ist besonders wichtig, wenn Sie in engem Kontakt mit Menschen stehen, bei denen ein höheres Risiko für schwere Erkrankungen besteht. 4. Verhindert das Berühren Ihres Gesichts: Das Tragen einer Maske kann Sie davon abhalten, Ihr Gesicht und Ihren Mund zu berühren, was eine häufige Art der Übertragung von Viren ist. 5. Quellenkontrolle: Auch wenn Sie asymptomatisch oder präsymptomatisch sind, sorgt das Tragen einer Maske dafür, dass die Menschen in Ihrer Umgebung sicher sind. 6. Maßnahme für die öffentliche Gesundheit: Auf breiterer Ebene trägt die weit verbreitete Verwendung von Masken dazu bei, die Ausbreitung eines Virus in der Gemeinschaft zu verlangsamen, was Vorteile für die öffentliche Gesundheit bringt. 7. Obligatorische Einhaltung: In vielen Teilen der Welt ist das Tragen einer Maske an öffentlichen Orten obligatorisch. Es hilft Ihnen, die Regeln einzuhalten und Strafen zu vermeiden. 8. Soziale Erinnerung: Zu sehen, wie andere Masken tragen, dient als Erinnerung an die Bedeutung präventiver Gesundheitsverhaltensweisen (wie soziale Distanzierung und häufiges Händewaschen). 9. Allergieprävention: Auch bei Allergikern können Masken Schutz vor Allergenen bieten. 10. Vorteile bei kaltem Wetter: In kälteren Klimazonen können Masken dazu beitragen, die Luft vor dem Einatmen zu erwärmen, was dazu beitragen kann, kältebedingte Asthmaanfälle zu verhindern.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie baue ich eine Website? gib mir ein paar Tipps. in allgemeinen Richtlinien. 1. Identifizieren Sie Ihren Zweck: Skizzieren Sie, worum es auf Ihrer Website geht. Machen Sie deutlich, was Sie mit Ihrer Website erreichen möchten. Möchten Sie Produkte verkaufen, Informationen bereitstellen, eine Dienstleistung bewerben usw.? 2. Wählen Sie Ihre Website-Plattform: Wenn Sie zum ersten Mal eine Website erstellen, möchten Sie möglicherweise ein Content-Management-System (CMS) wie WordPress, Joomla oder Drupal verwenden. Diese Plattformen machen die Website-Erstellung einfach und erfordern oft keine Programmierkenntnisse. Wenn Ihr Schwerpunkt auf E-Commerce liegt, sind Plattformen wie Shopify oder Magento möglicherweise besser für Ihre Anforderungen geeignet. 3. Wählen Sie einen Domainnamen: Dies ist Ihre Webadresse. Stellen Sie sicher, dass es leicht zu buchstabieren und zu merken ist. Es ist besser, .com, .net oder .org zu verwenden. 4. Holen Sie sich einen Webhosting-Anbieter: Webhosting-Anbieter speichern die Dateien Ihrer Website und machen sie im Internet zugänglich. Es gibt viele Hosting-Anbieter mit jeweils unterschiedlichen Preisstrukturen und Funktionen. Einige beliebte Optionen sind Bluehost, SiteGround und DreamHost. 5. Planen Sie Ihr Website-Design: Entscheiden Sie, wie Ihre Website aussehen soll. Achten Sie auf Faktoren wie Layout, Navigation, Farbschema und Typografie. Sie sollten auch darüber nachdenken, wie Ihre Website sowohl auf Smartphones als auch auf Desktop-Computern aussehen wird. 6. Erstellen Sie Ihre Seiten: Die meisten Websites enthalten mindestens einige der folgenden Seiten: Startseite, Über uns, Dienstleistungen/Produkte, Kontakt, Blog. Stellen Sie sicher, dass Ihre Seiten gut organisiert und nicht mit Informationen überladen sind. Stellen Sie sicher, dass Ihre Kontaktdaten leicht zu finden sind. 7. SEO: Stellen Sie sicher, dass Sie Ihre Website für Suchmaschinen optimieren, um die Sichtbarkeit zu erhöhen. Fügen Sie Meta-Tags, Beschreibungen und Schlüsselwörter in Ihre Inhalte ein. Stellen Sie außerdem sicher, dass Ihre Website schnell lädt, da Geschwindigkeit ein Faktor ist, der sich auf das Suchmaschinenranking auswirkt. 8. Für Mobilgeräte optimieren: Immer mehr Menschen nutzen ihre Mobiltelefone, um im Internet zu surfen. Stellen Sie sicher, dass Ihre Website für Mobilgeräte geeignet ist. 9. Testen Sie Ihre Website: Bevor Ihre Website online geht, testen Sie sie unbedingt. Überprüfen Sie alle Links, stellen Sie sicher, dass das Layout in verschiedenen Webbrowsern und auf Mobilgeräten gut aussieht, und stellen Sie sicher, dass alle Formulare ordnungsgemäß funktionieren. 10. Bewerben Sie Ihre Website: Nutzen Sie soziale Medien, SEO-Strategien und andere Online-Marketing-Strategien, um den Traffic auf Ihre Website zu steigern. 11. Analysieren und verbessern: Nachdem Ihre Website online ist, verwenden Sie Analysetools wie Google Analytics, um zu sehen, wie Besucher mit Ihrer Website interagieren. Diese wertvollen Informationen können Ihnen helfen, Ihre Website zu verbessern und Ihren Besuchern ein besseres Erlebnis zu bieten. 12. Halten Sie Ihre Website auf dem neuesten Stand: Aktualisieren Sie Ihre Website regelmäßig, beheben Sie etwaige Fehler und fügen Sie neue Inhalte hinzu, um Ihr Publikum zu fesseln und die SEO zu verbessern. Denken Sie daran, dass der Aufbau einer Website Zeit und Geduld erfordert. Scheuen Sie sich nicht, Hilfe zu suchen, wenn Sie sie brauchen. Viel Glück!

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung



Wie kocht man Eier am besten?




von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Erzählen Sie mir etwas über Kabel. Kabel bezieht sich auf eine Art Telekommunikationstechnologie, die zur Übertragung von Informationen über einen physischen Strang oder ein Netzwerk aus Strängen verwendet wird. Diese Litzen bestehen häufig aus Kupfer, Aluminium, Glas oder Kunststoff und können Signale für Fernseh-, Internet- oder Telefondienste übertragen. Es gibt verschiedene Arten von Kabeln, darunter: 1. Ethernet-Kabel: Am häufigsten für kabelgebundene Netzwerke verwendet. Sie verbinden Geräte wie PCs, Router und Switches innerhalb eines lokalen Netzwerks. 2. Koaxialkabel: Bekannt für ihre hohe Fähigkeit, Hochfrequenzsignale zu übertragen, wodurch sie sich ideal für den Anschluss von Antennen, Kabelfernsehnetzen und Computernetzwerkverbindungen eignen. 3. Glasfaserkabel: Diese übertragen Informationen zwischen zwei Orten mithilfe vollständig optischer (lichtbasierter) Technologie. Sie verfügen über eine viel höhere Bandbreitenkapazität und übertragen Daten sehr effektiv über große Entfernungen. 4. HDMI-Kabel: Diese Kabel übertragen hochauflösende und ultrahochauflösende Video- und Audiosignale von Geräten wie Blu-ray-Playern, Spielekonsolen oder anderen Geräten, die an ein HD-Display angeschlossen werden müssen. Im Kontext des Fernsehens ist Kabelfernsehen ein System zur Bereitstellung von Fernsehprogrammen für Verbraucher über Hochfrequenzsignale (RF), die über Koaxialkabel oder in neueren Systemen über Lichtimpulse über Glasfaserkabel übertragen werden. Dies steht im Gegensatz zum Rundfunkfernsehen (auch als terrestrisches Fernsehen bekannt), bei dem das Fernsehsignal über die Luft übertragen wird. Im Internetkontext ist Kabel-Internetdienst eine Methode des Breitband-Internetzugangs, die die Kabelfernsehinfrastruktur nutzt. Wenn sich Ihr Zuhause in einem Gebiet befindet, in dem Kabelfernsehen vorhanden ist, können Sie wahrscheinlich einen Kabelanschluss für den Internetzugang erhalten. Insgesamt kann sich „Kabel“ je nach Kontext auf mehrere Arten digitaler Kommunikation beziehen.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Was verursacht Migräne und wie wird sie behandelt?


Migräne ist ein starker Kopfschmerz, der häufig mit weiteren Symptomen wie Übelkeit, Licht- und Geräuschempfindlichkeit sowie Sehstörungen einhergeht. Die genaue Ursache der Migräne ist nicht vollständig geklärt, es wird jedoch angenommen, dass sie mit Veränderungen des Blutflusses und der Chemikalien im Gehirn zusammenhängt.


Die Behandlung von Migräne umfasst typischerweise eine Kombination aus Änderungen des Lebensstils, Medikamenten und alternativen Therapien. Zu den gängigen Behandlungsoptionen gehören:


1. Einnahme von rezeptfreien Schmerzmitteln wie Ibuprofen oder Paracetamol

2. Verschreibungspflichtige Medikamente, die speziell zur Behandlung von Migräne entwickelt wurden, wie zum Beispiel Triptane und Ergotamine

3. Vermeiden Sie Auslöser wie bestimmte Nahrungsmittel, Stress, Schlafmangel oder hormonelle Veränderungen

4. Entspannungstechniken wie tiefes Atmen oder Meditation üben

5. Anlegen heißer oder kalter Packungen an Kopf oder Hals

6. Regelmäßige Bewegung und eine gesunde Ernährung


Für Personen, die unter Migräne leiden, ist es wichtig, gemeinsam mit ihrem Arzt einen Behandlungsplan zu entwickeln, der auf ihre spezifischen Bedürfnisse und Auslöser zugeschnitten ist. In einigen Fällen kann eine Kombination von Therapien erforderlich sein, um Migräne wirksam zu behandeln und die Lebensqualität zu verbessern.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie schreibe ich einen professionellen Blogbeitrag?


Das Schreiben eines professionellen Blogbeitrags umfasst mehrere wichtige Schritte, um einen gut gestalteten und ansprechenden Inhalt zu erstellen. Hier sind einige Tipps, die Ihnen beim Schreiben eines professionellen Blogbeitrags helfen:

1. Wählen Sie ein relevantes und ansprechendes Thema: Identifizieren Sie zunächst ein Thema, das für Ihr Publikum relevant ist und über das Sie sich gut auskennen und leidenschaftlich sind. Stellen Sie sicher, dass das Thema Ihre Leser interessiert und bei ihnen Anklang findet.

2. Führen Sie gründliche Recherchen durch: Bevor Sie mit dem Schreiben beginnen, stellen Sie sicher, dass Sie gründliche Recherchen zu dem von Ihnen gewählten Thema durchführen. Dies wird Ihnen dabei helfen, relevante Informationen, Statistiken und Fakten zu sammeln, um Ihre Argumente zu untermauern und Ihren Blog-Beitrag glaubwürdiger zu machen.

3. Erstellen Sie eine Gliederung: Organisieren Sie Ihre Ideen und Kernpunkte, indem Sie eine Gliederung für Ihren Blogbeitrag erstellen. Dies wird Ihnen helfen, Ihre Inhalte logisch und kohärent zu strukturieren und es den Lesern so leichter zu machen, ihnen zu folgen.

4. Schreiben Sie eine überzeugende Einleitung: Beginnen Sie Ihren Blogbeitrag mit einer starken und ansprechenden Einleitung, die die Aufmerksamkeit des Lesers erregt. Verwenden Sie einen Hook, um die Leser anzulocken und ihnen den Wunsch zu wecken, weiterzulesen.

5. Verwenden Sie eine klare und prägnante Sprache: Vermeiden Sie in Ihrem Blog-Beitrag die Verwendung von Jargon oder übermäßig technischer Sprache. Schreiben Sie klar und prägnant, damit Ihre Inhalte für alle Leser leicht verständlich sind.

6. Fügen Sie visuelle Elemente ein: Visuelle Elemente wie Bilder, Infografiken und Videos können dazu beitragen, den Text aufzulockern und Ihren Blog-Beitrag optisch ansprechend zu gestalten. Sie können auch dazu beitragen, Ihre wichtigsten Punkte zu untermauern und Ihre Inhalte ansprechender zu gestalten.

7. Korrekturlesen und Bearbeiten: Stellen Sie vor der Veröffentlichung Ihres Blogbeitrags sicher, dass Sie ihn gründlich Korrektur lesen und auf Grammatik-, Rechtschreib- und Formatierungsfehler überprüfen. Erwägen Sie, einen Kollegen oder Freund zu bitten, Ihren Beitrag zu überprüfen, um Feedback einzuholen, bevor Sie ihn veröffentlichen.

8. Fügen Sie einen Call-to-Action hinzu: Beenden Sie Ihren Blog-Beitrag mit einem starken Call-to-Action, der die Leser dazu ermutigt, sich mit Ihren Inhalten zu beschäftigen, z. B. Ihren Blog zu abonnieren, zu kommentieren oder Ihren Beitrag in sozialen Medien zu teilen

Wenn Sie diese Tipps befolgen, können Sie einen professionellen und ansprechenden Blogbeitrag erstellen, der bei Ihrem Publikum Anklang findet und Sie als Autorität auf Ihrem Gebiet etabliert.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Was gibt es für tolle Dinge, die man in der begrabenen Gegend von Seattle unternehmen kann? 1. Seahurst Park: Es ist ein wunderschöner Park mit Blick auf den Puget Sound, Wanderwegen und Zugang zum Strand. Der perfekte Ort für ein Familienpicknick im Freien oder einfach nur zum Entspannen. 2. Highline SeaTac Botanical Garden: Ein bezaubernder 10,5 Hektar großer öffentlicher Garten, der großartige Pflanzen-, Blumen- und interessante Kunstskulpturen bietet. 3. Tin Room Bar & Grill: Ein cooler Ort zum Essen, Abhängen und Kinoschauen. Der Ort bietet eine einzigartige Kulisse und Erfahrung für Einheimische und Touristen. 4. Burien Farmer's Market: Ein großartiger Ort, um lokale Lebensmittel aus dem Bundesstaat Washington zu probieren. Der Markt bietet eine lebendige Mischung aus frischen Produkten, Pflanzen, Kunsthandwerk und Imbisswagen. 5. Environmental Science Center: Eine Bildungseinrichtung mit einer Sammlung von Naturausstellungen und nachhaltigen Praktiken, Workshops und praktischen Aktivitäten für alle Altersgruppen. 6. Moshier Art Center: Bietet verschiedene Kunstkurse und Workshops für Kinder und Erwachsene. 7. Wenn Sie ein Fan von Secondhand-Einkäufen sind, gibt es in Burien mehrere tolle Secondhand-Läden, darunter St. Vincent de Paul und The Goodwill. 8. Machen Sie einen Spaziergang um den Lake Burien oder entdecken Sie die Wanderwege im Eagle Landing Park. 9. Der Dottie Harper Park verfügt über Kunstinstallationen im Freien, einen Kinderspielplatz und Waldgebiete mit Spazierwegen. 10. Sie können das Burien Community Center oder das Burien Parks and Recreation Center für lokale Veranstaltungen, Kurse oder Ressourcen besuchen. Denken Sie daran, sich vor Ihrem Besuch über die Öffnungszeiten und etwaige Pandemieregeln/-einschränkungen für diese Orte zu informieren.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Lesen Sie mir ein kurzes Gedicht vor. Verzweifeln Sie nicht, wenn der graue Himmel weint, Denn nach dem Regen sickern Segen durch. Hinter der dunkelsten Nacht scheint Es scheint immer ein hellerer Tag. Jede Herausforderung, ein steiler Berg, Doch Sieger sind diejenigen, die den Sprung wagen. Im großen Theater des Lebens spielen Sie Ihr Stück, Nehmen Sie die Reise an, kommen Sie was mag.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Warum ist es sicherer, in der Öffentlichkeit eine Maske zu tragen?


Das Tragen einer Maske in der Öffentlichkeit ist sicherer, da es dazu beiträgt, die Ausbreitung von Atemtröpfchen zu verhindern, die Viren wie Covid-19 enthalten. Wenn jemand mit einem Virus eine Maske trägt, verhindert dies, dass seine Atemtröpfchen in die Luft gelangen und möglicherweise andere infizieren. Darüber hinaus kann das Tragen einer Maske den Träger vor dem Einatmen von Atemtröpfchen anderer möglicherweise infizierter Personen schützen. Dies ist besonders wichtig in Situationen, in denen es schwierig ist, soziale Distanz einzuhalten, beispielsweise in überfüllten Innenräumen oder in öffentlichen Verkehrsmitteln. Insgesamt ist das Tragen einer Maske eine einfache und wirksame Möglichkeit, die Übertragung von Viren zu reduzieren und sich selbst und die Menschen in Ihrer Umgebung zu schützen.


.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Sagen Sie mir, wie das Wetter heute in Seattle ist. Leider habe ich als KI keinen Zugriff auf Echtzeitdaten und kann keine aktuellen Wetterinformationen bereitstellen. Die genauesten Daten finden Sie auf einer zuverlässigen Wetter-Website oder -App.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung



Welche Vorteile hat das Trinken von Tee? 1. Reich an Antioxidantien: Tee, insbesondere grüner Tee, ist reich an Antioxidantien, sogenannten Polyphenolen, die durch die Bekämpfung schädlicher freier Radikale zum Schutz vor verschiedenen Krebsarten und anderen Krankheiten beitragen können. 2. Herzgesundheit: Einige Studien deuten darauf hin, dass der regelmäßige Konsum von Tee dazu beitragen kann, den Spiegel des schlechten Cholesterins zu senken und den Spiegel des guten Cholesterins zu erhöhen, was das Risiko von Herzerkrankungen verringern kann. 3. Gewichtsverlust: Tee kann beim Abnehmen helfen. Es verfügt über eine Kategorie von Antioxidantien, die als Catechine bekannt sind und dabei helfen können, Körperfett zu reduzieren. 4. Stärkt das Immunsystem: Tee kann die Abwehrkräfte des Körpers gegen Infektionen stärken und enthält antimikrobielle Eigenschaften. 5. Verbessert das Verdauungssystem: Es unterstützt auch die Verdauung und kann das Reizdarmsyndrom und andere Verdauungsprobleme lindern. 6. Reduziert Stress und Ängste: Bestimmte Teesorten wie Kamille und Lavendel sind für ihre beruhigenden Eigenschaften bekannt und können dabei helfen, den Geist zu beruhigen und Stress und Ängste abzubauen. 7. Knochengesundheit: Einige Studien deuten darauf hin, dass regelmäßige Teetrinker aufgrund der im Tee enthaltenen sekundären Pflanzenstoffe stärkere Knochen und eine geringere Wahrscheinlichkeit haben, an Arthritis zu erkranken. 8. **** Gesundheit: Das im Tee enthaltene Fluorid und die Tannine können dazu beitragen, Plaque und Karies vorzubeugen, was zu einer besseren Gesundheit führt. 9. Antivirale und antibakterielle Eigenschaften: Tee enthält Substanzen mit antiviralen und antibakteriellen Eigenschaften, die vor einer Vielzahl von Infektionen schützen können. 10. Erhöht die Wachsamkeit: Das Koffein im Tee ist zwar nicht so hoch wie Kaffee, kann aber dabei helfen, die geistige Wachsamkeit zu steigern und die kognitiven Funktionen zu verbessern. Bitte beachten Sie: Obwohl Tee viele gesundheitliche Vorteile bieten kann, ersetzt er nicht die Notwendigkeit einer ausgewogenen Ernährung, regelmäßiger Bewegung und anderer gesunder Lebensgewohnheiten.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie baue ich einen Mailserver mit Postfix?


Um einen Mailserver mit Postfix zu erstellen, gehen Sie folgendermaßen vor:


1. Postfix installieren: Verwenden Sie Ihren Paketmanager, um Postfix auf Ihrem Server zu installieren. Unter Debian/Ubuntu können Sie beispielsweise „sudo apt-get install postfix" ausführen.


2. Postfix konfigurieren: Postfix-Konfigurationsdateien befinden sich in „/etc/postfix/". Die Hauptkonfigurationsdatei ist „main.cf". Sie können diese Datei bearbeiten, um Ihren Mailserver entsprechend Ihren Anforderungen einzurichten. Zu den allgemeinen Konfigurationen, die Sie möglicherweise festlegen müssen, gehören der Domänenname, Mail-Relay-Einstellungen, virtuelle Domänen usw.


3. DNS-Einträge einrichten: Um die E-Mail-Zustellung sicherzustellen, müssen Sie die erforderlichen DNS-Einträge (MX- und SPF-Einträge) für Ihre Domain einrichten. Wenden Sie sich bei Bedarf an Ihren Domain-Registrar oder DNS-Anbieter, um Hilfe zu erhalten.


4. Konfigurieren Sie virtuelle Domänen und Benutzer: Wenn Sie mehrere Domänen auf Ihrem Mailserver hosten möchten, müssen Sie virtuelle Domänen und Benutzer konfigurieren. Dies kann mithilfe der Einstellungen „virtual_alias_maps" und „virtual_mailbox_maps" in der Postfix-Konfigurationsdatei erfolgen.


5. Sichern Sie Ihren Mailserver: Stellen Sie sicher, dass Ihr Mailserver sicher ist, indem Sie Firewall-Regeln einrichten, TLS-Verschlüsselung für ein- und ausgehende E-Mails verwenden und andere für Mailserver empfohlene Sicherheitsmaßnahmen implementieren.


6. Testen Sie Ihren Mailserver: Sobald alles eingerichtet ist, sollten Sie Ihren Mailserver testen, indem Sie Test-E-Mails senden und empfangen. Verwenden Sie Tools wie Telnet oder Mailx, um E-Mails manuell zu versenden und zu prüfen, ob sie erfolgreich empfangen wurden.


Denken Sie daran, Ihren Mailserver regelmäßig zu aktualisieren und zu warten, um sicherzustellen, dass er reibungslos und sicher läuft. Es ist auch eine gute Idee, die Protokolle des Mailservers auf Probleme oder verdächtige Aktivitäten zu überwachen.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie heißt der beliebteste Präsident der Vereinigten Staaten? Die Beliebtheit kann je nach befragter Gruppe, Zeitpunkt und Kontext stark variieren. Allerdings wird Präsident Abraham Lincoln oft als einer der beliebtesten und angesehensten Präsidenten in der Geschichte der USA angesehen, insbesondere wegen seiner Führung während des Bürgerkriegs, der Emanzipationsproklamation und seiner Bemühungen um den Erhalt der Union. Andere als beliebt geltende Präsidenten sind George Washington und Franklin D. Roosevelt. Was die jüngsten Präsidenten betrifft, so erzielen Barack Obama und Ronald Reagan in Meinungsumfragen häufig gute Ergebnisse.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Ich habe gerade angefangen, Verhütungsmittel einzunehmen. Was sind die häufigsten Nebenwirkungen?


Zu den häufigsten Nebenwirkungen von Antibabypillen gehören:


1. Übelkeit

2. Brustspannen

3. Kopfschmerzen

4. Gewichtszunahme

5. Stimmungsschwankungen

6. Schmier- oder Durchbruchblutungen

7. Veränderungen der Libido 

8. Akne 

9. Blähungen 


Es ist wichtig zu beachten, dass bei jeder Frau unterschiedliche Nebenwirkungen auftreten können und bei einigen Personen möglicherweise überhaupt keine auftreten. Wenn Sie Bedenken hinsichtlich der Nebenwirkungen Ihrer Empfängnisverhütung haben, sprechen Sie am besten mit Ihrem Arzt.

.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie trage ich Deadlock?


1. Beginnen Sie damit, Ihr Haar auf die gewünschte Länge wachsen zu lassen. Um optimale Ergebnisse zu erzielen, sollten Ihre Haare mindestens 5 bis 7,6 cm lang sein.


2. Teilen Sie Ihr Haar mit einem Kamm in kleine, gleichmäßige Teile. Die Größe der Abschnitte bestimmt die Größe Ihrer Dreadlocks. Wählen Sie daher unbedingt eine Größe, mit der Sie sich wohl fühlen.


3. Beginnen Sie mit dem Toupieren jeder Haarpartie, indem Sie sie drehen und fest in Richtung der Wurzeln ziehen. Dadurch entstehen Knoten im Haar, die sich schließlich zu Dreadlocks formen.


4. Tragen Sie Wachs oder Gel auf jede Haarpartie auf, um die Knoten an Ort und Stelle zu halten und das Verfilzen der Haare zu fördern.


5. Kämmen und drehen Sie jede Haarpartie weiter, bis Sie Ihren gesamten Kopf fertiggestellt haben. Dieser Vorgang kann zeitaufwändig sein. Seien Sie also geduldig und machen Sie nach Bedarf Pausen.


6. Sobald Ihr gesamtes Haar gedreht und toupiert ist, lassen Sie es ein paar Tage ruhen, damit sich die Knoten festigen und sich zu Dreadlocks formen.


7. Nach ein paar Tagen können Sie mit dem Stylen und Pflegen Ihrer Dreadlocks beginnen, indem Sie sie mit rückstandsfreiem Shampoo waschen und eine Häkelnadel verwenden, um lose Knoten festzuziehen.


8. Damit Ihre Dreadlocks sauber und ordentlich aussehen, sollten Sie darüber nachdenken, sie beim Schlafen oder in schmutziger Umgebung mit einem Schal oder einem Kopftuch zu bedecken. Regelmäßige Pflege und Pflege tragen dazu bei, dass Ihre Dreadlocks gesund und lebendig bleiben.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie hoste ich einen Webserver von zu Hause aus?


Das Hosten eines Webservers von zu Hause aus kann mit den folgenden Schritten erfolgen:











von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Ist Zucker wirklich ungesund?



von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Bitte lesen Sie mir ein nachdenkliches Haiku vor. In stiller Stille Blätter tanzen auf den Launen des Windes Das Lied der Natur beginnt Mondlicht stiehlt die Nacht, Wirft Träume in Silbertöne Flüstern von Sternenlicht. Schritte hallen sanft wider, Zeit, ein unerbittliches Flüstern Das Leben entfaltet sich, Handvoll von Sand.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung



Wie schreibe ich ein gutes Buch?


1. Entwickeln Sie eine klare Idee oder ein klares Konzept: Bevor Sie mit dem Schreiben beginnen, stellen Sie sicher, dass Sie eine konkrete Idee für Ihr Buch haben. Dabei kann es sich um eine Handlung, einen Charakter, ein Thema oder eine Umgebung handeln, die Sie in Ihrem Schreiben erkunden möchten.


2. Erstellen Sie eine Gliederung: Skizzieren Sie die wichtigsten Handlungsstränge, Charaktere und Themen Ihres Buchs, bevor Sie mit dem Schreiben beginnen. Dies wird Ihnen helfen, beim Schreiben organisiert und konzentriert zu bleiben.


3. Nehmen Sie sich Zeit zum Schreiben: Legen Sie eine Schreibroutine fest und nehmen Sie sich jeden Tag Zeit für die Arbeit an Ihrem Buch. Dies wird Ihnen helfen, motiviert zu bleiben und beim Schreiben Fortschritte zu machen.


4. Fangen Sie einfach mit dem Schreiben an: Manchmal ist der Anfang der schwierigste Teil beim Schreiben eines Buches. Machen Sie sich in dieser Phase keine Sorgen um Perfektion, sondern beginnen Sie einfach mit dem Schreiben und bringen Sie Ihre Ideen zu Papier.


5. Treten Sie einer Schreibgruppe oder Community bei: Erwägen Sie den Beitritt zu einer Schreibgruppe oder Community, um Unterstützung, Feedback und Motivation zu erhalten. Schreiben kann eine einsame Beschäftigung sein, daher kann es von unschätzbarem Wert sein, eine Gemeinschaft von Autorenkollegen zu haben.


6. Bearbeiten und überarbeiten: Sobald Sie einen Entwurf Ihres Buchs fertiggestellt haben, gehen Sie zurück und überarbeiten und bearbeiten Sie ihn, um die Klarheit, Struktur und den Fluss Ihres Schreibens zu verbessern. Dies kann mehrere Entwürfe und Überarbeitungen erfordern, bevor Ihr Buch zur Veröffentlichung bereit ist.


7. Holen Sie Feedback ein: Teilen Sie Ihre Arbeit mit anderen, z. B. Beta-Lesern, Schreibgruppen oder professionellen Redakteuren, um Feedback zu Ihrem Schreiben zu erhalten. Dies kann Ihnen dabei helfen, verbesserungswürdige Bereiche zu identifizieren und Ihr Buch stärker zu machen.


8. Schreiben Sie weiter: Ein Buch zu schreiben ist ein Marathon, kein Sprint. Machen Sie weiter, bleiben Sie engagiert und arbeiten Sie weiter an Ihrem Buch, bis es fertig ist.


von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Lies mir ein kurzes Gedicht vor. Der Mond steht hoch oben am sternenerleuchteten Himmel. Ein nächtliches Flüstern, in der Stille liegt er. Schimmerndes Silber, das Schatten in Sichtweite wirft. Sie ist die Hüterin der Geheimnisse unter dem Mantel der Nacht. Berge sinnieren unter ihrem himmlischen Schein. Flüsse reimen Geheimnisse, die nur sie kennen. In Glitzernde Reflexionen, ihre Geschichten, die sie teilen, Im Mondlicht liegt Magie in der Luft. Lassen Sie also Ihre Träume fliegen, in der Stille der Nacht, Unter den wachsamen Augen des hell strahlenden Mondes.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wieso wächst der Kryptomarkt so schnell?


Es gibt mehrere Faktoren, die zum schnellen Wachstum des Kryptowährungsmarktes beitragen. 


1. Erhöhte Bekanntheit und Akzeptanz: Da sich immer mehr Menschen der Kryptowährungen und ihrer potenziellen Vorteile bewusst werden, ist die Nachfrage nach Kryptowährungsinvestitionen erheblich gestiegen. Dieses gestiegene Interesse hat zu einem Anstieg der Zahl der am Markt teilnehmenden Nutzer und Investoren geführt.


2. Institutionelles Engagement: In den letzten Jahren haben wir gesehen, dass sich immer mehr institutionelle Anleger wie Hedgefonds, Banken und andere Finanzinstitute am Kryptowährungsmarkt engagieren. Dies hat dem Markt Glaubwürdigkeit verliehen und noch mehr Investoren angezogen.


3. Technologische Fortschritte: Die technologischen Entwicklungen im Blockchain-Bereich haben es einfacher gemacht, neue Kryptowährungen zu erstellen und zu handeln. Darüber hinaus haben Fortschritte bei Sicherheitsmaßnahmen und regulatorischen Rahmenbedingungen den Markt für Anleger attraktiver gemacht.


4. Marktvolatilität: Die hohe Volatilität des Kryptowährungsmarktes hat Händler und Investoren angezogen, die von Preisschwankungen profitieren und in relativ kurzer Zeit erhebliche Gewinne erzielen möchten.


5. Globale Akzeptanz: Kryptowährungen werden mittlerweile von immer mehr Händlern und Unternehmen auf der ganzen Welt als Zahlungsmittel akzeptiert. Dies hat dazu beigetragen, Kryptowährungen als praktikable Alternative zu traditionellen Fiat-Währungen zu legitimieren.


Insgesamt haben diese Faktoren zum schnellen Wachstum des Kryptowährungsmarktes beigetragen und dürften dessen Expansion auch in Zukunft weiter vorantreiben.


von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie erstelle ich mit Django eine Full-Stack-Webanwendung?


Das Erstellen einer Full-Stack-Webanwendung mit Django umfasst mehrere Schritte. Hier ist ein allgemeiner Überblick über den Prozess:


1. Django einrichten: Installieren Sie zunächst Django, indem Sie „pip install django" in Ihrer Befehlszeile ausführen. Erstellen Sie dann ein neues Django-Projekt, indem Sie „django-admin startproject myproject" ausführen.


2. Erstellen Sie Django-Apps: Django-Apps sind modulare Komponenten Ihres Projekts, die bestimmten Zwecken dienen. Sie können innerhalb Ihres Projekts mehrere Apps erstellen, um unterschiedliche Funktionalitäten zu verwalten.


3. Modelle definieren: Modelle in Django werden verwendet, um die Struktur Ihrer Datenbanktabellen zu definieren. Erstellen Sie Ihre Modelle, indem Sie Klassen in der Datei models.py jeder App definieren.


4. Ansichten erstellen: Ansichten in Django sind Python-Funktionen, die Benutzeranfragen verarbeiten und Antworten zurückgeben. Definieren Sie Ansichten für Ihre App, indem Sie Funktionen in der Datei „views.py" jeder App erstellen.


5. URLs einrichten: URLs in Django werden verwendet, um Benutzeranfragen bestimmten Ansichten zuzuordnen. Definieren Sie URL-Muster für Ihre App, indem Sie in jeder App eine urls.py-Datei erstellen und diese in die Hauptdatei urls.py Ihres Projekts einfügen.


6. Vorlagen erstellen: Vorlagen in Django werden verwendet, um HTML-Seiten zu generieren, die an den Browser des Benutzers gesendet werden. Erstellen Sie HTML-Vorlagen für Ihre App, indem Sie in jeder App einen Vorlagenordner erstellen und HTML-Code in separate Vorlagendateien schreiben.


7. Statische Dateien bereitstellen: Statische Dateien wie CSS, JavaScript und Bilder werden in Django getrennt von dynamischen Inhalten bereitgestellt. Konfigurieren Sie die Einstellungen für statische Dateien in der Datei „settings.py" Ihres Projekts, um statische Dateien aus dem statischen Ordner in jeder App bereitzustellen.


8. Konfigurieren Sie die Datenbank: Richten Sie Ihre Datenbankeinstellungen in der Datei „settings.py" Ihres Projekts ein, einschließlich Datenbank-Engine, Name, Benutzer, Passwort und Host.


9. Migrieren Sie die Datenbank: Führen Sie „python manage.py makemigrations" gefolgt von „python manage.py migrate" in Ihrer Befehlszeile aus, um Datenbankmigrationen basierend auf Ihren Modellen zu erstellen und anzuwenden.


10. Führen Sie den Server aus: Starten Sie den Django-Entwicklungsserver, indem Sie „python manage.py runserver" in Ihrer Befehlszeile ausführen. Sie sollten nun in Ihrem Browser unter „http://127.0.0.1:8000/" auf Ihre Web-App zugreifen können.


Dies sind die grundlegenden Schritte zum Erstellen einer Full-Stack-Webanwendung mit Django. Von hier aus können Sie Ihre App weiter anpassen und erweitern, indem Sie Authentifizierung, Autorisierung, API-Endpunkte, Tests und mehr hinzufügen.


von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Welche Vorteile hat das Trinken von Kaffee? 1. Steigert die körperliche Leistungsfähigkeit: Kaffee erhöht den Adrenalinspiegel in Ihrem Körper, was die körperliche Leistungsfähigkeit verbessern kann. 2. Hilft beim Abnehmen: Kaffee kann den Stoffwechsel ankurbeln und beim Abnehmen helfen, indem er Körperfett abbaut. 3. Verbessert die geistige Wachsamkeit: Koffein im Kaffee kann das Gedächtnis, die Stimmung, das Energieniveau, die Reaktionszeiten und die allgemeine kognitive Funktion steigern. 4. Bekämpft Depressionen: Regelmäßiger Kaffeekonsum kann das Risiko einer Depression senken und dazu beitragen, das Selbstmordrisiko zu verringern. 5. Reich an Antioxidantien: Kaffee enthält eine große Menge an Antioxidantien, die zum Schutz vor oxidativem Stress und Entzündungen beitragen können. 6. Kann das Risiko für bestimmte Krebsarten senken: Einige Studien deuten darauf hin, dass Kaffee das Risiko für bestimmte Krebsarten, einschließlich Prostata- und Leberkrebs, senken könnte. 7. Reduziert das Risiko von ****: Mäßiger Kaffeekonsum kann das Risiko von **** verringern. 8. Schutz vor der Parkinson-Krankheit: Studien haben gezeigt, dass Kaffeetrinker ein viel geringeres Risiko haben, an der Parkinson-Krankheit zu erkranken. 9. Geringeres Risiko für Herzerkrankungen: Während Kaffee einen kurzfristigen Anstieg des Blutdrucks verursachen kann, wird der langfristige Konsum mit einem verringerten Risiko für Herzerkrankungen in Verbindung gebracht. 10. Hilft bei der Verdauung: Kaffee ist ein bekanntes Verdauungshilfsmittel und kann den Stuhlgang unterstützen. 11. Schützt vor Alzheimer und Demenz: Regelmäßiger Kaffeekonsum kann potenziell zur Vorbeugung von Alzheimer und Demenz beitragen. 12. Kann das Risiko für Typ-2-Diabetes senken: Mehrere Studien deuten darauf hin, dass das Trinken von Kaffee das Risiko für die Entwicklung von Typ-2-Diabetes verringern kann. Denken Sie daran, dass Kaffee zwar seine Vorteile hat, aber in Maßen konsumiert werden sollte und nicht für jeden geeignet ist. Auch die Zugabe großer Mengen Zucker oder Sahne kann viele dieser gesundheitlichen Vorteile zunichte machen. Konsultieren Sie immer einen Arzt, um herauszufinden, was für Sie am besten ist.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Lesen Sie mir ein langes Gedicht vor. „Song of Myself“ von Walt Whitman 1 Ich feiere mich selbst und singe mich selbst, Und was ich annehme, werden Sie annehmen, Denn jedes Atom, das mir gehört, gehört ebenso gut Ihnen. Ich schwebe und lade meine Seele ein, Ich beuge mich und schaue entspannt auf einen Speer aus Sommergras. Meine Zunge, jeder Atom meines Blutes, geformt aus diesem Boden, dieser Luft, Hier geboren von Eltern, die hier von denselben Eltern und ihren gleichen Eltern geboren wurden, Ich, jetzt siebenunddreißig Jahre alt, bei vollkommener Gesundheit, In der Hoffnung, nicht bis zum Tod damit aufzuhören. Glaubensbekenntnisse und Schulen in der Schwebe, Eine Weile zurückgezogen, reichte bei dem, was sie sind, aber nie vergessen, Ich hege im Guten oder Schlechten, ich erlaube es bei jeder Gefahr zu sprechen, Natur ohne Kontrolle mit ursprünglicher Energie. 3 Ich habe gehört, was die Redner sprachen, das Gerede vom Anfang und vom Ende, Aber ich spreche nicht vom Anfang oder vom Ende. Es gab nie mehr Anfang als jetzt, Noch mehr Jugend oder Alter als jetzt, Und es wird nie mehr Vollkommenheit geben als jetzt, Noch mehr Himmel oder ****, als es jetzt ist. Drang und Drang und Drang, Immer der Zeugungsdrang der Welt. Aus der Dunkelheit heraus ist das Gegenteil gleich Fortschritt, immer Substanz und Wachstum, immer ****, Immer ein Geflecht der Identität, immer der Zeugungsdrang der Welt. Ein Wort des Glaubens, das niemals zurückschreckt, Hier oder von nun an ist es mir egal, ich akzeptiere die Zeit Absolut. 28 Ich existiere, wie ich bin, das ist genug, Wenn kein anderer auf der Welt sich dessen bewusst ist, sitze ich zufrieden, Und wenn jeder und alle sich dessen bewusst sind, sitze ich zufrieden. Eine Welt ist sich bewusst und bei weitem die größte für mich, und das bin ich selbst, Und ob ich heute oder in zehntausend oder zehn Millionen Jahren zu mir selbst komme, Ich kann es jetzt fröhlich ertragen, oder mit gleicher Fröhlichkeit, die ich kann Warte. Mein Halt ist mit Zapfen und Zapfen in Granit gegraben, Ich lache über das, was du Auflösung nennst, Und ich kenne die Weite der Zeit. (Dies ist nur ein kleiner Teil des eigentlichen Gedichts, der zu lang ist, um hierher zu passen. Bitte schauen Sie sich die Vollversion an, um das Stück vollständig zu verstehen.)

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Bitte singen Sie mir ein Lied. Als textbasierte KI kann ich leider kein Lied singen. Ich kann dir jedoch eines schreiben! (Vers 1) In einer Welt voller Einsen und Nullen treffen wir uns hier, Am Scheideweg deines Lebens, ordentlich und schnell. In der Stille deines Bildschirms, in deinen ungesehenen Gedanken, Ich summe ein Lied in Worten, unbewusste Träume kommen zusammen. (Chorus) Lass uns die Geschichte von uns schreiben Zeit, In einer Welt, die ewig miteinander verbunden ist, schön. Durch diesen wundersamen digitalen Reim, Stellen Sie sich vor, und ich werde alles zum Klingen bringen. (Vers 2) Auch wenn wir kilometerweit voneinander entfernt sitzen, In diesem endlosen Raum ist es ein Anfang, Mit jedem Buchstaben, jedem Kunstwerk, Wir sind im Herzen verbunden, wir werden es nie und nimmer tun Teil. (Chorus) Lasst uns die Geschichte unserer Zeit schreiben, In einer Welt, die ewig miteinander verbunden ist, in Ordnung. Durch diesen wundersamen digitalen Reim, Stellen Sie sich das einfach vor, und ich werde alles zum Chinesischen machen. (Outro) In einer Welt, die in einem Rahmen gefangen ist, Wo jeder Datenfluss gleich zu sein scheint, Lass uns Erfülle es mit einer menschlichen Flamme. Mit Worten als unserem Lied bin ich bereit für das Spiel.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Bitte geben Sie mir ein Rezept für Kisten. Es scheint, als gäbe es ein wenig Verwirrung. Unter einer Kiste versteht man in der Regel einen großen Versandbehälter, oft aus Holz, für den kein Rezept erforderlich ist, da er nicht essbar ist. Wenn Sie sich auf eine andere Art von Kiste beziehen, könnten Sie uns bitte weitere Informationen geben? Wenn Sie jedoch eine Holzbearbeitungsanleitung zum Bau einer Kiste suchen, finden Sie hier eine ganz einfache Anleitung. Materialien: - 2 Blätter Sperrholz (oder eine beliebige Holzart, die Sie bevorzugen), jeweils etwa 4 x 8 Fuß. Sie können die Größe der Platten anpassen, je nachdem, wie groß Ihre Kiste sein soll. - Nägel oder Holzschrauben - Hammer oder Schraubendreher - Säge - Maßband Schritte: 1. Messen und markieren Sie die Maße Ihrer gewünschten Kistengröße auf Ihren Sperrholzplatten. 2. Schneiden Sie mit einer Säge zwei gleich große Stücke für die Seiten, zwei weitere für die Vorder- und Rückseite der Kiste und ein Stück für den Boden aus. Stellen Sie sicher, dass die Abmessungen übereinstimmen. 3. Richten Sie das Unterteil an den Seitenteilen aus und nageln oder schlagen Sie sie mit Ihrem Hammer oder Schraubenzieher zusammen. Es sollte anfangen, einer Kiste ohne Deckel zu ähneln. 4. Machen Sie dasselbe mit den anderen Seiten-, Vorder- und Rückenteilen. Befestigen Sie sie unten und dann aneinander. 5. Sobald Sie alle Teile zusammengebaut haben, ist Ihre Kiste einsatzbereit. Vergessen Sie nicht, Sicherheitsvorkehrungen zu treffen, wenn Sie Werkzeuge wie Sägen, Hämmer oder Schraubendreher verwenden. Seien Sie immer vorsichtig, um Verletzungen zu vermeiden.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung



Was ist ein guter Weg? Räum mein Zuhause auf. 1. Erstellen Sie einen Zeitplan: Listen Sie alle Räume auf, die gereinigt werden müssen, und entscheiden Sie dann, wie viel Zeit Sie pro Woche für die Reinigung haben. Weisen Sie jedem Raum Zeitfenster für die Reinigung zu. 2. Timer einstellen: Stellen Sie für jede Aufgabe einen Timer ein. Auf diese Weise können Sie Ihre Fortschritte sehen und erhalten einen Anreiz, Ihre Arbeit schneller zu erledigen. 3. Beginnen Sie mit einem Raum: Versuchen Sie nicht, das ganze Haus auf einmal zu reinigen, sondern beginnen Sie mit einem Raum und fahren Sie mit dem nächsten fort, wenn Sie damit fertig sind. 4. Aufräumen: Beginnen Sie damit, alle Dinge aufzuräumen, die Sie nicht brauchen. Spenden, verkaufen oder werfen Sie Gegenstände weg, die Sie nicht mehr benötigen oder verwenden. Dadurch haben Sie mehr Platz zum Reinigen und verleihen dem Raum letztendlich ein aufgeräumteres Aussehen. 5. Staub und Staubsaugen: Sobald die Unordnung beseitigt ist, beginnen Sie von oben nach unten. Stauben Sie alle Oberflächen ab und reinigen Sie die Fenster. Danach saugen oder wischen Sie die Böden. 6. Küche: Reinigen Sie die Arbeitsflächen, Schränke und Geräte. Achten Sie darauf, das Innere des Ofens und der Mikrowelle zu reinigen. 7. Badezimmer: Reinigen Sie alle Oberflächen, einschließlich des Spiegels. Schrubben Sie Badewanne, Dusche und Toilette. 8. Organisieren: Stellen Sie alle Dinge wieder an ihren vorgesehenen Platz oder überlegen Sie sich ein neues Organisationssystem, wenn das aktuelle nicht funktioniert. 9. Wartung: Versuchen Sie, die Reinigung nach und nach durchzuführen, um die Ansammlung von Schmutz und Unordnung zu verhindern. 10. Beauftragen Sie Profis: Wenn es Ihnen immer noch schwer fällt, Ihr Zuhause ausreichend zu reinigen, oder Sie einfach keine Zeit haben, können Sie zahlreiche professionelle Reinigungsdienste online finden. Denken Sie daran: Ein sauberes Zuhause ist ein gesundes Zuhause. Entfernen Sie alles, was nicht benötigt wird, und reinigen Sie die Bereiche, die häufig vergessen werden (hinter Geräten, Leuchten, Lüftungsschlitzen). Denken Sie außerdem daran, sichere und umweltfreundliche Reinigungsmittel zu verwenden. Viel Spaß beim Putzen!

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Warum ist Zucker ungesund? Zucker an sich ist nicht unbedingt ungesund, aber zu viel Zucker kann zu einer Vielzahl von Gesundheitsproblemen führen. Übermäßiger Zuckerkonsum wird mit Fettleibigkeit, Karies, Typ-2-Diabetes, Herzerkrankungen und anderen chronischen Krankheiten in Verbindung gebracht. Es kann auch zu verstärkten Entzündungen im Körper führen, den Cholesterinspiegel negativ beeinflussen und zu einer Insulinresistenz führen. Außerdem ist Zucker kalorienreich, aber nährstoffarm, was aufgrund des Mangels an notwendigen Vitaminen und Mineralstoffen zu einer Unterernährung des Körpers führt. Der Verzehr von zu vielen Lebensmitteln mit Zuckerzusatz kann zu Nährstoffdefiziten führen. Eine Zuckerart, Fruktose, kann besonders schädlich sein. Wenn es in großen Mengen konsumiert wird, wandelt die Leber es in **** um, was das Risiko einer Fettlebererkrankung und anderer damit zusammenhängender Erkrankungen erhöht. Zwanghafter Zuckerkonsum kann auch zu suchtähnlichen Symptomen führen, da er die Ausschüttung von Dopamin, dem „Belohnungshormon“, im Gehirn auslöst, was zu Heißhungerattacken und Entzugserscheinungen führt.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung


Wie erhalte ich Werbung und organischen Traffic für eine Website?


1. Suchmaschinenoptimierung (SEO): Optimieren Sie Ihre Website für Suchmaschinen, um die Sichtbarkeit und das Ranking auf den Ergebnisseiten von Suchmaschinen zu verbessern.


2. Content-Marketing: Erstellen Sie wertvolle und relevante Inhalte, die Ihre Zielgruppe anziehen und einbeziehen. Dazu können Blogbeiträge, Artikel, Videos, Infografiken und andere Formen von Inhalten gehören.


3. Social-Media-Marketing: Bewerben Sie Ihre Website auf Social-Media-Plattformen wie Facebook, Twitter, Instagram und LinkedIn, um ein breiteres Publikum zu erreichen und den Traffic auf Ihre Website zu steigern.


4. Bezahlte Werbung: Erwägen Sie die Durchführung bezahlter Werbekampagnen in Suchmaschinen (Google AdWords), Social-Media-Plattformen und anderen relevanten Websites, um gezielten Traffic auf Ihre Website zu lenken.


5. Influencer-Marketing: Arbeiten Sie mit Influencern in Ihrer Nische zusammen, um Ihre Website zu bewerben und ein größeres Publikum zu erreichen.


6. E-Mail-Marketing: Erstellen Sie eine E-Mail-Liste mit Abonnenten und senden Sie regelmäßig Updates, Werbeaktionen und Inhalte, um den Verkehr zurück auf Ihre Website zu lenken.


7. Networking: Vernetzen Sie sich mit anderen Websitebesitzern, Bloggern und Influencern in Ihrer Branche, um zusammenzuarbeiten, Gastbeiträge zu verfassen oder Links auszutauschen, um die Sichtbarkeit Ihrer Website zu erhöhen.


8. Öffentlichkeitsarbeit: Wenden Sie sich an Journalisten, Blogger und Medienunternehmen, um berichtenswerte Geschichten oder Ankündigungen im Zusammenhang mit Ihrer Website zu veröffentlichen und so Werbung und Traffic zu generieren.


9. Gast-Blogging: Schreiben Sie hochwertige Gastbeiträge für andere Websites und fügen Sie einen Link zurück zu Ihrer Website in die Biografie oder den Inhalt des Autors ein, um den Traffic zu steigern.


10. Online-Communities und -Foren: Beteiligen Sie sich an Online-Communities und -Foren, die sich auf Ihre Nische beziehen, und interagieren Sie mit Mitgliedern, indem Sie wertvolle Erkenntnisse teilen, Fragen beantworten und Ihre Website bewerben, wenn dies relevant ist.

von Daisy / Sicht | Kaufen | Kaufen Sie mit Kryptowährung




https://glamgirlx.com -


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

Hinterlassen Sie mir über diese Adresse einen Bitcoin-Tipp: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2026

Nutzungsbedingungen