Praktisch webgebaseerd diep leren en beveiliging als voorbeeld

Daisy's Profielfoto

Door Daisy

Praktisch webgebaseerd diep leren en beveiliging bij voorbeeld Derde editie Charlotte Harper 3 juli 2024 Voorwoord: Beveiligingsoverwegingen in het bouwen van software voor internet zijn een belangrijk onderdeel van het plan en de uitvoering van elke webontwikkelaar, terwijl een prototype engineering van een prototype dat betrouwbaar, stabiel en nuttig is voor praktische doeleinden. De DOM (documentobjectmarkering), met de implementatie van HTML, JavaScript en CSS, evenals backend -software die Python, C/C ++, Java en Bash implementeert, geven webontwikkelaars de vrijheid en macht om een ​​breed scala aan projecten te creëren die een breed scala aan projecten creëren die een breed scala aan projecten creëren die een breed scala aan projecten creëren die uitdrukkelijk zijn Creativiteit, zorg gemak van gebruik en functionaliteit, portretteren nederigheid en karakter en bieden gebruiksgemak, evenals gemak en belangrijke diensten die allemaal aantrekkelijk zijn voor de gemiddelde Joe, de eindgebruiker die tijd wil doden of iets op internet wil doen, Meestal op een touchscreen -smartphone -apparaat. De meeste mensen zouden niet eens weten waar ze moeten beginnen als ze een website helemaal opnieuw willen bouwen,Ze zouden de neiging hebben om op de website van een ander te beginnen en iets te bouwen dat beperkt is in functionaliteit, betrouwbaarheid, gebruiksgemak en vooral creativiteit wanneer ze de nieuwste krachtige tools tot hun beschikking hadden kunnen hebben om iets nuttigs te bouwen zonder tijd te drukken op knoppen, en Vooral het verspillen van geld dat betalen voor dure abonnementen op software die maar weinig mensen wilden gebruiken, gezien de beperkingen van het gemak en flexibiliteit. Als je een paar minuten hebt om dit boek te lezen en te leren wat ik je wil leren, of zelfs met mij persoonlijk over je doelen wil praten en wat begeleiding in de goede richting krijgt, en gemotiveerd zijn om te leren coderen en te schrijven van je eigen software , neem dit boek mee naar huis en zet wat tijd opzij om te leren de volgende invloedrijke, krachtige, gestroomlijnde en belangrijke webapplicatie te bouwen, een website die allemaal op u staat en precies doet wat u wilt en voldoet aan de behoeften van uw publiek. Over mij: Ik ben een softwareontwikkelaar met een bredeAnge of Experience in C/C ++, Java, Python, HTML, CSS en JavaScript. Ik bouw websites die mensen willen gebruiken, willen bezoeken en zelfs verslaafd raken aan het gebruik alleen om tijd te leren, te herscheppen en te doden, en vooral, ik verkoop software. Als je een idee had om precies hoe je wilde dat een website eruit zou zien en functioneerde, was je bereid me te ondersteunen zodat ik aan mijn eigen behoeften kan voldoen terwijl ik de jouwe ontmoet, en je bent bereid om de kosten van het runnen van een website zelf te dekken, Ik zou je de volgende YouTube, Tiktok, Twitter, Google of zelfs een hightech-beveiligings-app bouwen die je toegang hebt. In plaats van te proberen je mijn tijd te verkopen, probeer ik de jouwe te kopen: ik wil je er zelf over hebben om een ​​app (website) te bouwen met de informatie die al bestaat, en je te leren wat je nodig hebt om een ​​onafhankelijke softwareontwikkelaar te zijn, Ondernemer, die een succesvolle carrière leidt op het gebied dat je wenst. En laat me duidelijk zijn, de opleiding die ik je geef, zal informeel zijn. Je zou naar school kunnen gaan en dit allemaal leren met eenRMAL -onderwijs, of lees dit boek zelfs op school, voltooi uw opdrachten en neemt veel weg van uw opleiding, maar ik zal u niet formeel in de hot -stoel zetten en u vragen om opdrachten te voltooien. Ik ben niet je professor, je kunt aan mij denken als een vriend die je wil begeleiden naar een carrière gedreven door je eigen persoonlijke succes. En ik verkoop je succes ook niet, je moet het met je tijd kopen. Leren te coderen heeft een steile leercurve en was nooit gemakkelijk, of zou zelfs moeten zijn. Je moet zo hard werken als je kunt en blijven proberen te falen en opnieuw te proberen, zelfs als je gefrustreerd bent om zelf apps te leren en te bouwen. Dat is in de aard van de code zelf. Code wordt uitgevoerd door een compiler die is ontworpen om de programmeerfoutmeldingen te geven, en deze zullen u leren hoe u moet coderen, zelfs als u de fout eenvoudigweg in uw zoekmachine kopieert en de voorbeelden van andere mensen leest. En ik moet zeggen, je hoeft niet extreem rijk, slim, succesvol te zijn,en detailgericht of georganiseerd om een ​​app te bouwen. De computer zorgt voor die organisatie voor u. Je hoeft alleen maar door de vallen en opstaan ​​te volharden, de focus te behouden en hard te werken aan wat je doet, en je zult een zeer succesvolle carrière hebben in het geheel van wat je doet. Wie ik ben: Ik realiseer me dat het laatste deel meer ging over leren en je neemt een manier uit dit boek. Wie ben ik precies? Dat is een ingewikkelde vraag. Ik ben daar zelf onduidelijk over, omdat ik last heb van medische aandoeningen die het voor mij moeilijk kunnen maken om dit boek soms te coderen of te schrijven, terwijl ik uitdagingen voor socialisatie- en identiteitsproblemen presenteert die mijn leven moeilijker maken als het gaat om het introduceren van mezelf . Kortom, als je dit boek leest, heb je het naar huis gebracht omdat je er doorheen bent gegooid en dacht dat het nuttig was, of zelfs als je net zo ver in leest, ben ik een gelijkgestemde persoon die je wil zien slagen Alles wat je doet. Ik ben zelf een ingenieur, een softwareontwikkelaar, en een student, en ik schrijf dit boek voor andere studenten die hun leven gemakkelijker willen maken door een handboek te hebben van de software die ze nodig hebben om hun leven gemakkelijker te maken door voorbeelden te geven die in elkaar passen als een grote puzzel in een werk , nuttige, grote, functionele, samenhangende en boeiende app die succes kan stimuleren, ongeacht de bedrijfslijnen. Grotendeels, dit is wat ik doe: ik bouw apps om mezelf en andere mensen te helpen slagen. Ik ben ook een auteur, hoewel dit mijn eerste publicatie is die ik van plan ben te voltooien om mijn portfolio samen te stellen in een nuttig document, en ik ben ook een kunstenaar. Ik zal je dit toegeven, ik ben een soort vreemd persoon. Ik ben niet perfect, ik heb de wet gehad met de wet, zelfs ertoe leiden dat ik hogescholen en universiteiten verlaten en staten verlaten om te proberen een naam voor mezelf te maken met meer succes. Ik ben een vrouw van geboorte, ik draag make -up, maak foto's van mezelf, draag jurken en andere dameskleding, en ik blijf me bewust van mezelf als eenman van nature. Ik heb in het verleden problemen gehad met andere mensen die hebben geleid tot worstelingen met het schrijven en bouwen van webapps, en ik bied mijn excuses aan dat ik dit boek niet eerder in handen heb kunnen krijgen: je had dit nodig. Je wilt code lezen en schrijven die op de mijne lijkt en werkt als de mijne en hetzelfde doet, maar nog beter, want als je het je kunt veroorloven om dit boek te kopen in plaats van je toetsenbord te pureren zoals ik gewoon een boek maakt om zelf een boek te maken. Daarvoor heb je de middelen die je nodig hebt om succesvol te zijn in je leven. Ik had allerlei problemen met het opgroeien van familie, gezondheidstoestand, artsen, de media en de wet, en mijn code weerspiegelt diep de strijd die feminisme en vrouwelijke natuur is in een verdeelde en gefrustreerde wereld. Dit boek is echter iets waar ik diep om geef, mijn baby, mijn portfolio en mijn levensonderhoud, dus ik waardeer je overweging wanneer je de tekst naar huis neemt en er zorgvuldig overheen porent om van mij te leren. Houd er rekening mee dat ik niet perfect ben,Boek zal fouten, revisies en nieuwe edities bevatten, en je moet zo goed mogelijk met je logische brein denken om een ​​succesvolle ervaring met mijn schrijven te hebben. Begrijp ook dat ik goed voor je bedoel, zelfs als je voor uitdagingen wordt geconfronteerd tijdens het schrijven. Denk er zo over na: als u gewoon een computersysteem kunt huren om alles te doen wat u zich kunt voorstellen in de digitale ruimte, alle informatie opslaat die u tegenkomt, #$%! Yze en organiseer het, en komt u begrijpen Onvermijdelijk moeilijkheden ondervinden met de informatie die u inneemt en zelfs publiceert. Ik vertel je dit omdat ik dezelfde moeilijkheden tegenkom. Gebruik dit boek op eigen risico, werk samen met uw community en communities die voor u beschikbaar zijn om software te bouwen binnen een veilige omgeving, en neem dingen niet persoonlijk aan wanneer u faalt of zelfs op de verkeerde manier slaagt: zo ben ik zo ver gekomen , en waarom ik je deze tekst kan meenemen en je kan helpen slagen zonder af te wekken op een pad van waanzin dat vertrektIk heb geruïneerd, gescheurd en gerafeld terwijl ik de gewone problemen tegenkomt die iedereen op wereldwijde schaal doet dankzij de paralellistische wereldwijde schaal van het netwerk waaraan we zullen werken, internet. Je bent misschien niet erg bekend met wie ik ben met slechts een paar woorden, maar ik moedig je aan om verder te lezen, je zult me ​​leren kennen terwijl je me blijft lezen en begrijpen tijdens het bouwen van je eigen projecten om je werk te voltooien. Er zal geen huiswerk zijn met dit boek, zolang uw professoren of leraren u geen enkele toewijzen, maar ik moedig u ten zeerste aan om zelf een portfolio van projecten te bouwen terwijl u leest, evenals een Capstone -project dat aantoont hoe u het kunt Pas toe wat je hebt geleerd. Mijn Capstone -project is de basis voor het grootste deel van wat je in dit boek gaat lezen, omdat het code van mijn vorige projecten bevat, code die ik heb gemaakt en geleerd om methodisch met de hand te schrijven, en een breed scala aan ideeën en tips die me hebben geholpen slagen tot het punt waarop ik een eenvoudige app kan draaien die isUlly uitgelicht en uiterlijk en gedraagt ​​zich als een populaire app die je je vriend of familie op internet kunt gebruiken, op internet, g...
Praktisch webgebaseerd diep leren en beveiliging als voorbeeld

Praktisch webgebaseerd diep leren en beveiliging bij voorbeeld Derde editie Charlotte Harper 3 juli 2024 Voorwoord: Beveiligingsoverwegingen in het bouwen van software voor internet zijn een belangrijk onderdeel van het plan en de uitvoering van elke webontwikkelaar, terwijl een prototype engineering van een prototype dat betrouwbaar, stabiel en nuttig is voor praktische doeleinden. De DOM (documentobjectmarkering), met de implementatie van HTML, JavaScript en CSS, evenals backend -software die Python, C/C ++, Java en Bash implementeert, geven webontwikkelaars de vrijheid en macht om een ​​breed scala aan projecten te creëren die een breed scala aan projecten creëren die een breed scala aan projecten creëren die een breed scala aan projecten creëren die uitdrukkelijk zijn Creativiteit, zorg gemak van gebruik en functionaliteit, portretteren nederigheid en karakter en bieden gebruiksgemak, evenals gemak en belangrijke diensten die allemaal aantrekkelijk zijn voor de gemiddelde Joe, de eindgebruiker die tijd wil doden of iets op internet wil doen, Meestal op een touchscreen -smartphone -apparaat. De meeste mensen zouden niet eens weten waar ze moeten beginnen wanneer ze een website willen bouwenScratch, ze zouden de neiging hebben om op de website van een ander te beginnen en iets te bouwen dat beperkt is in functionaliteit, betrouwbaarheid, gebruiksgemak en vooral creativiteit wanneer ze de nieuwste krachtige tools tot hun beschikking hadden kunnen hebben om iets nuttigs te bouwen zonder tijd te verspillen met drukknoppen. , en vooral het verspillen van geld betalen voor dure abonnementen op software die weinig mensen toch wilden gebruiken, gezien de beperkingen van het gebruik en flexibiliteit. Als je een paar minuten hebt om dit boek te lezen en te leren wat ik je wil leren, of zelfs met mij persoonlijk over je doelen wil praten en wat begeleiding in de goede richting krijgt, en gemotiveerd zijn om te leren coderen en te schrijven van je eigen software , neem dit boek mee naar huis en zet wat tijd opzij om te leren de volgende invloedrijke, krachtige, gestroomlijnde en belangrijke webapplicatie te bouwen, een website die allemaal op u staat en precies doet wat u wilt en voldoet aan de behoeften van uw publiek. Over mij: Ik ben een softwareontwikkelaar metBereik van ervaring in C/C ++, Java, Python, HTML, CSS en JavaScript. Ik bouw websites die mensen willen gebruiken, willen bezoeken en zelfs verslaafd raken aan het gebruik alleen om tijd te leren, te herscheppen en te doden, en vooral, ik verkoop software. Als je een idee had om precies hoe je wilde dat een website eruit zou zien en functioneerde, was je bereid me te ondersteunen zodat ik aan mijn eigen behoeften kan voldoen terwijl ik de jouwe ontmoet, en je bent bereid om de kosten van het runnen van een website zelf te dekken, Ik zou je de volgende YouTube, Tiktok, Twitter, Google of zelfs een hightech-beveiligings-app bouwen die je toegang hebt. In plaats van te proberen je mijn tijd te verkopen, probeer ik de jouwe te kopen: ik wil je er zelf over hebben om een ​​app (website) te bouwen met de informatie die al bestaat, en je te leren wat je nodig hebt om een ​​onafhankelijke softwareontwikkelaar te zijn, Ondernemer, die een succesvolle carrière leidt op het gebied dat je wenst. En laat me duidelijk zijn, de opleiding die ik je geef, zal informeel zijn. Je zou naar school kunnen gaan en dit allemaal leren met eenFormeel onderwijs, of lees dit boek zelfs op school, voltooi je opdrachten en neem veel weg van je opleiding, maar ik zal je niet formeel in de hot -stoel zetten en je vragen om opdrachten te voltooien. Ik ben niet je professor, je kunt aan mij denken als een vriend die je wil begeleiden naar een carrière gedreven door je eigen persoonlijke succes. En ik verkoop je succes ook niet, je moet het met je tijd kopen. Leren te coderen heeft een steile leercurve en was nooit gemakkelijk, of zou zelfs moeten zijn. Je moet zo hard werken als je kunt en blijven proberen te falen en opnieuw te proberen, zelfs als je gefrustreerd bent om zelf apps te leren en te bouwen. Dat is in de aard van de code zelf. Code wordt uitgevoerd door een compiler die is ontworpen om de programmeerfoutmeldingen te geven, en deze zullen u leren hoe u moet coderen, zelfs als u de fout eenvoudigweg in uw zoekmachine kopieert en de voorbeelden van andere mensen leest. En ik moet zeggen, je hoeft niet extreem rijk, slim te zijn,essentief, of zelfs gedetailleerd georiënteerd of georganiseerd om een ​​app te bouwen. De computer zorgt voor die organisatie voor u. Je hoeft alleen maar door de vallen en opstaan ​​te volharden, de focus te behouden en hard te werken aan wat je doet, en je zult een zeer succesvolle carrière hebben in het geheel van wat je doet. Wie ik ben: Ik realiseer me dat het laatste deel meer ging over leren en je neemt een manier uit dit boek. Wie ben ik precies? Dat is een ingewikkelde vraag. Ik ben daar zelf onduidelijk over, omdat ik last heb van medische aandoeningen die het voor mij moeilijk kunnen maken om dit boek soms te coderen of te schrijven, terwijl ik uitdagingen voor socialisatie- en identiteitsproblemen presenteert die mijn leven moeilijker maken als het gaat om het introduceren van mezelf . Kortom, als je dit boek leest, heb je het naar huis gebracht omdat je er doorheen bent gegooid en dacht dat het nuttig was, of zelfs als je net zo ver in leest, ben ik een gelijkgestemde persoon die je wil zien slagen Alles wat je doet. Ik ben zelf een ingenieur,ontwikkelaar, en een student, en ik schrijf dit boek voor andere studenten die hun leven gemakkelijker willen maken door een handboek te hebben van de software die ze nodig hebben om hun leven gemakkelijker te maken door voorbeelden te geven die in elkaar passen als een grote puzzel in een werk , nuttige, grote, functionele, samenhangende en boeiende app die succes kan stimuleren, ongeacht de bedrijfslijnen. Grotendeels, dit is wat ik doe: ik bouw apps om mezelf en andere mensen te helpen slagen. Ik ben ook een auteur, hoewel dit mijn eerste publicatie is die ik van plan ben te voltooien om mijn portfolio samen te stellen in een nuttig document, en ik ben ook een kunstenaar. Ik zal je dit toegeven, ik ben een soort vreemd persoon. Ik ben niet perfect, ik heb de wet gehad met de wet, zelfs ertoe leiden dat ik hogescholen en universiteiten verlaten en staten verlaten om te proberen een naam voor mezelf te maken met meer succes. Ik ben een vrouw van geboorte, ik draag make -up, maak foto's van mezelf, draag jurken en andere dameskleding, en ik blijf me bewust van mezelf als eenvrouw van nature. Ik heb in het verleden problemen gehad met andere mensen die hebben geleid tot worstelingen met het schrijven en bouwen van webapps, en ik bied mijn excuses aan dat ik dit boek niet eerder in handen heb kunnen krijgen: je had dit nodig. Je wilt code lezen en schrijven die op de mijne lijkt en werkt als de mijne en hetzelfde doet, maar nog beter, want als je het je kunt veroorloven om dit boek te kopen in plaats van je toetsenbord te pureren zoals ik gewoon een boek maakt om zelf een boek te maken. Daarvoor heb je de middelen die je nodig hebt om succesvol te zijn in je leven. Ik had allerlei problemen met het opgroeien van familie, gezondheidstoestand, artsen, de media en de wet, en mijn code weerspiegelt diep de strijd die feminisme en vrouwelijke natuur is in een verdeelde en gefrustreerde wereld. Dit boek is echter iets waar ik diep om geef, mijn baby, mijn portfolio en mijn levensonderhoud, dus ik waardeer je overweging wanneer je de tekst naar huis neemt en er zorgvuldig overheen porent om van mij te leren. Houd er rekening mee dat ik dat niet benEct, dit boek zal fouten, revisies en nieuwe edities hebben, en je moet zo goed mogelijk met je logische brein denken om een ​​succesvolle ervaring met mijn schrijven te hebben. Begrijp ook dat ik goed voor je bedoel, zelfs als je voor uitdagingen wordt geconfronteerd tijdens het schrijven. Denk er zo over na: als u gewoon een computersysteem kunt huren om alles te doen wat u zich kunt voorstellen in de digitale ruimte, alle informatie opslaat die u tegenkomt, #$%! Yze en organiseer het, en komt u begrijpen Onvermijdelijk moeilijkheden ondervinden met de informatie die u inneemt en zelfs publiceert. Ik vertel je dit omdat ik dezelfde moeilijkheden tegenkom. Gebruik dit boek op eigen risico, werk samen met uw community en communities die voor u beschikbaar zijn om software te bouwen binnen een veilige omgeving, en neem dingen niet persoonlijk aan wanneer u faalt of zelfs op de verkeerde manier slaagt: zo ben ik zo ver gekomen , en waarom ik je deze tekst kan brengen en je kan helpen slagen zonder af te wekken op een pad van waanzinAves me verpest, gescheurd en gerafeld terwijl ik de gewone problemen tegenkom die iedereen op wereldwijde schaal doet dankzij de paralellistische wereldwijde schaal van het netwerk waaraan we zullen werken, het internet. Je bent misschien niet erg bekend met wie ik ben met slechts een paar woorden, maar ik moedig je aan om verder te lezen, je zult me ​​leren kennen terwijl je me blijft lezen en begrijpen tijdens het bouwen van je eigen projecten om je werk te voltooien. Er zal geen huiswerk zijn met dit boek, zolang uw professoren of leraren u geen enkele toewijzen, maar ik moedig u ten zeerste aan om zelf een portfolio van projecten te bouwen terwijl u leest, evenals een Capstone -project dat aantoont hoe u het kunt Pas toe wat je hebt geleerd. Mijn Capstone -project is de basis voor het grootste deel van wat je in dit boek gaat lezen, omdat het code van mijn vorige projecten bevat, code die ik heb gemaakt en geleerd om methodisch met de hand te schrijven, en een breed scala aan ideeën en tips die me hebben geholpen slagen tot het punt waar ik een eenvoudige app kan opdraaienVolledig uitgelicht en uiterlijk en gedraagt ​​zich als een populaire app die je je vriend of familie op internet kunt gebruiken, op internet, geadverteerd aan jou of in het nieuws. Wat dit boek is: Dit boek is een tutorial bij voorbeeld. U kunt hier code vinden, instructies om te leren coderen, informatie over foutopsporingcode en fouten, stappen voor het oplossen van problemen, instructies over hoe u een back-up kunt maken en opslaan van uw code, opnieuw inzetten als iemand uw code breekt, uw code beveiligt, uw code beveiligt, uw code beveiligt, uw code beveiligt, uw code beveiligt, uw code beveiligt, uw code beveiligt, uw code beveiligt, uw code beveiligt, uw code beveiligt, uw code beveiligt, de implementatie implementeert. Uw code, bouw interactieve websites die vermakelijk, boeiend en verslavend zijn, en u zult een idee krijgen van wie ik ben, waarom dit belangrijk is en hoe u uzelf, uw app en bedrijfsimago kunt portretteren, evenals de software die u bouwt In het absoluut beste licht om het meest aantrekkelijk mogelijk te zijn voor uw eindgebruikers, de bezoekers van uw website. In dit boek zal ik een aantal voorbeelden van softwareontwerp demonstreren met een focus op internet als platform en beveiliging. We zullen de leerervaring initiëren door een basis te bouwenOject met behulp van de UNIX -shell, met back -up- en scriptfuncties. Vervolgens zullen we een basisblogwebsite onderzoeken, onze blog upgraden met foto- en videofuncties en deze functies gebruiken om beveiligingsoplossingen te gebruiken met behulp van gratis software en onze server beveiligen met behulp van een pluggable authenticatiemodule (PAM). We zullen dan bestuderen en verwerken van bestanden, het verkennen van videobewerking, spraakdonatie, barcodescanning en optische karakterherkenning, naast andere concepten. Onderweg zullen we API's onderzoeken die ons zullen helpen onze software nuttiger en veiliger te maken, met gratis en betaalde opties. Onderweg zullen we fysieke beveiligings- en militante tools onderzoeken zoals vuurwapens en munitieontwerp en -productie, waaronder het ontwerp van vat en repeater, torentje en drone -ontwerp en andere opdrachtgevers die we zullen integreren met onze software op het bestaande netwerk om onze software te beschermen en demonstreer zelfverdediging en resilversie. We zullen onderweg pauzes nemen om games te bouwen, 2D en 3DEnkerende motoren, en werk met ingebedde hardware in case study -voorbeelden van basisdimensionale rendering -software en een elektronische vibrerende massager die respectievelijk in siliconen rubber wordt gegoten. Onderweg zullen we ook machine learning -oplossingen gebruiken die al beschikbaar zijn om onze software beter te beveiligen. We zullen ook gebruik maken van stocktools die beschikbaar zijn voor het web om het proces te stroomlijnen en te beveiligen. Dit boek is een handleiding voor uw succes bij het bouwen van een webtoepassing en het integreren ervan met een professioneel netwerk van computer en ingebedde mechanische systemen, en over het algemeen een gids voor het bouwen van software en ingebedde hardware zonder achtergrondkennis of eerdere ervaring. Wat dit boek niet is: Als je echt een website wilt hebben, kun je gewoon een eenvoudige winkel opzetten en verkopen wat je nodig hebt, een blog posten, foto's of video's posten, of anderszins zonder ooit een enkele regel code te schrijven. Dit boek is dat niet. Dit boek leert u hoe u software kunt bouwen die nuttiger, volledig isUitgelicht, functioneel en veilig dan alle software die u al kunt vinden, omdat het de nieuwste software implementeert die nog steeds prototypes is, kan duur zijn om te worden uitgevoerd op een schaal die oudere bedrijven opereren, en een beroep doen op achterwaartse, ingewikkelde bedrijven die zijn opgezet Verdien geld voor mensen die niet echt iets doen. Als u dit boek nauwlettend volgt, wilt u code, onderzoekscode schrijven, uw eigen apps bouwen en u zult geld verdienen met wat u doet. Ik zal geld verdienen uit dit boek, zelfs in vroege stadia, omdat het informatie bevat die mensen nodig hebben en willen lezen, en al kopen wanneer ze mijn apps kopen of gebruiken. Dit boek zal geen app voor u bouwen, maar het zal u in de goede richting wijzen en u bewapenen met de tools die u nodig hebt en de vaardigheden en tips die uw eigen succes in het bouwen van software voor internet zullen vergemakkelijken, met elke regel van Code die u als voorbeeld moet schrijven, klaar om samen te voegen in software die u en uw supporters, gasten, klanten,Riends, familie, bezoekers, aannemers en de mensen van internet willen gebruiken en ondersteunen. Wat je zult leren: Dit boek leert u hoe u software kunt bouwen en verkopen, echt functionele, nuttige software, media -opname, beveiligingsfuncties zoals gezichtsherkenning, machine -leesbare zone barcodescan, web -API's om video en foto's te verifiëren, op te nemen en te renderen en berichten uit te wisselen zoals Bluetooth zoals Bluetooth zoals Bluetooth en Near Field (NFC) communicatie. Dit boek leert u hoe u een netwerkcomputer kunt gebruiken, gericht op Debian Linux, hoe u bash -code kunt bouwen om het installeren en een back -up van uw software een naadloze, geautomatiseerde bries te maken, hoe u pythoncode kunt bouwen als een backend om dynamische berichten, stijl te serveren, stijl Dingen die mooi zijn met CSS -stijlen met bootstrap, maakt gebruikersaanmeldingen en interactiviteit mogelijk via netwerkapparaten, bouwen interactieve media en netwerk met andere websites om beveiligingsfuncties aan te bieden, zoals sms -berichten voor verificatie of andere doeleinden, ID -scannen, afbeelding en video -matiging, gegevensRansacties om uw software veilig te houden, betalingsverwerking, cryptocurrency -handel, asynchrone taken en meer. U leert hoe u uw eigen Bluetooth -apparaten kunt bouwen, met batterijen, opladers, microcontrollers, circuits, motoren en sensoren, met soldeer, draad en 3D -geprinte evenals gegoten materialen. Ik zal demonstreren van 3D -ontwerpprincipes die zijn toegepast op additieve productie en gereedschap en het maken van die, zodat u uw eigen ingebedde, hardware -apparaten kunt produceren met geïntegreerde batterijen, opladers, elektronische circuits en functionele uitgangen. En netwerk ze met Bluetooth en het web. In het bijzonder zullen we twee casestudy's onderzoeken, een vibrerende massager en een zelfgemaakte vuurwapen, beide geprogrammeerd in OpenSCAD, die beschikbaar is als een grafische interface of opdrachtregelhulpprogramma en kan worden geïntegreerd in een web voor snellere resultaten. U leert hoe u een website vanaf de grond kunt bouwen en implementeren zonder voorafgaande ervaring, maakt deze functioneel, veilig, mooi, nuttig en de meesteMortant praktisch. U leert hoe u machine learning en computer vision kunt gebruiken om een ​​site veilig en praktischer te maken, video en audio van uw website op te nemen, uw stem te doneren, muziek te maken en audio te moduleren om nuttige voorbeelden te maken en het geluid door te breken door Gebruikmakend van andere websites om het best mogelijke netwerk van websites te bouwen die u rechtstreeks aan de uwe kunt koppelen om alle nuttige informatie die u te bieden heeft te delen, en nog belangrijker mensen naar uw software en bedrijf te brengen. Dit boek zal het zwaarst gericht zijn op media, beveiliging en machine learning, de belangrijkste drie componenten die u zullen helpen nuttige software voor het web te bouwen door de juiste gebruikers te betrekken en de verkeerde te verbreken op een manier die realistisch, praktisch is, Hands on en boeiend, terwijl ook automatisch en stevig. Dit boek leert Unix, met name Debian (Ubuntu), Bash Shell, Python, HTML, CSS, JavaScript en een aantal nuttige softwarepakketten voorn houden van verzoeken, evenals nuttige bash -software zoals git en ffmpeg. Ik zal je ook leren hoe je Cryptocurrency automatisch kunt verhandelen en betalingen moet doen in cryptocurrency of van reguliere betaalpassen, terwijl je zelfs je bezoekers een deel van je inkomsten betaalt als je ervoor kiest om dit te doen. Ik zal je leren hoe je ook geld kunt verdienen met je website via advertenties, hoe je je app kunt klaarmaken voor zoekmachines en het snel kunt maken, gerangschikt in de eerste rangorde voor wat je klanten zullen zoeken om je te vinden, en in zoveel gebruikelijke wijze zoekopdrachten mogelijk. Ik zal u leren hoe u uw software kunt verkopen, adverteren, klanten aanspreken die op zoek zijn naar uw services en een naam voor uzelf op internet maken via wegen die al bestaan, zijn goedkoop en werken goed. Ik zal u leren hoe u uw gegevens kunt opslaan op cloudcomputers die voor u werken en uw gegevens goedkoop opslaan, hoe u een website kunt plannen en bouwen die doet wat uw gebruikers willen en wat u wilt en hoe u uw gebruikers betrokken kunt houdenuw site een tik weg op hun telefoons met meldingen, e -mail, sms -berichten, telefoontjes en meer wegen om uw gebruikers terug te brengen naar uw website tot uw beschikking achter de klik op de knop die alleen aan u is gewaarborgd. Dit boek zal zich richten op de bruikbaarheid van het publiceren en distribueren van media in grote hoeveelheden, van tekst tot foto's tot video's tot audio, een goede indruk maken op eindgebruikers (uw klanten) en uzelf verkopen op een manier die u doet om te maken om te maken Een website, een app die alleen voor u en u representatief is en u, uw software en uw bedrijf er goed uit laten zien op de best mogelijke manier. Je leert ook een paar tips en trucs van mij, van coderingstips, praktische ijdelheid zoals make -up en fotografie, modellering en acteren, en meer, wat belangrijk zal zijn om jezelf en je bedrijf in het best mogelijke licht te portretteren met alle beschikbare tools aan u terwijl u zoveel inhoud verspreidt als u nodig hebt over een gezond evenwicht van platforms om uwE tot bloei zonder meer moeite, werk of geld dan nodig is. Dit boek wordt om een ​​reden "praktisch webgebaseerd diep leren en beveiliging bij voorbeeld" genoemd: het gaat over leren coderen, specifiek voor internet, specifiek met een focus op beveiliging, vanuit een praktisch standpunt, met voorbeelden van werkcode die dient De praktische doeleinden die in de tekst worden beschreven. De leercomponent van deze tekst omvat ook machine learning, de code die ik u zal laten zien hoe u kunt uitvoeren voor het web dat omgaat met computervisie, gezichtsherkenning, afbeelding en video -moderatie, beeldverbetering, resolutieverbetering, afbeelding bijschrift en andere taken zoals Voorspellingsstatistieken afkomstig van afbeeldingen, zoals de aard van de afbeelding als een authentieke, door de computer overgedragen afbeelding of een optische kopie (een foto van een afbeelding of afgedrukte foto). Machine learning is erg belangrijk als het gaat om webbeveiliging en softwarebeveiliging, omdat het taken kan voorafgaan die anders onmogelijk waren. Uw computerLog u in met een toegangscode, maar het kan veiliger zijn om het te gebruiken als het u in uw gezicht registreert. U kunt een servercomputer zo veilig maken, een computer die u normaal gesproken om een ​​gebruikersnaam en toegangscode vraagt ​​en u inlogt, misschien met een bevestigingstoken voor elke nieuwe login of nieuw IP -adres, maar als u grootschalige, gemakkelijk te bouwen bent Gebruik, fundamenteel veilige en krachtige software, dit kan voldoende zijn. Uw software te nauw verbinden met de software van iemand anders, zoals een e -mailservice of sms -service, is niet voldoende om uw software veilig te maken of iemands (elke site die u gebruikt). Iedereen die software bouwt die onberispelijk veilig is, heeft enig idee van wat dit impliceert. Software is inherent onzeker omdat de apparaten en accounts die we gebruiken om deze te openen niet altijd tot onze beschikking zijn, ze kunnen in handen zijn van iedereen met slechte intentie voor de software en kunnen daarom een ​​risico vormen voor de software zelf. Dit is iets van de focus van dit boek. Er is standaard een netwerkcomputerbeveiligd met een lang sleuteltoken, genaamd en SSH of Secure Shell -sleutel, en is anders het best beveiligd met een webserver, omdat de webserver de open toegang biedt en de status van de kunstbeveiligingshulpmiddelen op de server zelf. De webserver heeft toegang tot de webbrowser van de gebruiker, wat misschien wel het krachtigste deel van het apparaat van de gebruiker is, omdat het de plaats is waar de gebruiker toegang heeft tot netwerksoftware. Deze toolkit kan tekst weergeven, de webpagina's die u ziet en kan ook afbeeldingen, audio en video opnemen (zoals een foto van een gezicht of een status -ID), kan lezen en schrijven naar Bluetooth -radio -apparaten en kan lezen en schrijven naar nabij Field Transponder -tags, goedkope sleutelkaarten, FOB's, stickers, ringen en zelfs chipimplantaten met unieke serienummers die kunnen worden gelezen en geschreven met gegevens die zijn gegenereerd en gevalideerd door een webserver die aan de website is gekoppeld. Met behulp van alle tools tot uw beschikking, met dit boek zul je jezelf uitrusten met de kennis om een ​​veilige website te bouwen, en over het algemeen eenURE Networked Computer System dat voor u werkt, uw biedingen doet en ziet er goed uit en voelt en voelt zich goed. Waar te beginnen: U bent van harte welkom om de sectie over te slaan waarmee ik dit boek begin, of een andere sectie, naar de exacte code die u nodig hebt, vooral als u ervaring hebt met codering voor of een van de bovengenoemde tools die ik in dit boek in detail zal beschrijven als evenals het documenteren van use cases en praktische voorbeelden daarvan. Als je geen ervaring hebt met het schrijven van code, raad ik je ten zeerste aan al dit boek te lezen, en raad je vooral aan de vorige secties te lezen, om ervoor te zorgen dat dit boek geschikt is voor jou. Als dit boek niet geschikt is voor u, overweeg dan om het aan een vriend of familielid te schenken die misschien geïnteresseerd is in het leren over webontwikkeling zelf, en overweeg zelfs om het terug te lenen en van hen te leren om de gaten in te vullen waar ik u als een Leraar, of andere leraren deden voor mij. Begin waar u wilt, elk deel van dit boek zal nuttig zijn als u van plan bent een nuttige te bouwenPP, en bedenk dat de beste apps zijn gebouwd met de eindgebruiker in gedachten: ken uw klant. Nu ken je me, je kent dit boek en je bent klaar om te beginnen. Om te beginnen, pak je een computer (zelfs de goedkoopste laptop van een box -winkel, Amazon of een oude desktop werkt en zet hem op een manier die voor jou werkt. Hoe dit boek te lezen: Tekst gemarkeerd, geeft aan dat de tekst in een opdrachtprompt hoort, waar u de code die u uitvoert, schrijft. De opdrachtprompt is zwaar op het toetsenbord gericht en vereist weinig om niet te klikken, uw workflow te versnellen en dingen gemakkelijker te maken. Aan de slag: Laten we erin duiken. We beginnen met het bouwen van code op een lokale machine en beginnen zonder een website te bouwen die is verbonden met internet. Dit is veiliger om mee te beginnen, kost niets en is gemakkelijk voor u. Afhankelijk van uw besturingssysteem zal het in een bash -shell gaan een beetje anders zijn. Voor Mac OS raad ik aan om op dit moment een virtuele machine te installeren, omdat u de meeste compatibiliteit krijgtvirtuele machine. Verschillende providers zoals VirtualBox en Paralells kunnen een virtuele machine voor u uitvoeren, hoewel het ook mogelijk is om Ubuntu rechtstreeks op de machine te installeren, als u liever een native omgeving gebruikt die wordt aanbevolen om een ​​snelle, gestroomlijnde ervaring te creëren. Als u Linux of Windows gebruikt, die ik aanbeveel, moet het vrij eenvoudig zijn om een ​​project te maken. Open uw terminal, pas de maatstaf aan zoals u wilt en begin met het volgen van stap 2. Als u Windows gebruikt, volg dan stap 1. Stap 1: - alleen Windows -gebruikers Open de opdrachtprompt in Windows als beheerder en type wsl –stall Stap 2: - Ga hier verder of sla stap 1 over als u Windows geen Windows gebruikt In een open terminal (afhankelijk van uw besturingssysteem, Ubuntu genaamd in Windows, Terminal in Mac of Linux, of een vergelijkbare naam), begint u met het maken van een project. We doen dit met het MKDIR -opdracht, dat een map creëert. Als u een map moet maken om uw project op te slaan, die wordt aanbevolen, gebruik dan deCD -opdracht om te veranderen in de map en en en CD/PATH/TO/DIRECTORY - Het pad is de mappen (bestanden) die voorafgaan aan uw bestemmingsmap, uw standaardpad is ~ of/home/gebruikersnaam (waarbij gebruikersnaam uw gebruikersnaam is). Typ CD of CD ~ om te wijzigen in de standaardmap ~ MKDIR Voorbeeld - Vervang "Voorbeeld" door de naam van de map Nu heb je een werkmap voor je project. Omdat het zo belangrijk is om deze map te laten opslaan voor het geval u moet overschakelen naar een andere machine of de code die u schrijft moet implementeren, zodat het klaar is voor het web, zullen we een script bouwen om uw directory in de volgende stappen te ondersteunen. Maar het bouwen van een script kost een beetje code en code moet worden geautomatiseerd om zo nuttig mogelijk te zijn. Laten we dus een script bouwen om eerst scripts te bouwen. Laten we beginnen met het maken van het script en het uitvoerbaar maken. We zullen hiervoor sudo, chmod en touch gebruiken en het script aanroepen


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Nu hebben we het script gemaakt, het uitvoerbaar gemaakt en zijn we klaar om het te bewerken. Nano is een teksteditor waarmee u tekst kunt bewerken zonder te klikken, wat veel eenvoudiger is dan het gebruik van een grafische gebruikersinterface. Gebruik Nano en vervolgens het pad naar het bestand om een ​​bestand met nano te bewerken. Om een ​​script te maken dat een script maakt, is het redelijk vergelijkbaar met het maken van ons script in de eerste plaats. We zullen dezelfde code gebruiken als hierboven, ter vervanging van de naam van het script, "Ascript" door een argumentparameter, $ 1. Hierdoor kunnen we het script aanroepen door eenvoudig Sudo Ascript Newscript te typen, op welk moment we elk nieuw script kunnen maken door "Newscript" te vervangen door de naam van uw script. De code in Nano zou eruit moeten zien als:

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
En om Nano te sluiten, kunnen we de besturingstoets ingedrukt houden en op X drukken, dan y om aan te geven dat we het bestand opslaan en rendement raken. Nu in plaats van deze drie opdrachten te typen om een ​​script te bewerken, kunnen we sudo ascript AScript typen om het script opnieuw te bewerken. Dit werkt! En elk nieuw script kan eenvoudig worden uitgevoerd door het in de shell aan te roepen. Laten we ons werk nu opslaan: laten we een back -upscript schrijven om ons nieuwe script op te slaan en het vervolgens te ondersteunen in onze projectmap, terwijl het ook een back -up van het back -upscript back -up maakt.

sudo ascript backup
Nu, in Nano:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Waar/pad/naar/directory is het pad naar het project dat je hebt gemaakt met MKDIR. Later zullen we leren hoe we dergelijke herhaalde paden kunnen kopiëren met een lus en een lijst, die minder code is, maar laten we het voorlopig eenvoudig houden en een paar regels hebben. Sla het bestand op om dit script uit te voeren en back -up van uw code in nano met controle+x, y en retourneer en typ de onderstaande in uw shell

backup
Als u überhaupt wordt gevraagd voor een wachtwoord tijdens het lezen van dit boek en het volgen van de shell, voer dan uw gebruikerswachtwoord correct in, u hebt drie pogingen voordat u de opdracht opnieuw moet uitvoeren. U kunt de pijlen op en neer gebruiken om opdrachten te herstellen en te bewerken, als u alles twee keer moet uitvoeren. Eenvoudig op en neer druk op en neer om een ​​opdracht te selecteren, voordat u de opdracht bewerkt met de rechter, linker pijlen en verwijderde toets en toetsenbord en het uitvoeren met retour. Gefeliciteerd! Je bent erin geslaagd om een ​​geweldig back -upscript te maken dat twee belangrijke shell -scripts in je werkmap maakt. We kunnen de dingen later verplaatsen naarmate het project groter wordt, maar dit werkt voor nu. Laten we verder gaan met een back -up in de cloud, we zullen GitHub hiervoor gebruiken (hoewel er talloze andere Git -oplossingen zijn voor back -up, ze zijn allemaal ongeveer hetzelfde.) Git is een waaringscontrole -software waarmee u een back -up van uw bewerkingen kunt maken Software terwijl u ze naar een server maakt, terwijlzodat u ook hele kopieën van uw software achter een wachtwoord of sleutel kunt downloaden. Het is een belangrijke rol bij het opslaan van uw software, vooral omdat we migreren naar beveiligde Linux -instanties die soms breken wanneer een enkele regel code mislukt, waardoor u wordt vergrendeld terwijl uw code mogelijk niet wordt ondersteund als u geen kans krijgt om het te ondersteunen automatisch omhoog, die we zullen dekken. Als u op dit moment nog geen Ubuntu -virtuele machine gebruikt, raad ik op dit moment aan dat u een Ubuntu -virtuele machine gebruikt, omdat het uw leven gemakkelijker zal maken bij het installeren van alle benodigde pakketten om een ​​werkende website te bouwen en diep te leren bewerkingen op uw computer. We zullen de code in de nabije toekomst naar een webserver verplaatsen, maar we willen ervoor zorgen dat er minstens een paar beveiligingslagen achter onze webserver zijn die bestand zijn tegen phishing en een aantal Linux -pakketten gebruiken om te doen dit. Als u nog steeds Mac OS wilt gebruiken, bent u van harte welkom om te zoeken en te installerenE Noodzakelijke pakketten online, maar er zijn mogelijk geen alternatieven voor elk pakket dat dit boek of serie zal behandelen. Laten we een paar opdrachten toevoegen om ons werk te plegen met het back -upscript door de opdracht sudo -ascript uit te voeren

# …
git add –all
git commit -m “backup”
git push -u origin master
Breng nogmaals de controle van X om op te slaan. Nu moeten we eenmalige configuratie uitvoeren voor dit project. Omdat het binnenkort een GIT -project zal zijn, hoeven we niet elke commando te typen telkens wanneer we vanuit een Git -repository worden geïmplementeerd, maar we zullen dit onder de knie krijgen wanneer we onze implementatievaringen schrijven. Laten we ervoor zorgen dat we ons in de juiste map bevinden en de GIT -repository initialiseren en SSH -toetsen genereren.

cd /path/to/directory
git init
git branch -m master
ssh-keygen
Nadat we SSH-keygen hebben getypt, moet de nieuwe sleutel worden opgeslagen in de huizenmap onder een map genaamd .ssh. Het wordt id_rsa.pub genoemd. Laten we deze sleutel vinden en kopiëren. Om het te zien,

cd ~
cat .ssh/id_rsa.pub
Kopieer de tekst die wordt geretourneerd door de laatste opdracht en maak een account aan bij uw GIT -provider (idealiter GitHub), voordat u de SSH -toets aan uw account toevoegt. Zodra u een account hebt, klikt u op het menu Rechtsboven en voert u instellingen in, voordat u uw SSH -toets toevoegt in SSH- en GPG -toetsen onder toegang in het menu. Selecteer een SSH -toets toevoegen en voeg de uwe toe door deze in te plakken en een titel te geven, voordat u opslaan en terugkeren naar GitHub om een ​​nieuwe repository te maken. Dit is vergelijkbaar voor andere GIT -providers, u moet hun documentatie lezen. Geef uw repository in de nieuwe repository -configuratie een beschrijvende naam en beslis of u deze wilt publiceren, en zorg ervoor dat u nog geen bestanden voor opname configureert. Nadat de repository is gemaakt, kopieert u de kloon met SSH -URL en plakt u deze in de volgende opdracht.

git remote add git://… (your remote URL)
Nu kunt u teruggaan naar uw repository met CD, u zult hiermee bekend zijn. Probeer nu uw back -upscript met back -up Geweldig! Nu kunnen we echt coderen. Laten we Django installeren nu we een goede greep hebben op bash en git. Django laat ons onze software automatisch een back -up maken, Bash kan dit ook doen, maar Django moet een eenvoudiger veiligere implementatie hebben (het kan gemakkelijker worden uitgeschakeld en geconfigureerd). Om software in Ubuntu te installeren, zullen we de sudo apt-get-opdracht gebruiken. Laten we eerst de software bijwerken en upgraden die we al hadden. Dit kan worden gedaan met sudo apt-get update en sudo apt-get-upgrade -y. Laten we vervolgens Python en onze virtuele omgeving, de thuisbasis van onze code, installeren met de volgende opdracht: sudo apt-get install python-is-python3 python3-venv Dit is alles wat je nodig hebt om met Django aan de slag te gaan in termen van software -installaties in de Ubuntu -instantie. Voor Windows en Linux zou dit vrij eenvoudig moeten zijn, maar voor Mac wilt u misschien een virtuele machine installeren enLinux erop met een gratis of betaalde virtuele omgeving zoals VirtualBox of Paralells Desktop en de bovenstaande stappen opnieuw maken om een ​​Ubuntu -omgeving in te stellen. Ubuntu is in dit geval van cruciaal belang omdat het de software is die de websites uitvoeren en hiermee websites kunnen hosten met alle bovengenoemde software. Laten we in de Django graven. Opnieuw in onze map, met

python -m venv venv # Creëert de virtuele omgeving waar code wordt opgeslagen
source venv/bin/activate # Activeert de virtuele omgeving
pip install Django
django-admin startproject mysite . # Waar Mysite het project is dat ik begin in mijn huidige map.
Django laat ons net op weg gaan, omdat Django de webserver host en alles doet wat we nodig hebben om een ​​eenvoudige lokale website in gebruik te nemen. Nu we Django hebben geïnstalleerd, laten we de instellingen een beetje bewerken om het te laten werken hoe we nodig zijn. Laten we eerst een nieuwe app maken

python manage.py startapp feed
U zult merken dat de eerste app feed wordt genoemd. De app moet worden genoemd wat u maar wilt, en we zullen nieuwe apps maken, maar de naam van elke app moet consistent zijn telkens wanneer de app in de code wordt verwezen. Om een ​​nieuwe app toe te voegen, zullen we altijd de instellingen.py in de andere map bewerken, de app die is gemaakt, genaamd in StartProject, hierna app. Nano gebruiken,

nano app/settings.py
Zoek in de instellingen Installed_Apps en scheid de [] in 3 regels. Voeg 'feed' of de naam van uw app met vier spaties op de lege middellijn toe. Dit gedeelte van de instellingen.py moet eruit zien als:

INSTALLED_APPS = [
    'feed',
]
Voordat we het vergeten, laten we testen dat Django werkt. Met behulp van de opdracht python management.py runserver 0.0.0.0:8000, kunnen we de server uitvoeren en vervolgens navigeren in een webbrowser op de computer die de code uitvoert naar http: // localhost: 8000 en een voorbeeldwebpagina bekijken (deze werkt!) Vertel de server met controle C, hetzelfde als elke andere opdracht. Laten we nu een python -code schrijven. Django heeft drie hoofdcomponenten, ze zijn allemaal volledig uitgevoerd door code. De componenten worden model, weergave en sjabloon genoemd en elk bevindt zich respectievelijk op een hoger en lager niveau voordat de webpagina aan de gebruiker wordt geleverd. Het model is de code die informatie opslaat in de database voor het ophalen, sorteren en renderen. De weergave bepaalt hoe het model wordt weergegeven, gemanipuleerd en gewijzigd, bijna elke weergave zal een model rechtstreeks gebruiken. De sjabloon is de HTML -code met wat extra toeters en fluitjes genaamd sjabloontaal. De sjabloon wordt weergegeven door de weergave waar deze gevuld is met Python -code enContext zoals modellen en informatie (usuall strings en gehele getallen) uit de weergave. Django heeft ook andere componenten, waaronder maar niet beperkt tot: Instellingen, die de app configureren zoals we hebben besproken. URL's, die patronen zijn die de gebruiker volgt om toegang te krijgen tot specifieke delen van de webtoepassing. Formulieren, die bepalen hoe informatie die naar de server wordt verzonden, wordt behandeld en weergegeven aan de database en aan de gebruiker. Dit vormen de basis van het verwerken van informatie aan de serverzijde en kunnen elk type informatie accepteren dat de computer slaat, met name tekstreeksen, nummers en true/false booleans (meestal selectievakjes). Sjablonen, die een HTML -code en sjabloontaal zijn en de kloof tussen Python en HTML overbruggen, wat betekent dat Python -informatie kan worden geserveerd als HTML -code die iedereen toegang heeft en een website kan beveiligen met beperkte toegang, terwijl Python -code toegankelijk is voor internet en nuttig Voor verschillende doeleinden op een extern apparaat dat nieteed om in de buurt van de server te zijn. Statische bestanden, die meestal JavaScript zijn en de bibliotheken die de server bedient en zijn gekoppeld aan de sjabloon. Mediabestanden, die de server serveert of extern wordt gehost, of gewoon naar de server worden geschreven voordat ze worden verwerkt en op een andere server (een emmer) voor hosting worden geplaatst. Middleware, dat stukjes code is die tegelijkertijd met elke weergave worden uitgevoerd en worden beschouwd als 'inbegrepen' in de weergave. Contextprocessors, die de context van elke weergave verwerken en worden gebruikt om extra context toe te voegen. Tests, die valideren dat de gebruiker of het verzoek aan bepaalde vereisten voldoet voordat de weergave wordt weergegeven. Consumenten, die bepalen hoe websockets omgaan en reageren op communicatie. Admin, die wordt gebruikt om modellen te registreren zodat ze in detail kunnen worden gemanipuleerd op de Django -admin -pagina, waar de database kan worden beheerd via een grafische interface. Selderij, die asynchrone taken definieert, kunnen delen van de Django -code beginnenNning voordat u onmiddellijk naar de volgende taak of regel van code ging. Django kan veel andere componenten hebben, die we hier in detail zullen bespreken. Er zijn tal van manieren om Django functioneler te maken, websocket toe te voegen, die snel, gestroomlijnde communicatiekanalen, selderij zijn, die asynchrone taken uitvoeren, en een veelheid aan andere stukken software voor het uitbreiden van Django, vooral in de viewfuncties, waar de meeste van functies de code wordt uitgevoerd. Bekijkfuncties zijn belangrijk omdat ze meestal elk stuk code verklaren dat specifiek is voor een specifiek URL -patroon of een gedeelte van de server. Laten we eerst de view -functies verkennen. Bekijkfuncties beginnen met importcode die in de weergave wordt gebruikt en worden gedefinieerd met behulp van reguliere functiedefinities of klassen. De eenvoudigste weergaven worden gedefinieerd door de functiedefinitie DEF en retourneer een HTTPRESPONE met een basissjabloon. Laten we beginnen met het definiëren van een basisweergave om de tekst "Hallo wereld" te retourneren. Onthoud dat elke keer dat u toevoegtNa een verklaring als def, als, terwijl, voor, enz., u 4 spaties moet toevoegen voor elk van de voorgaande definities die u op uw functie wilt toepassen. We zullen ingaan op wat elk van deze betekent binnenkort. Bewerk vanuit de map van onze site het bestand feed/views.py met nano en voeg de volgende regels toe aan het einde van de

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
Django's HttPresponse reageert met een tekstreeks, aangegeven met de opening en sluiting '. Telkens wanneer u informatie doorgeeft aan een functie of klasse, zoals aanvraag of een tekenreeks, moet u haakjes (, openen en sluiten) gebruiken. Dit is niet alles wat we nodig hebben om onze mening nog te zien. Natuurlijk hebben we de server niet verteld waar de weergave precies is, we moeten nog steeds een pad definiëren waarmee de weergave moet worden weergegeven. Laten we beginnen met het definiëren van een basispad in app/urls.py en we zullen later in padgroepen komen. Voeg in app/urls.py een regel toe na de importverklaringen na het begin met het importeren van de weergave die we zojuist hebben gemaakt.

from feed import views as feed_views
Laten we nu het weergavepatroon definiëren. Bekijkpatronen hebben drie componenten, de padcomponent, die de server vertelt waar de weergave bestaat binnen de server (het URL -pad dat de gebruiker typt in de navigatiebalk om de webpagina in te voeren), de weergavecomponent waar de weergave is opgegeven, en een Vriendelijke naam voor de weergave, dus het is gemakkelijk om het patroon op te halen bij het werken met een sjabloon, vooral zodat de naam kan worden gewijzigd en bijgewerkt indien nodig om ruimte te maken voor een andere weergave of een meer logische naam aan te nemen. Het is logisch om dingen op deze manier te doen en flexibel te zijn, omdat uw codebase een steeds veranderende omgeving zal zijn die flexibiliteit en improvisatie nodig heeft om waardevol en gemakkelijk mee te werken. Dit is hoe uw weergave eruit zal zien, u kunt dit toevoegen aan de urlpatterns = [sectie van app/urls.py. Het weergavepatroon wordt gedefinieerd met de drie hierboven beschreven componenten en een functie die pad wordt genoemd. Uw URL -patronen zijn een lijst, dus zorg ervoor dat u elk item er altijd in beëindigtmet een komma, omdat dit elk scheidt. Elk item moet ook op een nieuwe regel gaan, opnieuw met vier spaties ervoor, net als de app in instellingen.py. We definiëren het eerste onderdeel van de weergave met een lege stringfunctie om een ​​weergave te maken die op de hoofdmap van de webserver wordt uitgevoerd. Uw urls.py zou er nu uit moeten zien

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Dit is de basis voor het maken van een website met Django die volledig statisch is. Om een ​​meer dynamische website te maken waar we kunnen beginnen met het cachen van informatie, zoals afbeeldingen, video's, audio en meer, moeten we modellen gebruiken, die we vervolgens zullen verkennen. Laten we voor nu onze code controleren en de server uitvoeren. Voer de code op om de code te controleren:

python manage.py check
Als er foutmeldingen zijn, moet u de wijzigingen die u in uw app hebt aangebracht zorgvuldig bekijken en kijken of er iets is dat moet worden opgelost, zoals een vreemde of gebrek aan ruimte, een extra teken, een niet -afgesloten string, een typefout, een per ongeluk Verwijderd karakter, of iets anders. Het lezen van de foutmelding (als je er een hebt), zou je het pad moeten kunnen zien naar een bestand dat je hebt gemaakt of bewerkt samen met een regelnummer, dus kijk in dat bestand en regel en kijk of je iets kunt repareren dat er is . Als u het probleem hebt opgelost, voert u de bovenstaande opdracht opnieuw uit. Wanneer uw software klaar is om uit te voeren en werkt, ziet u de uitvoer "Systeemcontrole die geen problemen heeft geïdentificeerd". Nu ben je klaar om te gaan. Voer de server uit met:

python manage.py runserver 0.0.0.0:8000
Open nu een webbrowser en navigeer naar http: // localhost: 8000. In uw weergave zou de tekst moeten worden geretourneerd in de haakjes en citaten van de HTTPRESPONSE -functie. Dit is slechts een fundamenteel voorbeeld, maar als je het zo ver hebt gehaald, begrijp je de basisprincipes van hoe Linux, Bash, Python en Django werken. Laten we dieper ingaan op wat databasemodellering en de kracht van een Python -klasse verkennen bij het opslaan van informatie. Vervolgens beginnen we een grip te krijgen op HTML en CSS voordat we onze site volledig aanbevolen, flexibel en veilig maken met behulp van JavaScript en Machine Learning. Klassen worden opgeslagen in de modellen.py van uw app. Nano gebruiken, app/modellen.py bewerken en een nieuwe klasse toevoegen. Een klasse wordt gedefinieerd met de klassendefinitie en wordt doorgegeven aan een superclass waar deze van, in dit geval modellen.model. De naam van de klasse komt na de klassendefinitie en na de klassendefinitie A: (colon) wordt gebruikt, voordat de attributen en functiedefinities die aan de klasse zijn gekoppeld hieronder worden aangegeven. Onze klasHeeft een ID nodig die we kunnen gebruiken om het op te halen en uniek te houden, en het heeft ook een tekstveld nodig om wat informatie op te slaan. Later kunnen we een tijdstempel, bestanden, booleans toevoegen (ware of valse definities die onze code kunnen helpen beslissingen te nemen over wat te doen met het model, en kunnen worden gebruikt om het te sorteren), een instantie om het model aan een gebruiker te binden in de server, en meer. Laten we de code uitpakken

from django.db import models # De import die wordt gebruikt om onze klasse en de attributen te definiëren

class Post(models.Model): # De definitie van onze klas zelf
    id = models.AutoField(primary_key=True) # De ID van ons model, een automatisch gegenereerde sleutel waarmee we het model kunnen opvragen, uniek houden en nuttig zijn wanneer we met het model moeten communiceren zodra het is gemaakt.
    text = models.TextField(default='') # Het kenmerk onze klasse -opslag, in dit geval, wat tekst, die niet in gebreke zijn gebleven naar een lege tekenreeks.
Sluit en sla het bestand op zoals we eerder deden om te voltooien. Er zijn veel andere velden en opties die we zullen onderzoeken wanneer we deze klasse bijwerken naarmate onze app evolueert, maar dit is de basisbehoeften om een ​​app te maken om wat tekst te plaatsen. Dit model werkt echter niet alleen. Zoals eerder beschreven, hebben we een aangepaste weergave en aangepast URL -patroon nodig om dit model te laten werken, en we hebben ook een formulier nodig samen met een sjabloon. Laten we eerst het formulier verkennen. Om een ​​formulier te definiëren, bewerkt u app/forms.py met nano en voegt u de volgende regels toe. We hebben twee import nodig, onze formulierenklasse, evenals het model dat we hebben gemaakt (feed.models.post), een klassendefinitie vergelijkbaar met het model en een veld samen met een subklas met. Het formulier kan ook een initialisatiefunctie hebben die deze instelt op basis van informatie in het verzoek, model of anderszins, we zullen dit later verkennen. Modelformulieren zijn zo nuttig omdat ze een model kunnen maken of ook een model kunnen bewerken,Dus we zullen ze voor beide gebruiken. Laten we er een in vormen definiëren. Py

from django import forms
from feed.models import Post

class PostForm(forms.ModelForm):
    text = forms.CharField(widget=forms.Textarea)
    class Meta:
        model = Post
        fields = ('text',)
Dit is de basisprincipes van hoe een vorm en model eruit zien. Dit modelformulier kan worden gebruikt om een ​​bericht te instantiëren of te bewerken, waarbij de tekst die het bevat te wijzigen. We zullen kijken naar de integratie van dit formulier in een weergave hierna. Laten we eerst de migraties maken en de database migreren, zodat onze code kan communiceren met het model wanneer het wordt uitgevoerd. Om dit te doen, voert u de volgende opdrachten uit:

python manage.py makemigrations
python manage.py migrate
Dit duurt een minuut om uit te voeren, maar zodra dit het geval is, kunt u toegang krijgen tot het model in de weergaven, middleware of ergens anders in de software. Laten we doorgaan door te bekijken waar we ons model kunnen zien. Bewerk feed/views.py en voeg de volgende code toe, zoals opgemerkt. U hoeft niets toe te voegen na het # -teken, die code is opmerkingen die worden gebruikt om informatie over de code aan te geven. We beginnen met het importeren van ons model in de weergaven en het toevoegen aan een context waarin we het in een sjabloon kunnen weergeven als een lijst voor weergave. Vervolgens zullen we een sjabloon toevoegen waarbij we het formulier en het model kunnen weergeven met een knop om een ​​nieuw object te maken op basis van het model en het op de server te plaatsen. Dit klinkt ingewikkeld, dus laten we het stap voor stap zetten. Voordat we de weergave voltooien, laten we een sjabloon maken die het model gewoon weergeeft en ervoor zorgen dat we het kunnen zien door een nieuwe post in de shell te maken. Hier is hoe die weergave eruit moet zien:

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

def feed(request):
    posts = Post.objects.all() # Vraag alle berichten tot nu toe in de database
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })
Dit ziet er allemaal vrij eenvoudig uit totdat we tot de bodem zijn. Render, de waarde die wordt geretourneerd door de functie in plaats van in een HTTP -reactie zoals het vorige voorbeeld, neemt altijd een verzoek als de eerste invoer, accepteert een context (in dit geval de berichten in de database), die nu in de sjabloon kunnen worden weergegeven en retourneert de sjabloon die in de functie is gedefinieerd. De sjabloon wordt een HTML -document met een beetje een taal genaamd Jinja2, die Python -informatie naar de HTML maakt. Om te beginnen met het maken van sjablonen, maak je twee mappen in feed.

mkdir feed/templates
mkdir feed/templates/feed
Bewerk vervolgens een sjabloon in de bovenstaande map, feed/sjablonen/feed en voeg de code toe voor dit voorbeeld. Laten we eens kijken naar de sjabloon voor dit voorbeeld.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Dit is een heel eenvoudige sjabloon. Het definieert het openen en sluiten van HTML -tags, een tag met documenttype, een body -tag met een legendetitel, een break -tag die een kleine lijn over het scherm toevoegt, en een voorlus die elk bericht in de lijst met berichten weergeeft als een paragraaf in de sjabloon. Dit is alles wat nodig is om berichten te geven, maar er zijn er nog geen in de database. Laten we wat maken met de shell. We kunnen de shell uitvoeren met management.py

python manage.py shell
Laten we nu ons postmodel importeren

from feed.models import Post
Vervolgens zullen we een eenvoudige post maken met een string en de shell verlaten. De string kan alles zijn, zolang het geldige tekst is.

Post.objects.create(text='hello world')
exit()
Ten slotte moeten we een URL -patroon aan onze feed toevoegen. Omdat onze feed -app meerdere URL's gebruikt en we de bestandsgroottes klein willen houden, laten we een lokale urls.py maken in onze feed -app die er zo uitziet:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
We zullen ook de urls.py in de basis -app moeten bewerken, wat we ook besloten het te noemen, dit was de eerste directory die we hebben gemaakt. Bewerk app/app.py en voeg het volgende toe aan de URL -patronen

from django.urls import include # bovenaan

urlpatterns = [
    # ... vorige code hier
    path('feed/', include(('feed.urls'), namespace='feed')),
]
Wanneer we de server nu uitvoeren met python management.py runserver, zien we de pagina die we hebben gemaakt omdat we het model, de weergave en het url -patroon hebben, samen met items in de database. Laten we vervolgens het formulier implementeren dat we hebben gemaakt en beginnen met het maken van onze eigen berichten. Maar voordat we te veel code schrijven, laten we een back -up maken met het script dat we eerder hebben geschreven, back -up. Voer dit script in de shell uit, wacht een paar ogenblikken en alle code wordt ondersteund door onze GIT -repository.

backup
Het implementeren van het formulier is relatief eenvoudig. We zullen ons formulier importeren, een post -aanvraaghandler toevoegen aan de weergave en het bericht opslaan in de database voordat we naar dezelfde weergave worden gericht. We kunnen de omleidingsfunctie gebruiken die we al hebben geïmporteerd, en een andere functie genaamd Reverse om de URL voor het weergavepatroon te krijgen. We zullen dit opvragen met de tekenreeks 'Feed: Feed' omdat de naamruimte van het opgenomen patroon feed is en de weergave ook Feed wordt genoemd.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Vraag alle berichten tot nu toe in de database
    if request.method == 'POST': # Behandel het postverzoek
        form = PostForm(request.POST) # Maak een instantie van het formulier en sla de gegevens op
        if form.is_valid(): # Valideer het formulier
            form.save() # Sla het nieuwe object op
        return redirect(reverse('feed:feed')) # Direct door naar dezelfde URL met een GET -verzoek
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # Zorg ervoor dat u de vorm in de context doorgeeft, zodat we het kunnen weergeven.
        'posts': posts,
    })
Nu moeten we de sjabloon bijwerken om rekening te houden met het nieuwe formulier. We kunnen dit doen door de
Tag in HTML en het weergeven van het formulier in de HTML -sjabloon met een verzendknop. We hebben ook een CSRF -token nodig, een token dat voorkomt dat externe sites op het formulier worden geplaatst zonder eerst een pagina te laden.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<form method=”POST”>
{% csrf_token %}
{{ form }}
<button type=”submit”>New Post</button>
</form>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Laten we dit afbreken. Er is een nieuwe formulierklasse, een token, het formulier zelf en een verzendknop. Vrij eenvoudig, maar als we er naar kijken, willen we het misschien beter laten lijken. Het werkt, we kunnen nieuwe berichten met het formulier plaatsen en ze zijn nu opgeslagen in de database. Er zijn hier een paar dingen aan de hand. We gebruiken HTML -tags om te verklaren dat het document een HTML -document is, we gebruiken een sjabloon -tag ({ %… %}) om het token voor het formulier weer te geven, en een andere, {{…}} om het formulier weer te geven. We hebben ook een lus om de tekst weer te geven met behulp van bloktags en een sjabloon -tag. Bloktags zijn echt belangrijk omdat we kunnen definiëren hoe secties van de sjabloon worden weergegeven, en sjabloontags vormen de basis van hoe we variabelen in onze code plaatsen. Nu moeten we onze app er beter uit laten zien, want voor nu ziet het er echt eenvoudig uit. We kunnen dit doen door CSS te gebruiken, inline, of in klassen die aan elk object in het document zijn gekoppeld. CSS is echt leuk omdat het alles op de pagina vertelt hoe het eruit moet zien,En kan het er echt goed uit laten zien. Er zijn een paar bibliotheken die dit kunnen doen, maar mijn persoonlijke is bootstrap. Bootstrap kan worden gedownload van hun website,getbootstrap.com/. Eenmaal daar, druk op de knop om de installatiedocumenten te lezen en kopieer de code uit de sectie Inclusief innemen via CDN. U hebt deze code bovenaan uw HTML -document nodig, in een tag genaamd Head. Laten we ook doorgaan en een basissjabloon maken, zodat we deze links niet in elke sjabloon opnieuw hoeven te maken. Maak een nieuwe map genaamd sjablonen met MKDIR -sjablonen en bewerk vervolgens sjablonen/base.html. Het zou er zo uit moeten zien:
 
<!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>
 
Zorg ervoor dat u de CSS en JavaScript, de .css- en .js -bestanden kopieert, omdat we het JavaScript nodig hebben om onze site in de toekomst functioneler te maken. Laten we nu terugkeren naar de bash -shell en een snelle opdracht uitvoeren. Vergeet niet dat als u ooit toegang moet krijgen tot de virtuele omgeving, de bron Venv/Bin/Activeer Typ. Hiermee kunt u Python -pakketten lokaal installeren op een manier waarmee Django toegang heeft. Om onze formulieren te geven die worden gegenereerd door Django Bootstrap -klassen, zullen we een Python -pakket gebruiken genaamd Crispy Forms. We kunnen dit downloaden met de volgende opdracht

pip install django-crispy-forms
Zodra dit is geïnstalleerd, voegt u het toe aan de instellingen.py

INSTALLED_APPS = [
    # … Vorige code hier
    'crispy_forms',
]
Nu, terug in onze toevoersjabloon, kunnen we enkele dingen verwijderen. Laten we het begin en einde van het document verwijderen en vervangen door overerving uit onze basissjabloon, met behulp van Extends en de blokdefinitie. We zullen ook een sjabloonfilter importeren met load en een sjabloonfilter aan het formulier toevoegen. Laten we ten slotte een bootstrap -klasse toevoegen aan de knop op het formulier om deze meer op een knop te laten lijken. Dat zou er zo uit moeten zien:
 
{% 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 %}
 
Mooi! Dat is al nogal wat code. Vervolgens moeten we het testen en ervoor zorgen dat we kunnen zien dat alles er mooi uitziet, en er ook zeker van dat alles goed werkt. Voer de server uit volgens eerdere instructies en zorg ervoor dat de site er uitziet en goed werkt. Geweldig werk! U bent klaar om door te gaan naar de volgende stap, waarin we gebruikersaanmeldingsfunctionaliteit toevoegen met vergelijkbare URL's, formulieren, weergaven en sjablonen. De basissjabloon is belangrijk, en we zullen het blijven wijzigen en wijzigingen aanbrengen als dat nodig is, maar laten we ons nu concentreren op het veiliger maken van onze site, door gebruikers in staat te stellen in te loggen met een gebruikersnaam en toegangscode, en uiteindelijk nog belangrijker informatie dat helpt uw ​​app veilig te houden en uw eigen account alleen toegankelijk door u. Om dit te doen, moeten we het gebruikersmodel gebruiken ingebouwd in Django. Het gebruikersmodel is een databasemodel, zoals onze post, dat kan worden weergegeven om een ​​gebruiker op de website te loggen. In de toekomst, voordat we de site op internet implementeren, zullen we dat doenBreid dit model uit met andere modellen die eraan worden toegeschreven en bouw extra beveiligingsmaatregelen op voor de inloggen die bestand zijn tegen phishing. We zullen beginnen met het gebruik van enkele ingebouwde inlogformulieren die Django biedt. Laten we eerst een nieuwe app maken die we zullen gebruiken om de sjablonen en weergaven voor de Basic Login -pagina weer te geven. We zullen ook andere apps maken om de voortdurende inloguitdagingen weer te geven om de app te beveiligen, waaronder een pincode, gezichtsherkenning, nabije veldcommunicatie, externe apparaten, multi -factor authenticatie en vingerafdrukherkenning. We hebben het al gehad over het starten van een app. Van onze map, binnen de virtuele omgeving, pass beheren.py deze

python manage.py startapp users
Nu moeten we een directory hebben voor de nieuwe app. Laten we beginnen met het maken van een weergave in die map die overeenkomt met de gebruikersaanmelding. Django heeft ingebouwde weergaven voor gebruikersaanmeldingen, maar deze zijn niet geschikt voor ons omdat we een aangepaste weergave nodig hebben, die bij voorkeur met een definitie wordt gedaan. In deze weergave zullen we beginnen met het controleren van een postverzoek, PASS -verzoek. Post naar een Loginform geïmporteerd vanuit Django, de gebruikersaccount verifiëren en de gebruiker inloggen voordat u deze naar onze feed -app omgeleid. Voeg in gebruikers/views.py de volgende code toe

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'] # Haal de gebruikersnaam en het wachtwoord uit het postverzoek
        password = request.POST['password'] # Authenticeer de gebruiker
        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()})
Dit is alles wat je nodig hebt voor een basisaanmeldingsweergave. Laten we nu een formulier voor de weergave maken door de basissjabloon uit te breiden. We beginnen met het maken van een nieuwe map voor sjablonen in de map Gebruikers.

mkdir users/templates
mkdir users/templates/users
Nu moeten we gebruikers/sjablonen/gebruikers/login.html kunnen bewerken. Terwijl we bezig zijn, maken we een sjabloon om de gebruiker ook aan te melden.

nano users/templates/users/login.html
Nu, in de sjabloon,
 
{% 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 %}
 
Dit is de basisprincipes van een inlogsjabloon. Het is echt net als de andere sjabloon in structuur, maar het ziet er een beetje anders uit wanneer het wordt weergegeven. We kunnen deze code kopiëren om een ​​andere zeer vergelijkbare sjabloon te bouwen genaamd Register.html, waar we de formulering zullen wijzigen en een nieuw formulier gebruiken dat we bouwen. Laten we eerst de sjabloon maken. Gebruikers/sjablonen/gebruikers/register.html bewerken en de volgende code toevoegen:
 
{% 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 %}
 
Laten we nu een formulier bouwen voor onze gebruikersregistratie en teruggaan naar de weergaven voordat we onze gebruikersaanmeldingen upgraden met een model. We zullen dit formulier fundamenteel maken om mee te beginnen, maar nemen in de toekomst meer details en beveiligingsfuncties op, zoals overeenkomsten en Captcha. Bewerk de formulieren met nano -gebruikers/formuliers.py en voeg de volgende code toe.

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']
Dus we hebben hier nog een vorm, wat redelijk eenvoudig werkt. Het is een gebruikersregisterformulier met een gebruikersnaam, e -mail en wachtwoord, evenals een bevestigingswachtwoordveld. Merk op dat dit formulier de reguliere vorm niet uitbreidt. Eén veld is precies hetzelfde gedefinieerd en de klasse meta definieert het model dat de vorm overeenkomt met de rest van de informatie die naar de vorm wordt geschreven. Het meeste hiervan bestaat al in Django's ingebouwde UserCreationForm, dus we zullen dat gebruiken als basis voor de klasse (doorgegeven in de haakjes). Vervolgens zullen we de weergave onderzoeken om een ​​gebruiker te registreren, nu we een formulier en een sjabloon hebben. Dit is een modelform, net als die in de nieuwe postweergave. Gebruikers/views.py bewerken en de volgende code toevoegen:

# ... bedragen
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})
Dit is alles wat we nodig hebben om een ​​gebruiker te laten registreren, maar we moeten meer informatie hebben. We willen weten hoe de gebruiker zich heeft geregistreerd, hoe laat ze voor het laatst op de site waren, wat informatie over hen, zoals een biografie, tijdzone, enz. Ook moeten we ons feedmodel bijwerken, post, om rekening te houden met de gebruiker Model- en kenmerkberichten aan elke gebruiker. Om dat te doen, zullen we de modellen.py bijwerken in beide apps. Laten we beginnen met het bewerken van het voedingsmodel. Het zou er nu zo uit moeten zien:

from django.db import models # ... bedragen
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') # Voeg deze regel toe
    text = models.TextField(default='')
Let op de tweede regel die aan het bestand is toegevoegd. Dit is een buitenlandse sleutel, die elk bericht per bericht per bericht toeschrijft, zodat we ervoor kunnen zorgen dat we de berichten op een gebruikers-per-gebruikersbasis opslaan en er kan geen bericht worden gemaakt zonder deze aan een gebruiker toe te schrijven. We definiëren deze buitenlandse sleutel met de klasse die het vertegenwoordigt, een verwijderargument om ervoor te zorgen dat berichten worden verwijderd met gebruikers, nul- en lege argumenten om ervoor te zorgen gemaakt, en een gerelateerde naam, die we kunnen gebruiken om te verwijzen naar de postobjecten die de gebruiker maakt. Deze gerelateerde naam, in tegenstelling tot Post.Author, de auteur van het bericht, geeft ons de gebruiker die het bericht zelf heeft gepost. We kunnen nu de berichten krijgen die een gebruiker heeft gemaakt door gebruiker.posts.all () of author.posts.all (). Laten we nu onze aanmeldingen veerkrachtiger maken. We kunnen onze site al veel minder kwetsbaar maken voor phishing door eenvoudigweg het aantal keren te beperken dat we een inloggen op deSite, dit is vrij eenvoudig. Laten we ook eerder wat informatie over elke gebruiker opslaan terwijl we onze app blijven ontwikkelen. Gebruikers/modellen.py bewerken, voeg het volgende toe

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='')
Merk op dat dit model redelijk vergelijkbaar is met het postmodel. We hebben een extra import, tijdzone, waarmee we standaardinstellingen kunnen instellen op de datetime -velden, en we hebben ook een Characterfeild en Textfield zoals het bericht. Het gebruik van al deze tijdstempels helpt ons om de site te beveiligen en het gebruik ervan te begrijpen, en de tekstvelden laten ons informatie over elke gebruiker of auteur op de website weergeven. Het OnetoOneField moet de enige kleine overweging zijn, het gedraagt ​​zich precies hetzelfde als een Foreockey, maar met slechts één per daaropvolgend model. Op deze manier heeft de gebruiker slechts één profiel, terwijl hij misschien veel berichten heeft. Laten we nu onze login verbeteren en weergaven voor het profiel registreren. Bewerk eerst gebruikers/views.py en focus op de registerweergave:

# ... bedragen
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) # Zorg ervoor dat u deze regel toevoegt om een ​​profiel voor de gebruiker te maken
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Dit maakt eenvoudig een profiel voor de gebruiker, zonder een van de informatie in te vullen. Nu willen we ervoor zorgen dat het gebruikersaccount niet te vaak kan worden ingelogd, of in ieder geval niet te vaak worden geprobeerd, dus laten we de inlogweergave bijwerken.

# ... bedragen
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(): # Merk op dat we nu controleren of de gebruiker kan inloggen
            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: # Als de login niet succesvol was,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Dit is het deel waar we het gebruikersprofiel bijwerken
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Dus ze kunnen niet opnieuw inloggen voor een paar seconden
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Dit is het fundamentele fundamentele beveiliging. Zorg ervoor dat de site niet kwetsbaar is voor iemand die gewoon elke mogelijke wachtwoordcombinatie probeert, of zelfs een paar daarvan tegelijkertijd. Dit zal niet frustrerend zijn voor de gewone gebruiker die hun toegangscode kent en gewoon inlogt op een paar apparaten, maar het zal talloze phishing -robots uit de app houden. Merk op dat we een IF -instructie hebben toegevoegd met een variabele, can_login, dat zou een tijd in het verleden moeten zijn en deze bijwerken met elke mislukte login met dezelfde gebruikersnaam. Op deze manier kan een kwaadaardige gebruiker geen wachtwoord nergens zo snel raden. Het aantal seconden in de DateTime.Timedelta () kan ook worden bijgewerkt en de website zal veerkrachtiger zijn en toch iets minder bruikbaar met meer seconden. Ik raad 15 aan om mee te beginnen. Vergeet niet dat we een back -upscript hebben opgebouwd om ons werk op te slaan, dus laten we doorgaan en een back -up maken van wat we tot nu toe hebben om ervoor te zorgen dat we alles hebben opgeslagen. Voer de opdracht uit:

sudo backup
Nogmaals, dit zal uw werk tot nu toe besparen. Ik raad aan om frequente back -ups uit te voeren om uw werk op te slaan en u wilt misschien zelfs automatisch een back -upopdracht uitvoeren. U kunt dit doen met behulp van een UNIX -hulpprogramma genaamd Cron. Om dit hulpprogramma te activeren, voert u de volgende opdracht uit en voert u uw wachtwoord in:

sudo crontab -e
Als u nog niet optie 1 voor Nano selecteert, moet de teksteditor waarmee u al bekend bent en naar de onderkant van het bestand bladert met behulp van de pijltoetsen. Voeg de volgende regel toe:

0 * * * * sudo backup
Cron gebruikt het formaat minuut, uur, dag van maand, maand, dag van de week, waarbij een * of een nummer vertegenwoordigt wanneer het commando moet worden uitgevoerd. Met behulp van een 0 voor de minuut en * voor de rest van de opties kunnen we een opdracht uitvoeren op de eerste minuut van elk uur aan het begin van de minuut. Hierdoor kunnen we de code automatisch maken. Alle taken van Cron wanneer ze worden uitgevoerd met Sudo Run als root, dus we hoeven niet elk uur een wachtwoord in te typen. Om het gemakkelijker te maken om onze code te ondersteunen zonder een wachtwoord te gebruiken, laten we het wachtwoord voor onze back -upopdracht uitschakelen. We zullen dit doen door de volgende opdracht uit te voeren en een wachtwoord in te voeren:

sudo visudo
Laten we nu naar de onderkant van het bestand bladeren en een andere regel toevoegen:

ALL ALL=NOPASSWD: /bin/backup
Hiermee kunnen we de opdracht "back -up" als elke gebruiker uitvoeren, zonder een wachtwoord. Het formaat hiervoor is eenvoudig, prefix gewoon de lijn met "all all = nopasswd:/bin/" en eindig met de opdracht, bijvoorbeeld/bin/backup, die bestaat in/usr/bin/. Laten we nu gaan werken met e -mail. E -mail is echt belangrijk voor websites, omdat het een manier is om een ​​website veiliger te houden, te controleren of gebruikers echte mensen zijn, en zelfs marktproducten of diensten aan klanten. Veel mensen die internet bezoeken, controleren dagelijks hun e -mail en ontvangen allerlei marketingmails over producten en diensten waarin ze geïnteresseerd zijn. Er zijn een paar opties als het gaat om het inschakelen van e -mail op een Django -website, en u bent van harte welkom om te kiezen wat het beste voor u werkt. Eerst kunt u betalen voor een e -mailservice waarmee u e -mail vanuit uw domein kunt verzenden en minimale code vereist. Er zijn veel services die dit aanbieden, zoals Google Workspace, SendinBlue, MailGun en meer. Anders ben je goed uit het bouwenUw eigen e -mailservice binnen uw server helemaal opnieuw. Ik raad deze optie aan, hoewel het meer code is en mogelijk speciale hosting vereist. U kunt waarschijnlijk niet een e -mailserver starten vanaf uw thuiscomputer, dus laten we doorgaan en de configuratie en code onderzoeken om e -mail te verzenden voordat we een server in de cloud starten en onze eigen mailserver erin maken. Bewerk eerst instellingen.py met het volgende

nano app/settings.py
Waar App de naam is van de app die u hebt gemaakt met StartApp. Voeg de volgende regels toe:

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)
Zorg ervoor dat u deze wijzigt wanneer u klaar bent om uw app te implementeren, we zullen dit later opnieuw bezoeken. De instelling E -mail_adress moet de e -mail zijn die u wilt verzenden en het wachtwoord (e -mail_host_password) moet worden ingesteld op het wachtwoord dat u voor de server genereert. Ik laad het wachtwoord uit een configuratiebestand om het uit de code te houden met behulp van de volgende logica, boven deze regels in settings.py:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Vervolgens heb ik een JSON -bestand ingesteld met de configuratie in /etc/config.json met behulp van nano als volgt. Om het bestand te bewerken:

sudo nano /etc/config.json
Voeg de volgende regels toe:

{
	“EMAIL_HOST_PASSWORD”: “<some password here>”
}
We zullen het configuratiebestand blijven bewerken en alle wachtwoorden en toetsen toevoegen die we in de app zullen gebruiken. Laten we voor nu snel onderzoeken hoe we e -mail kunnen verzenden met Python. Laten we eerst een sjabloon maken voor een verificatie -e -mail die we naar onze gebruikers kunnen verzenden en deze in de map Gebruikerssjablonen kunnen plaatsen. Deze sjabloon wordt geschreven in HTML.

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

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

<p>The link will expire in 30 minutes.</p>
<p>If you have not requested a verification email you can simply ignore this email.</p>
<p>See you there,</p>
<p>Daisy</p>
 
Deze e -mail is vrij eenvoudig. Het neemt een context van een gebruiker, de basis -URL voor de site en een gebruikers -ID en token die worden gebruikt om de e -mail van de gebruiker te verifiëren. Zorg ervoor dat u de basis -URL in instellingen definieert.py voordat we wat Python -code schrijven om de sjabloon weer te geven. Ga je gang en voeg de volgende regels toe aan app/instellingen.py, tegen het begin.

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

BASE_URL = PROTOCOL + '://' + DOMAIN
Uiteindelijk, wanneer uw site klaar is voor internet en u deze implementeert, wilt u uw domein definiëren als de domeinnaam die u koopt om de site te vertegenwoordigen. Dit is de naam die u de NAVBAR typt om toegang te krijgen tot uw site. Voor nu kunt u het domein leeg laten of een tijdelijke aanduiding gebruiken. U wilt ook de site -naam wijzigen in een naam die u uw site wilt geven, naar keuze. Voordat we e -mail verzenden, laten we een tokengenerator maken, zodat we een accountactiveringstoken kunnen hebben dat nooit verloopt. We kunnen dit doen door een accountactiveringstoken te bouwen en te importeren dat op het volgende lijkt. Bewerk het bestand:

nano users/tokens.py
Voeg de volgende code toe:

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()
Deze basistokengenerator genereert een token dat we de gebruiker in een URL kunnen sturen en de gebruiker kan gebruiken om hun e -mail te verifiëren en hun account te activeren. Laten we vervolgens kijken hoe u een e -mail kunt verzenden. Gebruik gebruikers/e -mail.py met behulp van nano.

nano users/email.py
Het verzenden van de verificatie HTML -e -mail ziet er zo uit:

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)
Dit is vrij eenvoudig. We importeren de functies die we nodig hebben om de e -mail te verzenden, de e -mail weer te geven met sjablonen en onze instellingen, en vervolgens definiëren we de e -mail met de sjabloonnaam en verzenden deze naar de gebruiker met behulp van een functie. U zult merken dat we de functie niet hebben gedefinieerd om de e -mail te verzenden, send_html_email, dus laten we dit hieronder schrijven hieronder de code die we al hebben toegevoegd aan gebruikers/e -mail.py

def send_html_email(user, mail_subject, html_message):
    to_email = user.email
    username = user.username
    if to_email == '':
        return None
    unsub_link = settings.BASE_URL + user.profile.create_unsubscribe_link()
    html_message = html_message + "<p><a href=\"" + unsub_link +  "\" + title=\"Unsubscribe from " + settings.SITE_NAME + " emails\">Unsubscribe</a></p></body></html>"
    msg = EmailMultiAlternatives(mail_subject, strip_tags(html_message), settings.DEFAULT_FROM_EMAIL, [to_email], headers={'List-Unsubscribe' : '<' + unsub_link + '>'},)
    msg.attach_alternative(html_message, "text/html")
    profile = user.profile
    try:
        msg.send(fail_silently=False)
        if not profile.email_valid:
            profile.email_valid=True
            profile.save()
    except:
        profile.email_valid=False
        profile.save()
Dit is een beetje complexer en we zijn nog niet klaar om al deze code uit te voeren. Merk op dat we een UNSUB_LINK definiëren, de link die de gebruiker kan gebruiken om zich af te melden bij onze e -mails. Dit is belangrijk, omdat gebruikers zich moeten kunnen afmelden voor onze e -mails, tenzij ze ze op elk moment willen zien. We voegen ook een tekstalternatief toe aan ons bericht, het HTML -bericht dat is ontdaan van HTML -tags. Ten slotte controleren we of de e -mail verzonden, en als dit niet het geval is, markeren we het profiel van de gebruiker dat hun e -mail niet geldig is. Laten we teruggaan naar de gebruikersmodellen, zodat we dit allemaal kunnen laten werken. We moeten een functie definiëren om een ​​link naar afmelden te genereren en een Booleaans veld definiëren om te markeren dat de e -mail van de gebruiker niet geldig is. Voeg eerst de volgende import toe bovenaan gebruikers/modellen.py

nano users/models.py

# …
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
Laten we vervolgens functies toevoegen aan het gebruikersmodel om het token te maken en het token te controleren dat wordt gebruikt om de e -mail te activeren, evenals het veld om op te slaan of de gebruiker zijn e -mail met succes ontvangt. Voeg in gebruikers/modellen.py opnieuw de volgende code toe aan het einde van het model (ingesprongen 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) # Geldig voor 30 dagen
        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,})
Dit is vrij eenvoudig, we gebruiken een tijdstempel, wat een basiscryptografietool is, om een ​​token te maken dat na een bepaalde tijd afloopt, en we gebruiken ook een andere functie om te controleren of deze geldig is. We gebruiken deze tokens twee keer, eenmaal om de e -mail te verifiëren, en eenmaal voor een afmeldlink. Nu we deze hebben, is het laatste werk dat we moeten doen in de opvattingen. Laten we binnen gebruikers/views.py views toevoegen om het e -mailadres te verifiëren en om af te schrijven.

nano users/views.py
Voeg eerst de volgende import toe. Ik heb er een paar extra in gegooid, dus we hoeven later niet meer items te importeren.

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 # Zorg ervoor dat u de verzendfunctie van de verificatie -e -mail importeert
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
Je hebt misschien al een aantal van deze import, maar het doet geen pijn om ze te herhalen. U moet onder andere de verzendende e -mail verzendfunctie importeren, evenals Account_Activation_Token van gebruikers.tokens, onder andere import. Voeg nu, onderaan het bestand, de volgende code toe:

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)):
        # mafschrijven ze
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    # Anders verleid de inlogpagina
    messages.warning(request,f'Your unsubscribe link has expired. Please log in to unsubscribe.')
    next_url = reverse('users:unsubscribe', kwargs={'username': username, 'token': token,})
    return HttpResponseRedirect('%s?next=%s' % (reverse('login'), next_url))

def activate(request, uidb64, token):
    try:
        uid = force_str(urlsafe_base64_decode(uidb64))
        user = User.objects.get(pk=uid)
    except(TypeError, ValueError, OverflowError, User.DoesNotExist):
        user = None
    ip = get_client_ip(request)
    if user is not None and account_activation_token.check_token(user, token):
        user.profile.email_verified = True
        user.profile.save()
        user.save()
# SendWelcomeMail (verzoek, gebruiker)
        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})
Dit is veel code. Laten we het afbreken. De eerste functie, schoon en eenvoudig, maft de gebruiker af van de mailinglijst. De tweede functie activeert hun e -mail en u zult merken dat ik een becommentareerde functie, SendWelcomeMail heb toegevoegd. U bent van harte welkom om een ​​e -mailsjabloon en functiedefinitie te gebruiken om een ​​welkome e -mail te verzenden, dat heb ik gewoon nog niet gedaan. De laatste functie waarin ik heb gooide is belangrijk, omdat activerings -e -mails vervallen. Daarom moeten we de activeringsmail enig van de tijd opnieuw verzenden. We kunnen hiervoor een basisformulier gebruiken en de functie aanroepen om de verificatie -e -mail te verzenden. Voordat we dit doen, laten we ervoor zorgen dat het in de eerste plaats wordt verzonden, door een functieaanroep toe te voegen aan de registerweergave. Voeg deze regel toe vlak voor de omleiding in de registerweergave, def register, in gebruikers/views.py.

nano users/views.py

# … (Na) def register (verzoek):
            send_verification_email(user)
# … (Eerder) Redirect (
U hoeft de eerste en laatste regels niet toe te voegen in dat codefragment, zorg ervoor dat de registerweergave de verificatie -e -mail naar de gebruiker verzendt. Het zou er zo uit moeten zien:

# ... bedragen
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) # Zorg ervoor dat u deze regel toevoegt!
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Nu moeten we een formulier toevoegen om de activerings -e -mail te verzenden. Voeg in gebruikers/forms.py het volgende formulier toe:

# … (Bedragen)
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)
We hebben ook een sjabloon nodig die overeenkomt met dit verzonden e -mailactiveringsformulier. Laten we deze sjabloon toevoegen. Bewerk het bestand:

nano users/templates/users/resend_activation.html
Voeg vervolgens de volgende code toe aan het bestand.

{% 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 %}
Oef, dat is veel! Wanneer we de code op onze server implementeren, kunnen we HTML -e -mail verzenden en gebruikersaccounts activeren met een klik in de e -mail. We willen misschien ook een eenvoudige welkome e -mail verzenden, dus laten we eens kijken hoe we dat moeten doen. Terug in gebruikers/e -mail.py, voeg de volgende code toe:

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)
Ook hebben we een sjabloon nodig om al deze informatie weer te geven. Op mijn website ziet de sjabloon eruit als hieronder, maar u bent van harte welkom om het te formatteren zoals u leuk vindt.
 
<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>
 
Merk op dat we geen sluitende body- of HTML -tags hebben, omdat we deze toevoegen wanneer we de HTML -afmelding -link toevoegen. Deze zijn belangrijk, maar we willen ze niet twee keer definiëren. Dus wat is het volgende? We hebben een lange weg afgelegd. We moeten echt klaar zijn om de site op een server te implementeren. We kunnen de @Login_Required Decorator toevoegen en onze weergaven beveiligen, gebruikersaanmeldingen nemen, conforme e -mail en cache -informatie verzenden, die de basis vormt van wat een website moet doen om relevant te blijven. We voegen een paar meer nuttige functies toe en bouwen vervolgens een basis voor het implementeren van onze code op een externe server, het instellen van een e -mailserver, domeinconfiguratie en filters om onze site veilig en geschikt te maken. We hebben ook een weergave -weergave nodig, dus laten we dat heel snel toevoegen. Django's ingebouwde wachtwoordresetweergave is verbroken in sommige functies, maar we zullen kijken hoe we onze eigen weergave, e -mailsjabloon, formulieren en URL -patronen kunnen schrijven. Dit is hoe de weergave eruit ziet, in gebruikers/views.py

# ... Importeren
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)
Dit formulier is ingebouwd in Django, maar we hebben een sjabloon nodig om de wachtwoordreset te bevestigen, gebruikers/sjablonen/gebruikers/wachtwoord_reset_confirm.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Reset Password</button>
            </div>
        </form>
{% endblock content %}
 
We hebben ook een sjabloon om een ​​wachtwoordreset -e -mail te verzenden, met een eenvoudig formulier, in gebruikers/sjablonen/gebruikers/wachtwoord_reset.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Request Password Reset</button>
            </div>
        </form>
{% endblock content %}
 
De sjabloon voor de e -mail zelf is eenvoudig, het is een basis HTML -bestand dat een link weergeeft om het wachtwoord te resetten, in gebruikers/sjablonen/gebruikers/wachtwoord_reset_email.html. Django zal dit bestand automatisch interpreteren.
 
<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>
 
We hebben ook nog twee sjablonen nodig. De eerste is om te bevestigen dat de e -mail is verzonden. Weergaven hiervoor zijn al in Django, dus we moeten ze gewoon aanspreken in de urls.py. Deze sjabloon bevindt zich bij gebruikers/sjablonen/gebruikers/wachtwoord_reset_done.html
 
{% extends 'base.html' %}
{% block content %}
  <div class="media-body">
    <div class="alert alert-info">
        An email has been sent with instructions to reset your password.
    </div>
  </div>
{% endblock content %}
 
En ten slotte, om te bevestigen dat de wachtwoordreset is voltooid, is gebruikers/sjablonen/gebruikers/wachtwoord_reset_complete.html
 
{% extends 'base.html' %}
{% block content %}
 <div class="media-body">
    <div class="alert alert-info">
        Your password has been set.
    </div>
    <a href="{% url 'users:login' %}">Sign In Here</a>
  </div>
{% endblock content %}
 
Nu hebben we URL -patronen nodig voor deze weergaven. Voeg bij gebruikers/urls.py de volgende URL -patronen toe:

urlpatterns = [
    # ... eerdere URL's hier
    path('password-reset/',
         auth_views.PasswordResetView.as_view(
             template_name='users/password_reset.html',
             html_email_template_name='users/password_reset_html_email.html'
         ),
         name='password_reset'),
    path('password-reset/done/',
         auth_views.PasswordResetDoneView.as_view(
             template_name='users/password_reset_done.html'
         ),
         name='password_reset_done'),
    path('password-reset-confirm/<uidb64>/<token>/',
         auth_views.PasswordResetConfirmView.as_view(
             template_name='users/password_reset_confirm.html'
         ),
         name='password_reset_confirm'),
    path('password-reset-complete/',
         auth_views.PasswordResetCompleteView.as_view(
             template_name='users/password_reset_complete.html'
         ),
         name='password_reset_complete'),
]
Vier sjablonen, dat is veel! Maar nu kunnen we zeker zijn om het wachtwoord van de gebruiker te resetten wanneer we moeten, allemaal vanuit de webbrowser. Ik begrijp dat dit veel code is. Als het een beetje over je hoofd lijkt, is dat oké. Je zult verbeteren, je begrip zal verbeteren en je zult snel veel competenter worden met code. Als je helemaal verloren bent, raad ik aan om later terug te keren naar deze software na te hebben gewerkt aan een zelf-leren om online te coderen. Deze zijn meestal gratis om aan de slag te gaan en zullen je door alles begeleiden wat je nodig hebt om succesvol te zijn wanneer je terugkomt naar dit project. Als u het gevoel hebt dat u klaar bent om door te gaan, verder te lezen, dan zullen we de implementatie van uw code naar een externe server behandelen en een e -mailserver instellen, en uw implementatie automatiseren met behulp van BASH, zodat u altijd een nieuw project kunt instellen met Een paar eenvoudige opdrachten. Het laatste wat we moeten doen voordat we naar een externe server worden geïmplementeerd, is onze site een beetje veiliger maken. Je zultMerk op dat de inlogweergave alleen een gebruikersnaam en wachtwoord nodig heeft en er is geen multi -factor authenticatie of eenmalige code. Dit is een eenvoudige oplossing en met dezelfde code kunnen we onze site sms -berichten laten verzenden en zelfs reageren op sms -berichten die naar de server zijn verzonden. Om te beginnen gaan we terug naar de gebruikersmodellen en voegen we een tijdstempel -ondertekenaar toe die elke login vertegenwoordigt. We zullen ook een unieke, roterende ID toevoegen aan het gebruikersmodel dat zal worden gebruikt om extra beveiliging aan onze login toe te voegen. Het bewerken van de gebruikersmodellen, gebruikers/modellen.py, voeg het volgende toe

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# Zorg ervoor dat u de UUID-, Timestamp -ondertekenaar- en URL -generator (achteruit) importeert
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='')
    # Voeg deze code hier toe
    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)

    # En voeg deze functie toe
    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) # Geldig voor 3 minuten
        except (BadSignature, SignatureExpired):
            return False
        return True
Zorg ervoor dat uw gebruikers/modellen.py er zo uitziet, naast de reacties (code op de regels met #). Dit afbreken, het is eenvoudig. We hebben een paar import, een tijdstempel, een cryptografisch hulpprogramma dat een veilige code kan genereren en deze kan verifiëren om ervoor te zorgen dat het geldig is, slechts eenmaal wordt gebruikt en niet ouder dan een bepaald aantal seconden. We gebruiken ook een UUID, een unieke identificatie die onze gebruiker identificeert bij het ondertekenen van het token, en in de URL waar het token naar de gebruiker wordt verzonden. We zullen deze basiscryptografie gebruiken om een ​​weerweergave met twee factoren authenticatie te bouwen. Voordat we iets anders doen, laten we de migraties uitvoeren, zodat onze gebruikersmodellen worden bijgewerkt. Voer in de map met management.py de volgende opdrachten uit om de migraties te maken en te voltooien.

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Dit is belangrijk omdat elke keer dat we wijzigingen aanbrengen in de modellen, we de tabellen moeten maken en de database moeten bijwerken met standaardwaarden voordat we de modellen daadwerkelijk kunnen gebruiken. Laten we vervolgens onze inlogweergave improviseren om een ​​secundaire authenticatieweergave om te leiden. Verwijder in gebruikers/views.py de inlogfunctie en leid naar de URL die we zojuist hebben gegenereerd in de gebruikersmodellen.

# ... bedragen

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(): # Merk op dat we nu controleren of de gebruiker kan inloggen
            # Verwijder de Auth_Login -functie die hier was
            messages.success(request, 'Your password was accepted. Please continue.')
            if user.profile.mfa_enabled:
                return redirect(user.profile.create_auth_url()) # Let op dat we hier doorgaan naar een nieuwe URL
            else: # Als de gebruiker multi-factor authenticatie niet gebruikt, logt u ze gewoon in.
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # Als de login niet succesvol was,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Dit is het deel waar we het gebruikersprofiel bijwerken
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Dus ze kunnen niet opnieuw inloggen voor een paar seconden
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Dus dit is vrij eenvoudig, we hebben nu een manier om de Two Factor -verificatieweergave om te leiden wanneer we deze maken. We hebben ook een fallback voor het geval de gebruiker geen telefoonnummer heeft toegevoegd. We zullen een basisweergave toevoegen om binnenkort een telefoonnummer toe te voegen en binnenkort in te loggen met een sms -bericht. Eerst hebben we een eenvoudige manier nodig om een ​​sms -bericht van onze code te verzenden. Om dit te doen, kunnen we kiezen uit een aantal API's, maar de gemakkelijkste is naar mijn mening Twilio. Ze bieden ook goede prijzen voor kleinere projecten, evenals bulkkortingen. Maak een account aan op twilio.com, vul enkele details over uw project in, koop een telefoonnummer en kopieer uw API -toetsen naar uw instellingen.py. Voeg vervolgens deze code toe onder een nieuw bestand, gebruikers/sms.py.

nano users/sms.py

# Importeer alle benodigde pakketten
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

# Deze code verzendt de tekst met Twilio
def send_text(target_phone, text):
    from twilio.rest import Client
    try:
        client = Client(account_sid, auth_token)
        if len(target_phone) >= 11:
            message = client.messages.create(
                to=target_phone,
                from_=source_phone,
                body=text)
    except:
        print(traceback.format_exc())

# Een helperfunctie om een ​​nummer te krijgen met zoveel cijfers
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# Stuur de tekst om de gebruiker te verifiëren
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)))

# Stuur een gebruiker elke tekst met deze functie
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# Valideer de code met deze functie
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

# Valideer de tijd
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
Zorg ervoor dat u uw instellingen op de juiste manier wijzigt en deze regels toevoegt met uw sleutels:

# Zorg ervoor dat u deze van uw Twilio Dashboard kopieert
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 # Het aantal minuten dat de TFA -pagina actief is, eenmaal is geïnstalleerd
Ten eerste hebben we formulieren nodig voor onze twee factor authenticatieweergaven. Gebruikers/formulier.py bewerken, voeg de volgende code toe.

# ... bedragen
from django import forms

# Een formulier voor het invoeren van ons telefoonnummer
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

# Een formulier voor authenticeren
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.'
    }
Laten we vervolgens de weergaven maken in gebruikers/views.py

# … Importeren
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})
We hebben ook sjablonen nodig voor beide opvattingen. Laten we eerst de MFA -sjabloon toevoegen.

nano users/templates/users/mfa.html
Voeg deze HTML -code toe aan de sjabloon
 
{% 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 %}
 
Dit is behoorlijk zelfverklarend. Het formulier verzendt een code of een lege code en u merkt in de weergave in de weergave die we de code verzenden als we een lege code ontvangen. Dan hebben we slechts twee verzendknoppen, en op deze manier kunnen we de code met beide knop verzenden. Vervolgens voegen we een eenvoudig formulier toe om een ​​telefoonnummer toe te voegen.

nano users/templates/users/mfa_onboarding.html
Voeg de volgende HTML toe:
 
{% 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 %}
 
Dit formulier is een stuk eenvoudiger, het maakt gewoon het telefoonnummerformulier dat we hebben gemaakt en laat de gebruiker een telefoonnummer toevoegen. Dit ziet er echt goed uit! Zolang alles goed is ingesteld, moeten we berichten kunnen verzenden en de gebruiker inloggen met hun telefoonnummer zodra we de URL -patronen toevoegen. Het laatste wat we moeten instellen is een profielweergave, zodat we ervoor kunnen zorgen dat de gebruiker zijn telefoonnummer kan wijzigen zonder ingelogd te worden. Ook zullen we uiteindelijk een optie "Stop om te stoppen" toe te voegen, zodat de gebruiker kan sms'en "Stop" om zich af te melden voor toekomstige tekstberichten. Laten we een profielweergave toevoegen aan de gebruikers/views.py. Deze weergave zal de bio, e -mail, gebruikersnaam en telefoonnummer van de gebruiker bijwerken en ons in staat stellen om multi -factor authenticatie mogelijk te maken. Ten eerste hebben we nog twee formulieren nodig in gebruikers/vormen. Py

# ... bedragen
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']
Vervolgens kunnen we een weergave maken om beide vormen te gebruiken. Gebruikers/views.py bewerken en de weergave toevoegen.

# Voeg deze import toe
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)
We hebben ook een sjabloon nodig voor deze weergave.

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

{% endblock content %}
{% block javascript %}
var form = document.getElementById('profile-form');
$('input').change(function(){
	var formdata = new FormData(form);
	$.ajax({
		url: window.location.href,
		type: "POST",
		data: formdata,
		processData: false,
		contentType: false,
		timeout: 1000 * 60,
                success: function(data) {
                  $(posted).removeClass("hide");
		  setTimeout(function() {
			$(posted).addClass("fade-hidden");
			setTimeout(function() {
				$(posted).addClass("hide");
				$(posted).removeClass("fade-hidden");
			}, 2000);
		  }, 2000);
                }
	});
});
{% endblock %}
 
Je zult merken dat dit een vrij eenvoudige vorm is, maar heeft wat JavaScript erin die automatisch de inhoud van het formulier plaatst terwijl ze worden bijgewerkt. Dit is handig om te hebben, dus u kunt bewerkingen maken zonder elke keer op te dienen. Vervolgens hebben we URL's nodig die al deze weergaven vertegenwoordigen in de URL -patronen van de gebruikers. Gebruikers/urls.py bewerken en deze code toevoegen:

# … Vorige code, import
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
# ... URL -patronen die we eerder hebben ingevoerd, voeg de volgende drie regels toe
    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'),
]
Dit is een goed moment om ons project te testen. Maar laten we eerst nog een back -up uitvoeren.

backup
En voer de server uit. Voordat we naar een Linux -server worden geïmplementeerd, is het een goed idee om twee factorauthenticatie op het account mogelijk te maken. We doen dit naar onze profiel -URL,/Users/Profile/, en controleren het vakje om authenticatie in te schakelen na het invoeren van ons telefoonnummer en vervolgens het formulier in te dienen.

python manage.py runserver localhost:8000
Bezoek de webpagina door naar uw webbrowser te gaan, ik gebruik Google Chrome in dit voorbeeld en voer de URL https in: // localhost: 8000/accounts/profiel/ U kunt indien nodig inloggen en twee factorauthenticatie inschakelen. Dit project heeft een server nodig om uit te voeren, zodat het echt e -mail kan verzenden. Maar eerst hebben we een manier nodig om fouten te zien. U zult merken dat als u de server uitvoert in de foutopsporingsmodus, met instellingen.debug gelijk aan true, de server automatisch fouten toont. Om fouten te tonen zonder de foutopsporingsmodus te gebruiken, die onveilig is op een productieserver, moeten we er een weergave voor toevoegen. De belangrijkste fouten die we moeten kunnen hanteren, zijn: Fout 500 - Een probleem met onze code Fout 404 - Een pagina die niet werd gevonden (Broken URL) Fout 403 - Een toestemming geweigerd fout Laten we een nieuwe app toevoegen om deze fouten te verwerken, fouten genoemd.

python manage.py startapp errors
Voeg dit toe aan de instellingen.py zoals we eerder deden, in de instelling Installed_apps, en begin met het toevoegen van verwijzingen naar enkele weergaven in app/urls.py, waarbij app de naam is van uw django -project.

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
Dit is alles wat we nodig hebben, behalve foutopvattingen, sjablonen en een klein beetje middleware. Laten we die zoals zo definiëren:

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

# Maak hier uw mening.
@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.'})
Laten we vervolgens de middleware definiëren om deze fouten af ​​te handelen. We zullen dit doen door eerst toe te voegen aan middleware_classes in settings.py, met de naam van onze middleware.

MIDDLEWARE_CLASSES = [
    # ... Vorige middleware
    'errors.middleware.ExceptionVerboseMiddleware,
]
Laten we vervolgens de middleware toevoegen.

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.')
We voegen een functie toe om de huidige uitzondering te krijgen met behulp van een threading -lokaal, waardoor we fouten in onze code kunnen traceren. In termen van sjablonen hebben we er maar één nodig, omdat we de titel in de weergave dynamisch definiëren. De sjabloon hoeft alleen de titel en "Trace" te geven, onze fouttraceback uit de context.

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
Dit is onze eenvoudigste sjabloon tot nu toe, maar zo gemakkelijk is het om de fouten in ons project te zien. Laten we vervolgens de foutopsporing in instellingen uitschakelen.

nano app/settings.py
Zoek deze regel waar deze is ingesteld op waar en verander deze in False

DEBUG = False
Ga je gang en back -up van de app nu. We zijn klaar om te implementeren naar een externe Linux -server en blijven vanaf daar functies toevoegen.

sudo backup
Voordat we deze code op een server plaatsen, moeten we bedenken dat er enkele problemen kunnen zijn met de code. Afhankelijk van de zaak, zullen sites die op hen zijn geplaatst, problemen hebben met het plaatsen van spam en moeite met het verwijderen van de spam. Dit zou niet onmiddellijk moeten gebeuren, maar als het gebeurt, zullen we later onderzoeken hoe we de spam automatisch op de site kunnen matigen en het moeilijker kunnen maken voor robots om toegang te krijgen Een scan van hun ID of een biometrische scan, zoals een vingerafdruk of gezichtsherkenning. Kijkend naar het voorbeeld van multi -factor authenticatie dat we hebben onderzocht, kunnen in productie dingen anders zijn. Merk op hoe we aanmeldingen beperken en de tokens vervallen. Als robots toegang hebben tot een site, kan twee factorauthenticatie moeilijker zijn, omdat deze codes kunnen invoeren tegelijkertijd de gebruiker. Laten we, om dit te bestrijden, een model in de gebruikersmodellen gebruiken, en geven ze aan hoe we met de site omgaan wanneer we dat zijnauthenticeren met behulp van multi -factor authenticatie met een telefoonnummer. We zullen ook een optie toevoegen om te authenticeren met e -mail. Begin met het bewerken van de gebruikersmodellen met

nano users/models.py
Dit is hoe het model dat we toevoegen, eruit zou moeten zien. We hebben geen methoden nodig, alleen variabelen om een ​​ID op te slaan, de gebruiker, de tijdstempel, vervaldatum, lengte en pogingen tegen elke multi -factor authenticatie (een code zoals 123456 verzonden naar een telefoon of e -mail).

# Een basistoken dat wordt gebruikt om in te loggen op de website
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)
Laten we ook een voorrecht aan onze gebruiker toevoegen, en we zullen het voorlopig handmatig instellen, voordat we uiteindelijk automatisch migreren naar het in dienst nemen van bevoorrechte gebruikers. Voeg in de gebruikersmodellen deze regel toe aan het profiel:

    vendor = models.BooleanField(default=False)
Zoals bij elke wijzigingen in de database, moeten we migraties aanbrengen en de database migreren wanneer we een modellen.py -bestand in Django bewerken. Vergeet niet dat we hiervoor eerst de bron gebruiken (als het nog niet is gebruikt sinds de terminal open was) en vervolgens python manag.py om de migraties te maken en te migreren.

cd project-directory-you-named # (indien nodig)
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Voor nu kunt u alle accounts inschakelen die u als leveranciers hebt gemaakt met behulp van de shell.

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
Laten we nu onze multi -factor authenticatieweergave evolueren om dit token te gebruiken. Eerst moeten we onze MFA -helperhulpprogramma's wijzigen. Nano gebruiken,

nano users/mfa.py

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

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

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

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

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

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

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

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

# Verifieer de gebruiker met behulp van zijn e -mail- of telefoonnummer
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() # Filter het token door de waarde die is doorgegeven in de URL (een UUID)
    if not token: token = MFAToken.objects.create(user=User.objects.filter(profile__uuid=username).first(), uid=username, expires=timezone.now() + datetime.timedelta(seconds=115)) # Als deze sessie niet is gemaakt, maak deze dan aan
    user = User.objects.filter(id=token.user.id).first() # Haal de gebruiker uit het token
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # Als ze al zijn geverifieerd, log ze dan in
    if not user: raise PermissionDenied() # Ontken als er geen gebruiker is gevonden
    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): # Controleer het AUTH -token
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Log in de gebruiker in als ze nog niet zijn ingelogd
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # Stel een verval van op hun multi -factor authenticatie
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # Direct de gebruiker om naar de volgende pagina
    if not user.profile.mfa_enabled: # Controleer of MFA is ingeschakeld
        if not check_verification_time(user, token): # Controleer de tijd
            user.profile.mfa_enabled = False # Wis het telefoonnummer
            user.profile.enable_two_factor_authentication = True # Schakel MFA in
            user.profile.phone_number = '+1' # Schakel het telefoonnummer uit
            user.profile.save() # Sla het profiel op
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Log de gebruiker in als zijn MFA niet is ingeschakeld
            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): # Als het verzoek een postverzoek is
        form = TfaForm(request.POST) # Instantiëren de vorm
        code = str(form.data.get('code', None)) # Krijg de code
        if code and code != '' and code != None: # Zorg ervoor dat het niet leeg is
            token_validated = user.profile.check_auth_token(usertoken) # Controleer het AUTH -token
            p = user.profile
            is_verified = check_verification_code(user, token, code) # Controleer de code
            p.mfa_authenticated = is_verified
            if token_validated: # Als alles
                if is_verified: # Is in orde
                    user.profile.mfa_enabled = True # MFA inschakelen (indien nog niet ingeschakeld)
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Log in de gebruiker in
                    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(): # Bouw een querystring voor de volgende parameter (indien aanwezig)
                        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) # Omleiden
                    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: # Als het token ongeldig was
                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: # Als er te veel pogingen waren
                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): # Stuur de e -mail (of sms)
                send_mfa_verification_email(user, token)
            else:
                send_verification_text(user, token)
            messages.success(request, "Please enter the code sent to your phone number or email. The code will expire in 3 minutes.")
        elif user.profile.can_send_mfa < timezone.now() + datetime.timedelta(seconds=115):
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    if request.user.is_authenticated: return redirect(reverse('/'))
    # Render het formulier (voor get -aanvragen)
    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'})
Wanneer we deze code toevoegen, moet u de functie importeren om een ​​e -mail te verzenden. Bovenaan het bestand viewt de gebruikers (met andere imports) toevoegen

from .mfa import send_verification_email as send_mfa_verification_email
Nu moeten we die functie schrijven voordat dit zal werken. Het zou onze e -mailfunctie moeten uitbreiden en eenvoudig een e -mail naar de gebruiker verzenden met de verificatiecode.

nano users/mfa.py

def send_verification_email(user, token):
    length = user.profile.verification_code_length
    code = random.randint(get_num_length(1, length), get_num_length(9, length));
    token.token = code
    token.expires = timezone.now() + datetime.timedelta(minutes=settings.AUTH_VALID_MINUTES)
    token.save()
    send_html_email(user, "Your verification code for {} is {}".format(settings.SITE_NAME, str(code)), "<p>Dear {},</p><p>Your verification code for {} is {}. Thank you for using this code to secure your account.</p><h2>{}</h2><p>Sincerely, {}</p>".format(user.profile.name, settings.SITE_NAME, str(code), str(code), settings.SITE_NAME))
Dus dit werkt allemaal geweldig, nu hebben we een multi -factor authenticatiesysteem dat afhankelijk is van een telefoonnummer of e -mail om in te loggen. Maar we hebben ook een manier nodig om gebruikers te verwijderen, of op zijn minst verbergen die niet met onze voorwaarden samenwerken. Dit kunnen spammers, robots of iemand zijn die niet goed betekent voor ons werk. Bekijk een weergave die ik heb om gebruikers op mijn website te bewaken:

# bedragen
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor # We moeten deze test maken

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # Koop een lijst met gebruikers
    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', { # Retour u gebruikers in een sjabloon
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
Merk op dat deze code een test gebruikt, we moeten deze test in een tests.py -bestand verklaren en importeren. Gebruikers/tests.py bewerken, laten we de test maken.

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
Dit is in combinatie met de users/users.html -sjabloon, die er zoiets uitziet:
 
{% 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 %}
 
Merk op dat de sjabloon een andere sjabloon bevat, gebruikers/_user.html. Bij het gebruik van een sjabloon die een subtemplate heeft en niet gebruikt, is het een goed idee om een ​​onderstrepingsteken (_) toe te voegen vóór de naam van het bestand om uit te breiden, om sjablonen te onderscheiden. Merk op dat dit veel Jinja is, je hebt misschien niet al deze variabelen gedefinieerd. Maar dit is hoe mijn code eruit ziet.
 
{% load app_filters %}
<div>
<img src="{{ user.profile.get_image_url }}" alt="@{{ user.profile.name }}'s profile photo" width="120" height="120" align="left" style="margin-top:5px; margin-right:10px; margin-bottom:10px; border-radius: 50%;"/>
    <div class="article-metadata">
      <p class="mr-2">@{{ user.username }} - {{ user.profile.name }} ({{ user.profile.preferred_name }})</p>
      <small class="text-muted">Last seen {{ user.profile.last_seen|date:"F d, Y" }} {{ user.profile.last_seen|time:"H:i" }}</small>
      <small class="text-muted">Joined on {{ user.profile.date_joined|date:"F d, Y" }} {{ user.profile.date_joined|time:"H:i" }}</small>
      <small>{{ user.email }}</small>
      {% if user.profile.phone_number %}<small><i class="bi bi-phone-fill"></i>{{ user.profile.phone_number }}</small>{% endif %}
      {% if user.verifications.last %}
      <small>'{{ user.verifications.last.full_name }}'</small>
      <small><i class="bi bi-123"></i> {{ user.verifications.last.document_number }}</small>
      <small><i class="bi bi-calendar-heart-fill"></i> {{ user.verifications.last.birthdate }}</small>
      <a href="{{ user|document_front }}" class="btn btn-sm btn-outline-primary" title="ID front"><i class="bi bi-person-badge-fill"></i> ID front</a>
      <a href="{{ user|document_back }}" class="btn btn-sm btn-outline-primary" title="ID back"><i class="bi bi-upc-scan"></i> ID back</a>
      {% endif %}
      <small># {{User.id}} </mall>
      <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>
 
We hebben ook een andere subtemplate nodig, toggle_active.html. Deze sjabloon moet een formulier zijn waarmee we kunnen schakelen of een gebruiker actief is.
 
<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>
 
We moeten ook een weergave toevoegen om gebruikersactiviteit en geschikte URL -patronen te schakelen. Terwijl we bezig zijn, laten we een weergave toevoegen om een ​​gebruiker te verwijderen voor het geval we dat nodig hebben.

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


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

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

    def test_func(self): # Test of de gebruiker superuser is en toestemming heeft om te verwijderen
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
Hoewel dit praktisch is wanneer dat nodig is, zou het verwijderen van een gebruiker meestal niet nodig moeten zijn, kunnen we gewoon de zichtbaarheid van gebruikers die de site bezoeken schakelen als we ze moeten afwijzen. De URL -patronen die we hebben toegevoegd, zien er zo uit. Met nano, bewerk gebruikers/urls.py en voeg deze regels toe:

nano users/urls.py
De regels moeten in de lijst met paden in de gebruikersweergaven gaan, vóór het einde "]" maar na het begin "[".

# …
    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'),
# …
Zorg er nu voor dat u de site een back -up maakt, zodat u deze op de webserver kunt downloaden waaraan we blijven werken. Van de opdrachtregel,

sudo backup
Nu wordt onze site een back -up gemaakt. Dus nu hebben we nog een paar nuttige functies. Maar hoe zit het met het grote geheel hier? Deze code is nog steeds niet toegankelijk via internet, we hebben nog geen e -mailserver en we moeten onze app uitbreiden om een ​​uitgebreid verificatieproces op te nemen, evenals soepele lay -outs om ons te helpen de site te verkennen, samen met beveiligde protocollen voor authenticerende bevoorrechte gebruikers . We zullen dit allemaal bereiken. Het belangrijkste voor nu zal deze code gewoon online krijgen, wat we kunnen doen met slechts een paar regels bash op een Ubuntu -server. U moet hiervoor een server huren, tenzij u thuis een server hebt en een zakelijk internetabonnement waarmee u poorten kunt openen. Ik heb persoonlijk mijn website uitgevoerd op een HP Z440 die in mijn appartement is geïnstalleerd, maar het is meestal veel goedkoper voor basisbehoeften om een ​​virtuele privéserver (VPS) te huren. Houd er rekening mee dat de code die we nu uitvoeren relatief dun is, deze moet worden onderhouden en verbeterd voordat we dat zijnKlaar om te gebruiken wat we hebben om een ​​product te bouwen. Zorg ervoor dat u voorzichtig bent wat u doet met internet, zorg ervoor dat als u deze site publiekelijk op het web op een Linux -server implementeert, u een plan hebt om ongewenste interacties met uw website te blokkeren. Dit zal in het begin waarschijnlijk geen probleem zijn, maar we zullen verschillende oplossingen onderzoeken om dit te bestrijden, waaronder machine learning, kunstmatige intelligentie en computer vision. Wanneer het een probleem wordt, kijk dan verder in deze tekst voor een oplossing. Wat een VPS huurt, zijn er veel plaatsen waar u naartoe kunt. Google Cloud heeft VPS -servers, Ionos, Kamatera, Amazon AWS en meer providers bieden cloudserveroplossingen die aan onze behoeften voldoen. U moet door hun formulieren klikken en een plan selecteren om aan de slag te gaan. U kunt met een provider gaan met een basisplan, maar zorg ervoor dat u de poortpoorten kunt openen om een ​​e -mail te openen om e -mail te verzenden (dit moet poort 587 en poort 25 zijn), sommige providers blokkeren deze poorten. Tot nu toe heb ik deEST -ervaring met Ionos en Kamatera, beide sta me toe om onbeperkte e -mail te sturen en hun prijzen zijn vrij goedkoop. U zult verbinding maken met uw nieuwe server via een protocol genaamd SSH of Secure Shell, waarmee u op afstand met de server kunt interface met de server, precies zoals uw personal computer, vanaf uw personal computer. Wanneer u de server instelt, zal de hostingprovider u waarschijnlijk vragen om een ​​SSH -toets toe te voegen, of zij zullen u een gebruikersnaam en wachtwoord geven. De SSH -toets is hoe u inlogt op de server vanaf de opdrachtregel om de code te bewerken. Gebruik de onderstaande SSH-Keygen-opties om een ​​SSH te genereren

ssh-keygen
Sla het bestand op en overschrijf het als dat nodig is, het is goed om uw SSH -toetsen te roteren als u dat nog niet hebt gedaan. Nu kunt u de volgende opdracht gebruiken om uw SSH -toets te zien. U wilt het naar uw externe server kopiëren, zodat u het kunt gebruiken om te verifiëren.

cat ~/.ssh/id_rsa.pub
Als u geen SSH-sleutel kon zien bij het typen van die opdracht (een lange reeks cijfers en letters die beginnen met "SSH-RSA AAA"), probeer dan een RSA-sleutel te genereren (ze zijn veiliger, dus ik adviseer ze om ze te gebruiken .) De volgende code genereert een 4096 bit RSA SSH -toets.

ssh-keygen -t rsa -b 4096
Maak een VPS met Ubuntu, maar u bent van plan dit te doen. Nadat u een VPS hebt gemaakt door de formulieren op de website van de providers te klikken (Kamatera.com, Ionos.com of vergelijkbaar), wilt u inloggen. Gebruik hiervoor de SSH -opdracht met uw IP -adres (het adres Dat lijkt op xx.xx.xx.xx). U moet ook gevoelig zijn voor de standaardgebruikersnaam op de server die we hebben gemaakt, bijvoorbeeld Ubuntu.

ssh ubuntu@XX.XX.XX.XX
U kunt om een ​​wachtwoord worden gevraagd, als u om een ​​wachtwoord wordt gevraagd, voert u dit in. We zullen de standaardgebruikersnaam niet gebruiken, dus laten we beginnen met het maken van een nieuwe gebruiker en het toevoegen van een SSH -toets aan hun account. Laten we beginnen met het toevoegen van een nieuw SSHD_CONFIG -bestand, dat de server vertelt hoe SSH te gebruiken.

nano sshd_config

# Dit is het SSHD Server-systeembrede configuratiebestand.  Zien
# sshd_config (5) voor meer informatie.

# Deze SSHD is samengesteld met pad =/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# De strategie die wordt gebruikt voor opties in de standaard SSHD_config verzonden met
# OpenSSH is om opties op te geven met hun standaardwaarde waar
# mogelijk, maar laat ze becommentarieerd.  Ongecomplimeerde opties overschrijven de
# Standaardwaarde.

# Poort 22
# Adresfamilie elke
# Lijstadres 0.0.0.0
# Luister Adres ::

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

# Cijfers en sleutel
# Rekeylimit standaard geen

# Houtkap
# Syslogfaciliteit auth
# Loglevelinfo

# Authenticatie:

# Logringracetime 2m
# PermitRootLogin verboden Password
# StrictModes ja
# MaxAuthtries 6
# Maxessions 10

PubkeyAuthentication yes

# Verwacht .SSH/Authorized_Keys2 zal in de toekomst standaard worden genegeerd.
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# Geautoriseerd principals

# Geautoriseerde KeysCommand geen
# AuthorizedKeysCommanduser Niemand

# Om dit te laten werken, hebt u ook hostsleutels nodig in/etc/ssh/ssh_ bekende_hosts
# Host -basedauthentication nr
# Wijzig naar ja als u niet vertrouwt ~/.ssh/bekende_hosts voor
# Host -basedauthenticatie
# Negeerderbekend Hosts nee
# Lees de ~/.rhosts van de gebruiker en ~/.shosts niet
# Onwetendhosts ja

# Wijzig hier om NEE!
PasswordAuthentication no
# PermitemPtypassWords Nee

# Wijzig naar ja om uitdagingen voor uitdagingsrespons mogelijk te maken (pas op voor problemen met
# Sommige PAM -modules en draden)
KbdInteractiveAuthentication no

# Kerberos -opties
# Kerberosauthentication nr
# KerberosorlocalPasswd ja
# Kerberosticketcleanup ja
# Kerberoscoted rod nr

# GSSAPI -opties
# GSSAPIAuthentication no
# GssapicleanUpcredentials Ja
# Gssapistrictacceptorcheck ja
# Gssapikeyexchange nr

# Stel dit in op 'ja' om PAM -authenticatie, accountverwerking mogelijk te maken,
# en sessieverwerking. Als dit is ingeschakeld, zal PAM -authenticatie
# worden toegestaan ​​door de KBDinteractiveAuthentication en
# WachtwoordAuthentication.  Afhankelijk van uw PAM -configuratie,
# PAM -authenticatie via KBDinteractiveAuthentication kan omzeilen
# de instelling van "permitRootLogin zonder-Password".
# Als u gewoon wilt dat het PAM -account en de sessiecontroles zonder uitvoeren
# PAM -authenticatie, schakel dit vervolgens in, maar stel wachtwoordAuthentication in
# en KBDinteractiveAuthentication to 'No'.
UsePAM yes

# ToyAgentforwarding Ja
# Toegestaan ​​met ja
# Gatewayports nee
X11Forwarding yes
# X11displayoffset 10
# X11uselocalhost Ja
# Permitty ja
PrintMotd no
# PrintLastlog ja
# Tcpkeepalive ja
# Permittuenvironivering in
# Compressie vertraagd
# Clientalive interval 0
# ClientaliveCountMax 3
# Gebruikte in
# Pidfile /run/sshd.pid
# MaxStartups 10: 30: 100
# Pemittunl nee
# Chrootdirectory geen
# Versie addendum geen

# Geen standaardbannerpad
Banner /etc/banner

# Sta de klant in staat om de locale omgevingsvariabelen te passeren
AcceptEnv LANG LC_*

# Verhaal de standaard van geen subsystemen
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Voorbeeld van overhegende instellingen per gebruiker
# Match user anoncvs
# X11forward no
# Toegestane nr.
# Toereik in
# Forcecommand CVS -server
PermitRootLogin no
Vergeet niet dat Ctrl+X en Y om het bestand op te slaan. Laten we vervolgens een basisscript schrijven met de naam Initialize (allemaal in de standaard Home Directory van onze gebruiker).

nano initialize
Voeg deze regels toe aan het bestand, vervangenMet je SSH -sleutel die je hebt gevonden met CAT. (.ssh/id_rsa.pub)

# ! / BIN / BASH
sudo apt install -y nano git openssh-server
sudo cp sshd_config /etc/ssh/sshd_config
sudo service ssh restart
sudo service sshd restart
echo "/root/.ssh/id_rsa" | sudo su root -c "ssh-keygen -t rsa -N ''"
echo "root ssh key:"
sudo su root -c "cat /root/.ssh/id_rsa.pub"
sudo adduser --disabled-password --gecos "" team
sudo passwd -d team
sudo usermod -aG sudo team
echo "/home/team/.ssh/id_rsa" | su team -c "ssh-keygen -t rsa -N ''"
cat /home/team/.ssh/id_rsa.pub >> /home/team/.ssh/authorized_keys
echo '<key here>' >> /home/team/.ssh/authorized_keys
echo "team ssh key:"
cat /home/team/.ssh/id_rsa.pub
Laten we, om u door dit bestand te leiden, regel voor regel beginnen. De eerste regel vertelt de compiler dat dit een bash -script is. Vervolgens installeren we afhankelijkheden, kopiëren sshd_config naar de juiste map, starten SSH opnieuw op, genereren SSH -toetsen voor root, het toevoegen van het 'team van de gebruiker' (u kunt een naam kiezen die u hiervoor leuk vindt, gebruik de opdracht AddUser met hun naam en gehandicapt wachtwoord voor nu). We voegen ook een team toe aan de Sudo -groep, genereren hun SSH -sleutel, voegen ook onze sleutel toe aan geautoriseerde toetsen en die van hen en drukken hun sleutel af. Deze nieuwe gebruiker zal zijn hoe we inloggen op de site. Ga in een nieuwe terminal door en open de server opnieuw.

ssh team@XX.XX.XX.XX
Je zou deze keer geen wachtwoord nodig hebben, omdat je een SSH -toets hebt. We hebben ook inloggen met een wachtwoord uitgeschakeld om de site veiliger te houden. Nu begint deze server volledig leeg zonder informatie. Laten we beginnen met het klonen van ons project van Git, zodat we het kunnen downloaden en uitvoeren op de externe machine. Druk eerst uw SSH -sleutel op de externe server die via SSH is verbonden, op:

cat ~/.ssh/id_rsa.pub
Plak deze sleutel vervolgens in de GIT -instellingen zoals we eerder deden om onze Git -repository in te stellen. We kunnen ons project nu rechtstreeks op de server klonen. Zorg ervoor dat je het project eerst lokaal hebt geback -ups, dus het staat op de GIT -server om te downloaden.

git clone git://github.com/you/yourproject.git
Perfect. Nu zijn alle bestanden hier. We kunnen ze zien met LS

ls
Laten we nu beginnen met het instellen van de server. Kopieer eerst uw projectmap naar een eenvoudige, memorabele naam die we voor het project zullen gebruiken.

cp -r yourproject whatyoucalledit
Waar "WhatyoucalLedit" de nieuwe naam van uw project is. Vervolgens moeten we een basishulpprogramma bouwen om de server in te stellen. We zullen dit hulpprogramma opslaan en in de toekomst gebruiken. Om dit hulpprogramma te bouwen, laten we een gebruiker binair maken om te bepalen hoe we een script bewerken. Bash gebruiken, bewerken/usr/bin/ascript

sudo nano /usr/bin/ascript
Zorg ervoor dat je Sudo daar gebruikt, dus je hebt machtigingen om het bestand te bewerken. Voeg in het bestand deze regels toe:

# ! / BIN / BASH
if [ ! -f /usr/bin/$1 ]; then
    sudo touch /usr/bin/$1
    echo "# ! / bin / bash ">> / usr / bin / $ 1
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
    echo $1 | sudo tee -a /etc/ascripts
else
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
fi
Onthoud dat dit script een argument, de scriptnaam, als $ 1 neemt. Eerst controleert het of het bestand bestaat, of anderszins maakt het, voegt de eerste regel toe om te verklaren dat het script bash is, verandert zijn machtigingen, bewerkt het en voegt zijn naam toe aan /etc /ascripts waarmee we de namen van de scripts kunnen opslaan wij zijn aan het creëren. Als het bestand al bestaat, wijzigt u eenvoudig de machtigingen en bewerkt u het. Sla het bestand op en vervolgens zullen we de machtigingen wijzigen. Zolang we dit script gebruiken, hoeven we dat niet opnieuw te doen.

sudo chmod a+x /usr/bin/ascript
Perfect. Laten we nu een script maken met de naam Setup. Ten eerste, niet om je te overweldigen, maar kijk eens naar hoe mijn setup -script eruit ziet. We zullen doorlopen hoe dit script eruit zou moeten zien in uw project, u hebt niet alles in mijn script nodig om mee te beginnen.

# ! / BIN / BASH
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
# sudo chmod a+x scripts/usersetup
# ./scripts/usersetup
# SSH-keyen
# Projectmap
DIR="/home/team/femmebabe"
USER="team"
# Logopdrachten
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# Nano -configuratie
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git Config
echo "Git configuration"
sudo git config --global user.email "jasper.camber.holton@gmail.com" && sudo git config --global user.name "Jasper Holton"
git config --global user.email "jasper.camber.holton@gmail.com"
git config --global user.name "Jasper Holton"
git config --global --add safe.directory $"$DIR"
sudo ssh-keyscan -t rsa gitlab.com | sudo tee -a /root/.ssh/known_hosts
sudo ssh-keyscan -t rsa github.com | sudo tee -a /root/.ssh/known_hosts
echo "Mounting setup"
sudo mount -o remount,size=16G,exec /tmp
# Update en installeren
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
# Schakel Clamav -antivirus in
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Stel hostnaam in
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Stel postgres in
echo "Postgres setup"
sudo -u postgres psql -U postgres -c "DROP DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE USER django WITH PASSWORD 'password';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET client_encoding TO 'utf8';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET default_transaction_isolation TO 'read committed';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET timezone TO 'UTC';"
sudo -u postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE database TO django;"
# Setup Backup -database
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
# Uitgeschakeld ipatables
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Installeer Bitdefender
cd $DIR
echo "Runnning BitDefender antivirus installer"
wget https://cloud.gravityzone.bitdefender.com/Packages/NIX/0/7aTSsy/setup_downloader.tar
mkdir bitdefender
tar -xf setup_downloader.tar -C bitdefender
sudo rm setup_downloader.tar
sed -i -e 's/{LOGINPASSWD/z&A*3BPd_qBGUMs/g' bitdefender/installer
sudo chmod a+x bitdefender/installer
sudo ./bitdefender/installer
# Setup postfix
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
# Creëer dirs
cd $DIR
mkdir media/audio
mkdir media/audio/fingerprints
mkdir media/security
mkdir media/secure
mkdir media/secure/media
mkdir media/secure/video
mkdir media/secure/profile
mkdir media/secure/face
mkdir media/images
mkdir media/live
mkdir media/live/files
mkdir media/live/stills
mkdir media/files
mkdir temp
mkdir temp/data
mkdir temp/gfpgan
mkdir mail/inbox
mkdir mailbox
# Setup virtuelealenv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# Krijg en bouw afhankelijkheden
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
# Stel Firewall -regels in
cd $DIR
# Installeer PYPI -afhankelijkheden
echo "Installing remaining python dependencies (this may take a while)"
sudo systemctl mask tmp.mount
cd $DIR
source venv/bin/activate
pip3 install -U "celery[redis]"
pip3 install -r requirements.txt --use-deprecated=legacy-resolver --use-pep517
pip3 install --upgrade opencv-python # == 4.5.4.60
pip3 install --upgrade opencv-contrib-python # == 4.5.4.60
# Pip Install OpenCV-Python == 4.5.5.64
# PIP Installeer OpenCV-Contrib-Python == 4.5.5.64
pip3 install --upgrade opencv-python-headless
pip3 uninstall channels
pip3 uninstall daphne
pip3 install channels["daphne"]
pip3 install Pillow==9.5.0
pip3 install librosa
pip3 install -U 'Twisted[tls,http2]'
pip3 install --upgrade certifi requests urllib3 numpy oauthlib twisted pyjwt sqlparse cryptography astral webauthn docbarcodes pdf417 deepface --no-cache-dir
pip3 install tensorflow==2.15.1
# Installeer certbot
echo "Installing certificates"
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap install redis
sudo systemctl enable apache2
sudo systemctl start apache2
# Voer certbot uit
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# Laad Mail Server opnieuw
sudo systemctl restart opendkim postfix dovecot
# Kopieer certs
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privkey.pem
# sudo cp /etc/lettesencrypt/live/femmebabe.com/cert.pem cert.pem
# Lapje
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"
# Stel de gebruikersinstellingen in
sudo gpasswd -a www-data users
# Machtigingen instellen
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# sudo chown -R team: gebruikers/var/run/
# sudo chown root: root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
# sudo chmod 664 db.sqlite3
# sudo chown www-data: gebruikers db.sqlite3
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
sudo chown -R team:users ./gfpgan/
sudo chown -R team:users ./temp/
sudo chmod a+r team /var/mail/$USER
# Kopieer configuratie en stel machtigingen in
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
# Database -instelling
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"
# Injecteer PAM -configuratie en verwijder een defecte SSH -configuratie
# sudo sed -i '' -e '$ d' /tc/pam.d/sshd
# Sudo sed -i '' -en $ d ' /etc /profiel
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
# Kopieer bin scripts en stel machtigingen in
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
# Herlaad en schakel services in
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
# Schakel Apache -modules in
echo "Enabling apache2"
sudo a2enmod rewrite
sudo a2enmod wsgi
sudo a2enmod headers
sudo a2enmod ssl
sudo a2enmod proxy
sudo a2enmod proxy_balancer
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
# sudo a2dismod mpm_event
# sudo a2dismod mpm_worker
# sudo a2enmod mpm_prefork
# Schakel de standaardsite uit
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# Schakel voor de site
sudo a2ensite femmebabe-le-ssl
# Herlaad daemon en herstart Apache, Postfix en Opendkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# Machtigingen instellen
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# Swap Configuration
echo "Allocating swap, this may take a while"
sudo swapoff /swapfile
sudo rm /swapfile
sudo fallocate -l 8G /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1024 count=8388608
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab
sudo swapon --show
# Init Thais Motor
echo "Initializing routine caption"
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/routine_caption.py
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/setup_mail.py
# Setup git
echo "Setting up git"
cd $DIR
sudo rm -r .git
git init --initial-branch=main
echo "Setting user password"
sudo usermod --password $(echo team | openssl passwd -1 -stdin) team
# Toon IPv6 en OpenDKim voor domeinconfiguratie
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}'
# Instellingen voltooid
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."
Dat is veel opstelling! Kortom, deze codelogs -opdrachten, configureert nano en git, kopieën over bestanden, downloads en installeert ubuntu apt -pakketten, python -afhankelijkheden, configureert postfix, configureert postgresql (de databaseserver) en laadt de database, configureert de UFW (een niet -gecompliceerde firewall), Schakelt iptables uit, downloadt een antivirus, maakt mappen, afhankelijkheden van klonen, installeert certificaten en stelt de server in, installeert configuratie, start en stelt de SERP, wijst swap toe, stelt machtigingen in en drukt het IP-, IPv6 -adres en OPENDKIM -sleutel. Vrij eenvoudig, maar het lijkt veel code. We zullen dit niet veel nodig hebben omdat we niet de afhankelijkheden hebben, we gebruiken geen selderij, selderybeat of daphne, maar we zullen er toch een aantal installeren om aan de slag te gaan. Merk op dat deze code meerdere keren een domein heeft verklaard. We zullen ook een domeinnaam moeten kopen (wat een kleine jaarlijkse vergoeding is). Ik raad Squarespace aan voor de aankoop van een domein, hun lay -out isIntuïtief en gemakkelijk te gebruiken. U kunt elk domein naar keuze kopen, maar ik gebruik de domein femmebabe.com in dit voorbeeld. Nadat u een domein hebt gekocht, gaat u naar het Squarespace DNS -configuratiepaneel en voegt u een A -record toe dat uw domein naar de server wijst op het IP -adres. Het zou er zo uit moeten zien: @ A xx.xx.xx.xx Met de @ -operator als host, wat betekent dat alle subdomeinen onder dit domein en het rootdomein allemaal naar de server worden doorgeleid. Er zijn meer records om aan te geven, maar we kunnen hierop doorgaan zodra we klaar zijn om e -mail te verzenden. Houd er rekening mee dat het enkele dagen kan duren voordat u e -mail met de server met succes kunt verzenden. De DNS -records die we instellen, hebben tijd nodig om zich te verspreiden. Hoe dan ook, het enige record dat we moeten beginnen is een A -record. Dus nu kunnen we het onderstaande script invullen volgens ons project en het uitvoeren. Laten we beginnen met een kleiner setup -script om gewoon te installeren wat we nodig hebben voor een basisvoortgang. We zullen nog niet zoveel afhankelijkheden of postgreesql gebruiken, we zullen gewoonEen eenvoudige HTTP -server op en maak je zorgen over het certificeren wanneer dat is gedaan. Vergeet niet dat om een ​​HTTPS -certificaat te krijgen en de server veilig uit te voeren, moeten we een domein kopen samen met Rent A Server. Vervang voor nu "team" in dit bestand door de naam van uw gebruiker, "Dir" door de map van uw project, en leveren uw e -mail en domein in de <> -tags. Bovendien moeten we, voordat we deze code uitvoeren, de instellingen wijzigen in de firewall die de hostingprovider ondersteunt, indien aanwezig. Meestal staat dit op het tabblad 'Netwerken' van uw hostingprovider, of als u zelf host, het is in het gedeelte 'Port forwarding' van uw router. U wilt ook een statisch IP instellen via uw router met het adres van uw servermachine, als u zelfhosting gebruikt. U moet de volgende poorten openen voor lees-/schrijftoegang. 22 (SSH) 25 (e -mail) 587 (e -mail) 110 (e -mailclient) 80 (http) 443

# ! / BIN / BASH
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
# Logopdrachten
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# Nano -configuratie
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git Config
echo "Git configuration"
sudo git config --global user.email "<youremail>@gmail.com" && sudo git config --global user.name "<yourname>"
git config --global --add safe.directory $"$DIR"
sudo ssh-keyscan -t rsa gitlab.com | sudo tee -a /root/.ssh/known_hosts
sudo ssh-keyscan -t rsa github.com | sudo tee -a /root/.ssh/known_hosts
# Update en installeren
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
# Schakel Clamav -antivirus in
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Stel hostnaam in
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
# Setup Backup -database
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
# Uitgeschakeld ipatables
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Setup virtuelealenv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
# Installeer certbot
echo "Installing certificates"
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap install redis
sudo systemctl enable apache2
sudo systemctl start apache2
# Voer certbot uit
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# Stel de gebruikersinstellingen in
sudo gpasswd -a www-data users
# Machtigingen instellen
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# sudo chown -R team: gebruikers/var/run/
# sudo chown root: root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
# Herlaad en schakel services in
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Schakel Apache -modules in
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
# Herlaad daemon en herstart Apache, Postfix en Opendkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# Toon IPv6 en OpenDKim voor domeinconfiguratie
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
Voordat u deze code uitvoert, moet u ervoor zorgen dat het domein dat u hebt gekocht is verbonden met de server. Open hiervoor een terminal op uw lokale machine en voer deze opdracht uit met uw domein:

ping femmebabe.com # Voeg hier uw domein in na ping
Als alles er goed uitziet en de server antwoorden verzendt, zijn we klaar om het script uit te voeren en pakketten te installeren en onze Apache -server te starten, in te schakelen en te certificeren. Dit is niet alles wat nodig is om Postfix te configureren, we zullen die installatie later meer bekijken. Voer deze installatiecode voor nu uit en het moet enkele minuten duren om uw server te installeren en te certificeren. Zorg er nogmaals voor dat u naam, e -mail en domeinnaam in het script vervangt op basis van de naam die u hebt gekocht. Nu de server is voorzien, kunt u naar de URL gaan in elke webbrowser en controleren of de server HTTPS uitvoert. Als dit niet het geval is, probeer dan een tijdje te wachten op de DNS -records om in te halen en voert vervolgens de volgende opdracht uit om CertBot -certificering opnieuw te proberen:

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
Zolang u alles correct hebt geconfigureerd, zou u toegang moeten hebben tot de standaardpagina van Apache om te weten dat uw code werkt en een live -webpagina weergeeft. Laten we vervolgens de instellingen.py bewerken om onze standaard foutopsporingsmodus te wijzigen in productie. We zullen het domein ook configureren in de instellingen, evenals interne IP's.

nano yourproject/settings.py
Wijzig/voeg deze regels toe in de instellingen.

DEBUG = False

# Site Config
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',
]
Nu moeten we Apache2 configureren. Laten we het configuratiebestand bewerken dat we met deze regel zullen implementeren:

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
Dit configuratiebestand moet onze domeinnaam erin bevatten en de naam van de gebruiker en het project. Ik gebruik de domeinnaam femmebabe.com, het gebruikersnaamteam en de projectnaam femmebabe.

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

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

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

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

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

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

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

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

	TimeOut 60000
	LimitRequestBody 0

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

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

	RewriteEngine on
	RewriteCond %{SERVER_NAME} =femmebabe.com
	RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
</IfModule>
Zorg ervoor dat u de naam van het project, de mappen en het domein vervangt in deze voorbeeldcode bij het configureren van uw server. Nu moeten we de standaardsite uitschakelen. Dit kan worden gedaan met Bash.

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
Vervolgens kunnen we de standaardsite inschakelen en Apache2 herladen, ook met BASH. Vergeet niet om FemmeBabe te vervangen door de naam van het bestand dat u hebt uitgeroepen bij het bewerken in/etc/Apache2/sites-beschikbare/.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Ga terug naar uw domein in de Navbar. U zou de site moeten zien die u in uw webbrowser hebt geconfigureerd. Gefeliciteerd! Als u het niet ziet, moet u mogelijk enkele wijzigingen aanbrengen. Bekijk de instellingen zorgvuldig in uw project, Apache -configuratie en zorg ervoor dat u geen fouten hebt en voer de volgende opdrachten uit om het project op fouten te controleren.

cd projectname
source venv/bin/activate
python manage.py check
Als u fouten hebt in uw Python -project, volg ze dan tot waar ze zijn en repareer ze. Je kunt misschien niet al je fouten zien, afhankelijk van waar ze zijn, dus als je een fout hebt die zegt dat "popule niet opnieuw is", bewerk dan het volgende bestand in de virtuele omgeving, registry.py, om de bloot te leggen fout.

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Scroll naar regel 83, waar deze runtime -fout wordt verhoogd (RuntimeError verhogen ("Populate () is niet reentrant")) en voeg een opmerking toe vóór deze regel, en voeg vervolgens, met dezelfde inspringing, self.app_configs = {} toe. Dit ziet er zo uit:

            if self.loading:
                # Voorkom dat nieuwe oproepen worden uitgevoerd om te voorkomen dat AppConfig.Ready () wordt uitgevoerd
                # methoden tweemaal.
# RuntimeError verhogen ("Populate () is niet reentrant")
                self.app_configs = {}
            self.loading = True
U kunt het project vervolgens opnieuw controleren en de fout blootleggen.

python manage.py check
Vervolgens kunt u de fout zien en deze repareren. Wanneer u het hebt opgelost en de code zonder fouten compileert, zorg er dan voor dat u het bestand terug wijzigt zodat het er zo uitziet:

            if self.loading:
                # Voorkom dat nieuwe oproepen worden uitgevoerd om te voorkomen dat AppConfig.Ready () wordt uitgevoerd
                # methoden tweemaal.
                raise RuntimeError("populate() isn't reentrant")
# self.app_configs = {}
            self.loading = True
Op voorwaarde dat de server online is, moeten we, wanneer we er verdere wijzigingen in aanbrengen, de volgende opdracht gebruiken om de server opnieuw te laden:

sudo systemctl reload apache2
Geweldig! Maar hoe zit het met het verzenden van e -mail? Om te beginnen met het verzenden van e -mail, moeten we eerst de domeinconfiguratie bijwerken. Dit zou in uw DNS -paneel op Squarespace moeten zijn, of welke domeinnaam registrar u koos. We moeten ook configuratie installeren en toevoegen en een paar opdrachten uitvoeren. Laten we eerst het IPv6 -adres van de server krijgen. We openen vervolgens uw DNS en voegen de records toe. Gebruik deze opdracht om het IPv6 -adres van de server te krijgen:

ip -6 addr
Nu kunnen we de volgende records toevoegen aan de DNS -instellingen. Mijn records zien er zo uit. Voor uw gegevens moet u het IP -adres echter vervangen door uw IP (niet 75.147.182.214, dat is van mij). Voeg ook uw domein toe in plaats van femmeBabe.com, evenals uw IPv6 -adres gevonden met de vorige opdracht (u kunt de mijne niet gebruiken, Fe80 :: 725A: FFF: FE49: 3E02). Maak je voorlopig geen zorgen over het domeainkey, dit wordt gemaakt wanneer we Postfix, de Mail Server, met OpenDKim instellen en de sleutel afdrukken. We zullen dit laatste configureren. @ A Nvt 75.147.182.214 @ Mx 10 femmebabe.com @ PTR Nvt femmebabe.com @ Txt Nvt Txt @ v = spf1 mx ip75.147.182.214ip6: fe80 :: 725a: fff: fe49: 3e02 ~ All standaard._bimi Txt Nvt v = bimi1; l = https: //femmebabe.com/media/static/femmebabe.svg _DMARC Txt Nvt v = dmarc1; P = geen sendonly._domainkey Txt NvtNu moeten we wat aanhoudende configuratie voor Postfix toevoegen. Het enige dat we moeten doen is ervoor zorgen dat we de domeinnaam, femmeBabe.com, vervangen door de domeinnaam die u gebruikt. Laten we eens kijken naar alle configuratiebestanden een voor een en deze installeren in een map met de naam Config in ons project, voor installatie op het besturingssysteem.

nano config/etc_postfix_main.cf
Voeg deze tekst toe aan het bestand

# Zie /usr/share/postfix/main.cf.dist voor een becommentarieerde, meer complete versie


# Debian -specifiek: het opgeven van een bestandsnaam zal de eerste veroorzaken
# Lijn van dat bestand dat als naam moet worden gebruikt.  De Debian Standaard
# is /etc /mailnaam.
# Myorigine = /etc /mailname

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

# Toevoegen .domain is de taak van de MUA.
append_dot_mydomain = no

# Uncomment de volgende regel om "vertraagde post" -waarschuwingen te genereren
# vertraging_warning_time = 4h

readme_directory = no

# Zie http://www.postfix.org/compatibility_readme.html - Standaard op 3.6
# frisse installaties.
compatibility_level = 3.6



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

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

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

# Milter -configuratie
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
Volgende configuratie!

nano config/etc_postfix_master.cf
Voeg deze lijnen toe:

# 
# Postfix Master Process Configuration -bestand.  Voor meer informatie over het formaat
# Zie van het bestand de hoofdmaster (5) handmatige pagina (opdracht: "man 5 master" of
# On-line: http://www.postfix.org/master.5.html).
# 
# Vergeet niet om "Postfix Reload" uit te voeren na het bewerken van dit bestand.
# 
# ==================================================== =========================
# Servicetype privé Priv Chroot wake -up maxProc -opdracht + args
# (Ja) (ja) (nee) (nooit) (100)
# ==================================================== =========================
smtp      inet  n       -       y       -       -       smtpd
# SMTP inet n - y - 1 postscreen
# smtpd pass - - y - - smtpd
# DNSBLOG UNIX - - Y - 0 DNSBLOG
# TlSproxy Unix - - y - 0 tlsproxy
# Kies er een: Inzending inschakelen voor Loopback -clients alleen of voor een klant.
# 127.0.0.1: Submission Inet n - y - - Smtpd
submission inet n       -       y       -       -       smtpd
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
# -o syslog_name = postfix/inzending
# -o smtpd_tls_security_level = code
# -o smtpd_sasl_auth_enable = ja
# -o smtpd_tls_auth_only = ja
# -o smtpd_reject_unlisted_recipient = nee
# -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_authenticeerd, afwijzen
# -O milter_macro_daemon_name = afkomstig
# Kies er een: Schakel SMTPS alleen voor loopback -clients in, of voor een client.
# 127.0.0.1:smtps inet n - y - - smtpd
# Smtps inet n - y - - smtpd
# -O syslog_name = postfix/smtps
# -o smtpd_tls_wrappermode = ja
# -o smtpd_sasl_auth_enable = ja
# -o smtpd_reject_unlisted_recipient = nee
# -O smtpd_client_restrictions = $ mua_client_restrictions
# -o smtpd_helo_restrictions = $ mua_helo_restrictions
# -o smtpd_sender_restrictions = $ mua_sender_restrictions
# -o smtpd_recipient_trastrictions =
# -o smtpd_relay_restrictions = permit_sasl_authenticeerd, afwijzen
# -O milter_macro_daemon_name = afkomstig
# 628 inet n - y - - qmqpd
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
# Qmgr Unix n - n 300 1 oqmgr
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
# -o smtp_helo_timeout = 5 -o smtp_connect_timeout = 5
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd
# 
# ==================================================== ===================
# Interfaces naar niet-Postfix-software. Zorg ervoor dat u de handleiding onderzoekt
# Pagina's van de niet-Postfix-software om erachter te komen welke opties het wil.
# 
# Veel van de volgende services gebruiken de levering van de Postfix Pipe (8)
# tussenpersoon.  Zie de pijp (8) Woman Page voor informatie over $ {ontvanger}
# en andere opties voor het envelop van berichten.
# ==================================================== ===================
# 
# Maildrop. Zie het bestand Postfix Maildrop_readme voor meer informatie.
# Geef ook op in main.cf: maildrop_destination_recipient_limit = 1
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# ==================================================== ===================
# 
# Recente Cyrus -versies kunnen de bestaande "LMTP" master.cf -invoer gebruiken.
# 
# Specificeer in cyrus.conf:
# lmtp cmd = "lmtpd -a" luister = "localhost: lmtp" proto = tcp4
# 
# Specificeer in main.cf een of meer van het volgende:
# mailbox_transport = lmtp: inet: localhost
# Virtual_transport = lmtp: inet: localhost
# 
# ==================================================== ===================
# 
# Cyrus 2.1.5 (Amos Gouaux)
# Geef ook op in main.cf: cyrus_destination_recipient_limit = 1
# 
# Cyrus Unix - n n - - pijp
# flags = drx user = cyrus arg =/cyrus/bin/leveren -e -r $ {afzender} -m $ {extension} $ {user}
# 
# ==================================================== ===================
# Oud voorbeeld van levering via Cyrus.
# 
# Old -Corus Unix - N N - - Pipe
# Flags = r user = cyrus argv =/cyrus/bin/leveren -e -m $ {extension} $ {user}
# 
# ==================================================== ===================
# 
# Zie het postfix UUCP_README -bestand voor configuratiegegevens.
# 
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# 
# Andere externe leveringsmethoden.
# 
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}
En de OpenDKIM -configuratie. OpenDKim identificeert e -mailservers met domeinsleutels om ze veiliger te maken. Zonder dit is e -mail niet ondertekend en komt misschien niet in een inbox.

nano config/etc_default_opendkim
Voeg deze lijnen toe:

# Opmerking: dit is een legacy -configuratiebestand. Het wordt niet gebruikt door de Opendkim
# Systemd Service. Gebruik de overeenkomstige configuratieparameters in
# /etc/opendkim.conf in plaats daarvan.
# 
# Eerder zou men de standaardinstellingen hier bewerken en vervolgens uitvoeren
# /lib/opendkim/opendkim.service.Generate om SystemD te genereren die bestanden naar overschrijven
# /etc/systemd/system/opendkim.service.d/override.conf en
# /etc/tmpfiles.d/opendkim.conf. Hoewel dit nog steeds mogelijk is, is het nu
# Aanbevolen om de instellingen rechtstreeks in /etc/opendkim.conf aan te passen.
# 
# Daemon_optts = ""
# Wijzig naar/var/spool/postfix/run/opendkim om een ​​UNIX -socket te gebruiken met
# Postfix in een chroot:
# Rundir =/var/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Uncomment om een ​​alternatieve socket op te geven
# Merk op dat het instellen hiervan elke socketwaarde in OpendKim.conf zal overschrijven
# standaard:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Luister op alle interfaces op poort 54321:
# Socket = INET: 54321
# Luister op loopback op poort 12345:
# Socket = inet: 12345@localhost
# Luister is 192.0.2.1 is poort 12345:
# Socket = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

nano config/etc_dovecot_conf.d_10-master.conf
Voeg deze lijnen toe:

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

# Standaard VSZ (virtuele geheugengrootte) limiet voor serviceprocessen. Dit is vooral
# bedoeld om processen te vangen en te doden die geheugen lekken voordat ze opeten
# alles.
# default_vsz_limit = 256m

# Aanmeldingsgebruiker wordt intern gebruikt door inlogprocessen. Dit is de meest niet -vertrouwde
# Gebruiker in het Dovecot -systeem. Het zou helemaal geen toegang moeten hebben tot iets.
# default_login_user = dovenull

# Interne gebruiker wordt gebruikt door onbevestigde processen. Het moet los staan ​​van
# Inloggebruiker, zodat inlogprocessen andere processen niet kunnen verstoren.
# default_internal_user = dovecot

service imap-login {
  inet_listener imap {
    # Poort = 143
  }
  inet_listener imaps {
    # Poort = 993
    # SSL = ja
  }

  # Aantal verbindingen om te verwerken voordat een nieuw proces wordt gestart. Typisch
  # De enige nuttige waarden zijn 0 (onbeperkt) of 1. 1 is veiliger, maar 0
  # is sneller. <doc/wiki/loginProcess.txt>
  # service_count = 1

  # Aantal processen om altijd op meer verbindingen te blijven wachten.
  # Proces_min_avail = 0

  # Als u Service_Count = 0 instelt, moet u dit waarschijnlijk laten groeien.
  # VSZ_LIMI = $ default_vsz_limit
}

service pop3-login {
  inet_listener pop3 {
    # Poort = 110
  }
  inet_listener pop3s {
    # Poort = 995
    # SSL = ja
  }
}

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

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

  # Maak INET -luisteraar alleen als u de bovenstaande Unix -socket niet kunt gebruiken
  # inet_lister lmtp {
    # Vermijd LMTP zichtbaar te maken voor het hele internet
    # Adres =
    # poort =
  # }
}

service imap {
  # Het grootste deel van het geheugen gaat naar mmap () ing bestanden. Mogelijk moet u dit verhogen
  # Beperk als je enorme mailboxen hebt.
  # vsz_limit = $ default_vsz_limit

  # Max. Aantal IMAP -processen (verbindingen)
  # proces_limit = 1024
}

service pop3 {
  # Max. Aantal POP3 -processen (verbindingen)
  # Proces_limit = 1024
}

service submission {
  # Max. Aantal SMTP -indieningsprocessen (verbindingen)
  # Proces_limit = 1024
}

service auth {
  # Auth_Socket_Path wijst standaard naar deze UserDB -socket. Het is meestal
  # gebruikt door dovecot-lda, doveadm, mogelijk IMAP-proces, enz. Gebruikers die hebben
  # Volledige machtigingen voor deze socket kunnen een lijst krijgen van alle gebruikersnamen en
  # Krijg de resultaten van ieders UserDB -lookups.
  # 
  # Met de standaard 0666 -modus kan iedereen verbinding maken met de socket, maar de
  # UserDB -lookups zullen alleen slagen als de UserDB een "UID" -veld retourneert
  # komt overeen met de UID van het bellerproces. Ook als beller's UID of GID overeenkomt met de
  # Socket's UID of GID De lookup slaagt. Al het andere veroorzaakt een mislukking.
  # 
  # Om de beller volledige machtigingen te geven om alle gebruikers op te zoeken, stelt u de modus in op
  # Iets anders dan 0666 en Dovecot laat de kernel de
  # Machtigingen (bijv. 0777 staat iedereen volledige machtigingen toe).
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # AUTH Worker -proces wordt standaard als root uitgevoerd, zodat het toegang heeft
  # /etc/schaduw. Als dit niet nodig is, moet de gebruiker worden gewijzigd in
  # $ default_interal_user.
  # User = root
}

service dict {
  # Als dict proxy wordt gebruikt, moeten e -mailprocessen toegang hebben tot de socket.
  # Bijvoorbeeld: modus = 0660, group = vmail en global mail_access_groups = vmail
  unix_listener dict {
    # Modus = 0600
    # Gebruiker =
    # Groep =
  }
}
Zorg er nogmaals voor dat u het domein in al deze bestanden, femmebabe.com, vervangt met het domein dat u hebt geselecteerd. Bewerk het volgende bestand, Dovecot's Config,

nano config/etc_dovecot_dovecot
En voeg deze lijnen toe

## Ovecot -configuratiebestand

# Als je haast hebt, zie http://wiki2.dovecot.org/quickconfiguration

# "Doveconf -n" -opdracht geeft een schone uitvoer van de gewijzigde instellingen. Gebruik het
# In plaats van bestanden te kopiëren en te plakken bij het posten op de Dovecot -mailinglijst.

# '# 'Karakter en alles nadat het als opmerkingen wordt behandeld. Extra ruimtes
# en tabbladen worden genegeerd. Als u een van deze expliciet wilt gebruiken, zet dan de
# value inside quotes, eg.: key = "# Char en achterblijvende witruimte "

# De meeste (maar niet alle) instellingen kunnen worden opgeheven door verschillende protocollen en/of
# Bron/bestemming IP's door de instellingen in secties te plaatsen, bijvoorbeeld:
# Protocol IMAP {}, Local 127.0.0.1 {}, externe 10.0.0.0/8 {}

# Standaardwaarden worden voor elke instelling weergegeven, het is niet vereist om te ontdoening
# die. Dit zijn hierop uitzonderingen: geen secties (bijv. Namespace {})
# Of plug -in -instellingen worden standaard toegevoegd, ze worden alleen als voorbeelden vermeld.
# Paden zijn ook slechts voorbeelden met de echte standaardwaarden die zijn gebaseerd op configureren
# Opties. De hier genoemde paden zijn voor configure -prefix =/usr
# ---sysconfdir =/etc --localStatedir =/var

# Geïnstalleerde protocollen inschakelen
!include_try /usr/share/dovecot/protocols.d/*.protocol

# Een door komma gescheiden lijst van IP's of hosts waar te luisteren naar verbindingen.
# "*" luistert in alle IPv4 -interfaces ", ::" Luistert in alle IPv6 -interfaces.
# Als u niet-defaultpoorten of iets complexers wilt opgeven,
# Conf.D/master.conf bewerken.
# Luister = *, ::

# Base Directory waar runtime -gegevens op te slaan.
# Base_dir =/var/run/dovecot/

# Naam van dit exemplaar. In multi-installatie setup doveadm en andere opdrachten
# kan -i <instantie_name> gebruiken om te selecteren welk exemplaar wordt gebruikt (een alternatief
# naar -c <config_path>). De exemplaarnaam wordt ook toegevoegd aan dovecot -processen
# in PS -output.
# instantie_name = dovecot

# Groet bericht voor klanten.
# login_greeting = dovecot klaar.

# Space gescheiden lijst van vertrouwde netwerkbereiken. Verbindingen van deze
# IP's mogen hun IP -adressen en poorten overschrijven (voor logboekregistratie en
# voor authenticatiecontroles). disable_plaintext_auth wordt ook genegeerd voor
# deze netwerken. Meestal zou u hier uw IMAP -proxy -servers opgeven.
# login_trusted_networks =

# Space gescheiden lijst met inlogtoegangscontroles (bijv. TCPWRAP)
# login_access_sockets =

# Met proxy_maybe = ja als de proxy -bestemming overeenkomt met een van deze IP's, doe het dan niet
# proxying. Dit is normaal niet nodig, maar kan nuttig zijn als de bestemming
# IP is b.v. Het IP van een load balancer.
# auth_proxy_self =

# Toon meer uitgebreide procestitels (in PS). Toont momenteel de gebruikersnaam en
# IP -adres. Handig om te zien wie de IMAP -processen daadwerkelijk gebruiken
# (bijv. Gedeelde mailboxen of als dezelfde UID wordt gebruikt voor meerdere accounts).
# verbose_procTitle = nee

# Mochten alle processen worden gedood wanneer Dovecot Master Proces wordt uitgeschakeld.
# Dit instellen op "nee" betekent dat dovecot kan worden opgewaardeerd zonder
# Bestaande clientverbindingen dwingen om te sluiten (hoewel dat ook zou kunnen zijn
# Een probleem als de upgrade is b.v. vanwege een beveiligingsfix).
# shutdown_clients = ja

# Als het niet nul is, voert u e-mailopdrachten uit via deze vele verbindingen naar de doveadm-server,
# in plaats van ze rechtstreeks in hetzelfde proces te draaien.
# doveadm_worker_count = 0
# Unix -socket of host: poort gebruikt voor verbinding met DoveAdm Server
# doveadm_socket_path = doveadm-server

# Space gescheiden lijst met omgevingsvariabelen die op dovecot worden bewaard
# Startup en doorgegeven aan al zijn kinderprocessen. Je kunt ook geven
# sleutel = waardeparen om altijd specifieke instellingen in te stellen.
# Import_environment = tz

## 
## Instellingen van de woordenboekserver server
## 

# Woordenboek kan worden gebruikt om sleutel = waardelijsten op te slaan. Dit wordt door verschillende gebruikt
# plug -ins. Het woordenboek is direct toegankelijk
# woordenboekserver. De volgende dictblokkaarten Woordenboeknamen naar Uris
# Wanneer de server wordt gebruikt. Deze kunnen vervolgens worden verwezen met behulp van URI's in formaat
# "Proxy :: <Name>".

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

# Het grootste deel van de werkelijke configuratie wordt hieronder opgenomen. De bestandsnamen zijn
# Eerst gesorteerd op hun ASCII -waarde en ontleed in die volgorde. De 00-prefixes
# In bestandsnamen zijn bedoeld om het gemakkelijker te maken om de bestelling te begrijpen.
!include conf.d/*.conf

# Een configuratiebestand kan ook proberen op te nemen zonder een fout te geven als
# Het is niet gevonden:
!include_try local.conf

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

protocols = imap pop3

# Hiermee kan Dovecot luisteren naar alle invoerverbindingen (IPv4 / IPv6)

listen = *, ::
Voeg een wachtwoord toe voor de Dovecot -gebruiker:

nano config/etc_dovecot_passwd
Het eerste deel van het bestand, vóór de dikke darm, is de gebruikersnaam. Het laatste deel, "YourPassWord", geeft het wachtwoord aan dat u uw mailserver wilt geven.

team:{plain}yourpassword
Vervolgens de OpenDKim -configuratie

nano config/etc_opendkim.conf
En voeg deze lijnen toe:

# Dit is een basisconfiguratie voor het ondertekenen en verifiëren. Het kan gemakkelijk zijn
# aangepast aan een basisinstallatie. Zie OpenDKim.conf (5) en
# /usr/share/doc/opendkim/examples/opendkim.conf.Sample voor compleet
# Documentatie van beschikbare configuratieparameters.

Syslog			yes
SyslogSuccess		yes
# LOGWHA NEE

# Veel voorkomende ondertekening en verificatieparameters. In Debian is de "from" header
# overgenomen, omdat het vaak de identiteitssleutel is die wordt gebruikt door reputatiesystemen
# en dus enigszins beveiligingsgevoelig.
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# Ondertekening van domein, selector en sleutel (vereist). Voer bijvoorbeeld ondertekening uit
# voor domein "exemplaar.com" met selector "2020" (2020._domainkey.example.com),
# De privésleutel gebruiken die is opgeslagen in /etc/dkimkeys/example.private. Meer korrelig
# Setup -opties zijn te vinden in /usr/share/doc/opendkim/readme.opendkim.
# Domein exemplaar.com
# Selector 2020
# Keyfile /etc/dkimkeys/example.private

# In Debian loopt OpenDKim als gebruiker "OpendKim". Een umask van 007 is vereist wanneer
# met behulp van een lokale aansluiting met MTA's die toegang krijgen tot de socket als een niet-bevoorrechte
# Gebruiker (bijvoorbeeld postfix). Mogelijk moet u gebruiker "Postfix" toevoegen aan groep
# "Opendkim" in dat geval.
UserID			opendkim
UMask			007

# Socket voor de MTA -verbinding (vereist). Als de MTA in een chroot -gevangenis zit,
# Er moet ervoor worden gezorgd dat de socket toegankelijk is. In Debian komt Postfix binnen
# Een chroot in/var/spool/postfix, daarom zou een Unix -socket moeten zijn
# geconfigureerd zoals weergegeven op de laatste regel hieronder.
# Socket Local: /run/opendkim/opendkim.sock
# Socket INET: 8891@localhost
# Socket INET: 8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Hosts om te ondertekenen in plaats van te verifiëren, standaard is 127.0.0.1. Zie de
# Bedieningssectie van OpenDKim (8) voor meer informatie.
# InternalHosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# Het Trust -anker maakt DNSSEC mogelijk. In Debian wordt het Trust Anchor -bestand verstrekt
# door het pakket dns-root-data.
TrustAnchorFile		/usr/share/dns/root.key
# NAMESERVERS 127.0.0.1

# Kaartdomeinen in van adressen tot toetsen die worden gebruikt om berichten te ondertekenen
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Een set interne hosts waarvan de e -mail moet worden ondertekend
InternalHosts       /etc/opendkim/trusted.hosts

nano config/etc_default_opendkim
En voeg deze lijnen toe

# Opmerking: dit is een legacy -configuratiebestand. Het wordt niet gebruikt door de Opendkim
# Systemd Service. Gebruik de overeenkomstige configuratieparameters in
# /etc/opendkim.conf in plaats daarvan.
# 
# Eerder zou men de standaardinstellingen hier bewerken en vervolgens uitvoeren
# /lib/opendkim/opendkim.service.Generate om SystemD te genereren die bestanden naar overschrijven
# /etc/systemd/system/opendkim.service.d/override.conf en
# /etc/tmpfiles.d/opendkim.conf. Hoewel dit nog steeds mogelijk is, is het nu
# Aanbevolen om de instellingen rechtstreeks in /etc/opendkim.conf aan te passen.
# 
# Daemon_optts = ""
# Wijzig naar/var/spool/postfix/run/opendkim om een ​​UNIX -socket te gebruiken met
# Postfix in een chroot:
# Rundir =/was/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Uncomment om een ​​alternatieve socket op te geven
# Merk op dat het instellen hiervan elke socketwaarde in OpendKim.conf zal overschrijven
# standaard:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Luister op alle interfaces op poort 54321:
# Socket = INET: 54321
# Luister op loopback op poort 12345:
# Socket = inet: 12345@localhost
# Luister is 192.0.2.1 is poort 12345:
# Socket = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Wanneer we klaar zijn om onze Postfix -server in te stellen, voeren we de onderstaande code uit, met de juiste domeinnaam ingebed. Begin met het maken van een script

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
Nu, in Nano, bewerkt de teksteditor dit bestand zodat het uw domeinnaam bevat in plaats van femmeBabe.com.

# ! / BIN / BASH
# Setup postfix
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
sudo cat /etc/opendkim/keys/femmebabe.com/sendonly.txt | tr -d '\n' | sed 's/\s//g' | sed 's/""//g' | awk -F'[)(]' '{print $2}'
Voer nu het voltooide script uit om Postfix, OpenDKim en Dovecot te configureren.

./scripts/postfixsetup
Nadat dit script is uitgevoerd, kopieert u de laatste regel die deze afdrukt en plakt u deze in uw DNS -configuratie als de waarde voor sendonly._domainkey. Dit is de OpenDKim -sleutel die wordt gebruikt om uw domein te identificeren bij het verzenden van beveiligde e -mail. Geweldig! Binnen enkele dagen zou u e -mail moeten kunnen verzenden van de server, op voorwaarde dat alles correct is geconfigureerd. Als u net de DNS voor uw mailserver hebt geconfigureerd, moet deze minder dan 72 uur duren voordat de records worden bijgewerkt. Het is meestal veel sneller. U kunt controleren of uw server werkt met behulp van deze opdracht, heeft uw e -mail geleverd:

echo “test” | mail -s “Test Email” youremail@gmail.com
Als alles correct lijkt te werken, zou u e -mail met uw server moeten kunnen verzenden. Als het niet werkt, probeer dan naar de logboeken te kijken om te zien wat de fout kan zijn.

tail –lines 150 /var/log/mail.log
Dit biedt uitgebreide informatie over e -mail die door de server wordt verzonden en of deze correct werkt. U zou de e -mail ook in uw inbox moeten kunnen zien, als deze er niet is, controleert u uw spammap. U moet ook uw instellingen configureren in uw instellingen.py zodat uw e -mailserver met uw Django -app kan praten, het project. Voeg deze regels toe in uw instellingen

EMAIL_HOST = DOMAIN
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = 'team@femmebabe.com'
EMAIL_HOST_USER = 'team' # 'Love@mamasen.com'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
Merk op dat we een configuratiebestand gebruiken om het wachtwoord te krijgen. Laten we dit bestand laden in de instellingen zoals zo, aan het begin van het bestand.:

import os
import json

# Open en laad configuratie
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Laten we dit bestand maken en er een geheime sleutel aan toevoegen, evenals het e -mailwachtwoord. Gebruik deze opdracht om een ​​geheime sleutel te genereren, met elke lengte die u aan het einde leuk vindt:

openssl rand -base64 64
Kopieer nu de tekst die OpenSSL heeft gegenereerd en bewerken /etc/config.json

sudo nano /etc/config.json
Voeg de volgende regels toe aan uw bestand, met de sleutel die wordt gegenereerd als de geheime sleutel.

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
JSON -formaat is eenvoudig en gemakkelijk te gebruiken, we kunnen andere sleutels die we in ons project willen gebruiken ook op deze manier verklaren en ze gescheiden houden van onze projectmap, zodat andere gebruikers niet aan hen kunnen schrijven en dus niet kunnen worden gelezen Alleen al uit onze projectmap. Dit is aanbevolen praktijk voor API -toetsen, waarvan we hier meer dan een paar zullen gebruiken. U wilt ook een back -up maken van uw project om ervoor te zorgen dat alles wordt opgeslagen en u kunt uw werk later herstellen, zelfs als u niet langer een server wilt huren.

sudo backup
Probeer nu een HTML -e -mail te verzenden vanaf de webserver, mits het verzenden van een van de opdrachtregel werkt. Vraag uw gebruikersinstantie in de shell en stuur een HTML -e -mail naar die gebruiker via Django. Wijzig mijn naam in de code, Charlotte, in uw gebruikersnaam.

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()
Als het eerste opdracht niet werkt, zorg er dan voor dat u gebruikt

source venv/bin/activate
Op voorwaarde dat alles correct is ingesteld, krijgt u nu een welkome e -mail in uw mailbox die door uw web -app is verzonden. Goed gedaan! Je hebt een lange weg afgelegd. Ik wilde toevoegen, als je ooit met fouten worstelt terwijl je aan een project als dit werkt, aarzel dan niet om naar antwoorden te zoeken en om hulp te vragen. Google, onder andere zoekmachines, zijn geweldige bronnen om te zoeken naar programmeerhulp. Zoek gewoon naar de fout die u krijgt en u kunt zien hoe andere mensen het probleem oplossen. Je bent ook van harte welkom om contact met mij op te nemen, je opvoeders (leraren, professoren, docenten), alle collega's op internet die beschikbaar zijn voor het programmeren van hulp, of dit boek opnieuw raadplegen of andere bronnen om oplossingen te vinden voor de problemen die je ondervindt. Ik begrijp dat dit niet eenvoudig is, maar zelfs als je zo ver hebt gelezen en geen code schrijft, leer je veel over het bouwen van een web -app helemaal opnieuw. Klop jezelf op de rug, je doet het geweldigfunctie. Bedankt dat je de tijd hebt genomen om deze Web Development Guide van de derde editie te lezen. In toekomstige edities zal ik meer van de belangrijke voorbeelden opnemen die in het begin van het document worden besproken en we zullen veel dieper in de wereld van software en hardware -ontwikkeling duiken. Blijf op de hoogte voor wat er gaat komen, en ik kijk ernaar uit je te leren hoe je ongelooflijke software kunt bouwen. Tot ziens in de volgende






Dichtbij
Pagina 1
Springen
Zie het volledige artikel
Lees verder

Kopen | Koop met crypto



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


(Klik of tik op om afbeelding te downloaden)
Professioneel entertainment, foto's, video's, audio, livestreaming en casual gameplay, evenals ID -scannen, webontwikkeling en draagmoederschap.

Laat me een tip achter in Bitcoin met dit adres: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

Voorwaarden van services