Praktiese webgebaseerde diepleer en sekuriteit deur voorbeeld

Daisyse profielfoto

Deur Daisy

Praktiese webgebaseerde diep leer en sekuriteit deur voorbeeld Derde uitgawe Charlotte Harper 3 Julie 2024 Voorwoord: Veiligheidsoorwegings in die bou van sagteware vir die web is 'n belangrike deel van die plan en uitvoering van enige webontwikkelaar, terwyl 'n prototipe wat betroubaar, stabiel en nuttig is vir praktiese doeleindes, ontwerp. Die DOM (Document Object Markup), met die implementering van HTML, JavaScript, en CSS, sowel as backend -sagteware wat Python, C/C ++, Java en Bash implementeer, gee webontwikkelaars die vryheid en krag om 'n wye verskeidenheid projekte te skep wat uitdruk wat uitdruk wat uitdruk wat uitdruk wat uitdruk wat uitdruk wat uitdruk wat uitdruk. kreatiwiteit, bied gemaklike gebruik en funksionaliteit, beeld nederigheid en karakter uit, en bied gemaklike gebruik sowel as gemak en belangrike dienste wat almal aantreklik is vir die gemiddelde Joe, die Eindgebruiker wat tyd wil doodmaak of iets op die internet doen, gewoonlik op 'n aanraakskerm -slimfoonapparaat. Die meeste mense sal nie eens weet waar om te begin as hulle van nuuts af 'n webwerf wil bou nie,Hulle sal geneig wees om op 'n ander persoon se webwerf te begin en iets beperk te bou in funksionaliteit, betroubaarheid, gebruiksgemak en veral kreatiwiteit toe hulle al die nuutste kragtige gereedskap tot hul beskikking kon gehad het om iets nuttigs te bou sonder om tyd te mors om te druk op die knoppies, en Veral geld mors om te betaal vir duur intekeninge op sagteware wat min mense in elk geval wou gebruik, gegewe die beperkinge in die gemak en buigsaamheid. As u 'n paar minute het om hierdie boek deur te lees en te leer wat ek u wil leer, of selfs persoonlik met my praat oor u doelwitte en 'n bietjie leiding in die regte rigting kry, en gemotiveerd is om te leer om u eie sagteware te kodeer en te skryf , neem hierdie boek huis toe en sit 'n geruime tyd opsy om te leer om die volgende invloedryke, kragtige, vaartbelynde en belangrike webtoepassing te bou, 'n webwerf wat alles op u is en presies doen wat u wil hê en aan die behoeftes van u gehoor voldoen. Oor my: Ek is 'n sagteware -ontwikkelaar met 'n wyeAnge of Experience in C/C ++, Java, Python, HTML, CSS en JavaScript. Ek bou webwerwe wat mense wil gebruik, wil besoek en selfs verslaaf raak aan die gebruik net om tyd te leer, te herskep en dood te maak, en die belangrikste is dat ek sagteware verkoop. As u 'n idee gehad het om presies te hê hoe u 'n webwerf wou hê om te lyk en te funksioneer, was u bereid om my te ondersteun, sodat ek aan my eie behoeftes kan voldoen terwyl ek aan u behoort, en u is bereid om die koste van die bestuur van 'n webwerf self te dek, Ek sou die volgende YouTube, Tiktok, Twitter, Google of selfs 'n hoë-tegnologie-sekuriteitsprogram vir u bou. In plaas daarvan om my tyd aan u te probeer verkoop, probeer ek die uwe koop: ek wil u praat om 'n app (webwerf) te bou met die inligting wat reeds bestaan, en u leer wat u nodig het om 'n onafhanklike sagteware -ontwikkelaar te wees, Entrepreneur, wat 'n suksesvolle loopbaan lei in watter veld u ook al wil. En laat my duidelik wees, die opvoeding wat ek aan u gee, sal informeel wees. U kan skool toe gaan en dit alles leer met 'nRMAL -onderwys, of selfs hierdie boek op skool lees, voltooi u opdragte en neem baie van u opleiding weg, maar ek sal u nie formeel in die warm sitplek plaas en u vra om opdragte uit te voer nie. Ek is nie u professor nie, u kan aan my dink soos 'n vriend wat u wil lei na 'n loopbaan wat deur u eie persoonlike sukses gedryf word. En ek verkoop ook nie u sukses nie, u moet dit met u tyd koop. Om te leer kodeer het 'n steil leerkurwe en was nooit maklik of selfs veronderstel om te wees nie. U moet so hard as moontlik werk en aanhou probeer om te misluk en weer te probeer, selfs as u gefrustreerd is om self programme te leer en te bou. Dit is in die aard van die kode self. Kode word bestuur deur 'n samesteller wat ontwerp is om die programmeerfoutboodskappe te gee, en dit sal u leer hoe om te kodeer, selfs al kopieer u die fout in u soekenjin en lees die voorbeelde van ander mense. En ek moet sê, jy hoef nie buitengewoon ryk, slim, suksesvol te wees nie,en detail georiënteerd of georganiseer om 'n app te bou. Die rekenaar sorg vir die organisasie vir u. U hoef net deur die proef en fout te volhard, fokus te handhaaf en hard te werk aan wat u doen, en u sal 'n baie suksesvolle loopbaan hê in die geheel van wat u doen. Wie ek is: Ek besef dat die laaste afdeling meer handel oor leer en u maniere uit hierdie boek neem. Wie is ek presies? Dit is 'n ingewikkelde vraag. Ek is onduidelik daaroor, aangesien ek aan mediese toestande ly wat dit vir my moeilik kan maak om hierdie boek selfs soms te kodeer of te skryf, terwyl ek uitdagings aanbied met sosialisering en identiteitskwessies wat my lewe moeiliker maak as dit kom by die bekendstelling van myself . Kortom, as u hierdie boek lees, het u dit huis toe gebring omdat u daardeur geslinger het en gedink het dit is nuttig, of selfs as u net so ver in lees, is ek vir u 'n soortgelyke individu wat wil sien dat u daarin slaag alles wat jy doen. Ek is self 'n ingenieur, 'n sagtewareOntwikkelaar en 'n student, en ek skryf hierdie boek vir ander studente wat hul lewens wil vergemaklik deur 'n handboek te hê van die sagteware wat hulle nodig het om hul lewens te vergemaklik deur voorbeelde te gee om te kopieer , Nuttige, groot, funksionele, samehangende en innemende app wat sukses kan veroorsaak, ongeag die onderneming. Dit is grotendeels wat ek doen: ek bou programme om myself en ander mense te help slaag. Ek is ook 'n skrywer, hoewel dit my eerste publikasie is wat ek van plan is om te voltooi om my portefeulje in 'n nuttige dokument saam te stel, en ek is ook 'n kunstenaar. Ek sal dit aan u erken, ek is 'n vreemde persoon. Ek is nie perfek nie, ek het die wetgewing gehad met die wet wat my selfs daartoe gelei het om kolleges en universiteite te verlaat en state te verlaat om myself met meer sukses te probeer noem. Ek is 'n vrou van geboorte af, ek dra grimering, neem foto's van myself, dra rokke en ander damesklere, en ek bly bewus van myself as 'nmanlik van nature. Ek het in die verlede probleme met ander mense gehad wat lei tot sukkel met die skryf en bou van webapps, en ek vra om verskoning dat ek nie vroeër hierdie boek in u hande kon kry nie: u het dit nodig gehad. U sal kode wil lees en skryf wat soos myne lyk en soos myne werk en dieselfde ding doen, maar nog beter, want as u dit kan bekostig om hierdie boek te koop in plaas daarvan om u sleutelbord te fyn soos ek doen net om self 'n boek te skep wat geld vra Daarvoor het u die hulpbronne wat u nodig het om suksesvol te wees in u lewe. Ek het allerhande probleme gehad met die grootword van die gesin, gesondheidstoestande, dokters, die media en die wet, en my kode weerspieël diep die stryd wat feminisme en vroulike natuur in 'n verdeelde en gefrustreerde wêreld is. Hierdie boek is egter iets waarvoor ek diep omgee, my baba, my portefeulje en my bestaan, so ek waardeer u oorweging as u die teks huis toe neem en dit noukeurig daaroor porie om van my te leer. Hou in gedagte dat ek nie perfek is nie,Die boek sal foute, hersienings en nuwe uitgawes hê, en u sal so goed as moontlik met u logiese brein moet dink om 'n suksesvolle ervaring met my skryfwerk te hê. Verstaan ​​ook dat ek goed bedoel vir u, selfs as u uitdagings in die gesig staar as u skryf. Dink daaraan: as u net 'n rekenaarstelsel kan huur om alles te doen wat u moontlik in die digitale ruimte kan voorstel, al die inligting wat u teëkom, #$%! Yze en organiseer en dit verstaan, sal u dit verstaan Probleme met die inligting wat u inneem en selfs publiseer. Ek sê dit vir u omdat ek dieselfde probleme ondervind. Gebruik hierdie boek op u eie risiko, werk saam met u gemeenskap en gemeenskappe wat u beskikbaar het om sagteware binne 'n veilige omgewing te bou, en neem nie dinge na persoonlik as u misluk of selfs op die verkeerde manier slaag nie: dit is hoe ek so ver gekom het , en waarom ek hierdie teks vir u kan bring en u kan help om te slaag sonder om af te afwyk op 'n pad van waansin wat vertrekEk het verwoes, geskeur en verswak terwyl ek die gewone probleme ondervind wat almal op 'n wêreldwye skaal doen danksy die paralellistiese wêreldwye skaal van die netwerk waarop ons sal werk, die internet. U is miskien nie baie vertroud met wie ek met net 'n paar woorde is nie, maar ek moedig u aan om verder te lees, u sal my leer ken as u aanhou om my te lees en te verstaan ​​terwyl u u eie projekte bou om u werk te voltooi. Daar sal geen huiswerk met hierdie boek wees nie, solank u professore of onderwysers u nie toewys nie, maar ek moedig u sterk aan om self 'n portefeulje projekte te bou terwyl u saam lees, sowel as 'n Capstone -projek wat wys hoe u kan Pas toe wat u geleer het. My Capstone -projek is die basis vir die meeste van wat u in hierdie boek sal lees, aangesien dit kode bevat uit my vorige projekte, kode wat ek geskep het en geleer het om metodies met die hand te skryf, en 'n wye verskeidenheid idees en wenke wat my gehelp het slaag tot die punt waar ek 'n eenvoudige app kan opdokUlly verskyn en lyk en gedra hulle soos 'n gewilde app wat u kan sien dat u vriend of familie op die internet aan u geadverteer word, of in die nuus. Wat hierdie boek is: Hierdie boek is 'n handleiding volgens voorbeeld. U kan kode hier vind, instruksies vir hoe om te leer om te kodeer, inligting oor ontfoutingskode en foute op te los, stappe op te los, instruksies oor hoe u u kode kan rugsteun en stoor, weer te ontplooi as iemand u kode breek, u kode beveilig, ontplooi, ontplooi U kode, bou interaktiewe webwerwe wat vermaaklik, innemend en verslawend is, en u sal 'n idee kry van wie ek is, waarom dit belangrik is, en hoe u uself, u app en die maatskappy se beeld, sowel as die Sagteware wat u in die absolute beste lig bou om die aantreklikste as moontlik vir u eindgebruikers, die besoekers van u webwerf, te wees. In hierdie boek s...
Praktiese webgebaseerde diepleer en sekuriteit deur voorbeeld

Praktiese webgebaseerde diep leer en sekuriteit deur voorbeeld Derde uitgawe Charlotte Harper 3 Julie 2024 Voorwoord: Veiligheidsoorwegings in die bou van sagteware vir die web is 'n belangrike deel van die plan en uitvoering van enige webontwikkelaar, terwyl 'n prototipe wat betroubaar, stabiel en nuttig is vir praktiese doeleindes, ontwerp. Die DOM (Document Object Markup), met die implementering van HTML, JavaScript, en CSS, sowel as backend -sagteware wat Python, C/C ++, Java en Bash implementeer, gee webontwikkelaars die vryheid en krag om 'n wye verskeidenheid projekte te skep wat uitdruk wat uitdruk wat uitdruk wat uitdruk wat uitdruk wat uitdruk wat uitdruk wat uitdruk. kreatiwiteit, bied gemaklike gebruik en funksionaliteit, beeld nederigheid en karakter uit, en bied gemaklike gebruik sowel as gemak en belangrike dienste wat almal aantreklik is vir die gemiddelde Joe, die Eindgebruiker wat tyd wil doodmaak of iets op die internet doen, gewoonlik op 'n aanraakskerm -slimfoonapparaat. Die meeste mense sal nie eens weet waar om te begin as hulle 'n webwerf wil bou niekrap, hulle sal geneig wees om op 'n ander persoon se webwerf te begin en iets beperk te bou in funksionaliteit, betroubaarheid, gebruiksgemak en veral kreatiwiteit toe hulle al die nuutste kragtige gereedskap tot hul beskikking kon gehad het om iets nuttigs te bou sonder om tyd te mors om die knoppies te druk , en veral om geld te mors om duur intekeninge aan sagteware te betaal wat min mense in elk geval wou gebruik, gegewe die beperkinge in die gemak en buigsaamheid daarvan. As u 'n paar minute het om hierdie boek deur te lees en te leer wat ek u wil leer, of selfs persoonlik met my praat oor u doelwitte en 'n bietjie leiding in die regte rigting kry, en gemotiveerd is om te leer om u eie sagteware te kodeer en te skryf , neem hierdie boek huis toe en sit 'n geruime tyd opsy om te leer om die volgende invloedryke, kragtige, vaartbelynde en belangrike webtoepassing te bou, 'n webwerf wat alles op u is en presies doen wat u wil hê en aan die behoeftes van u gehoor voldoen. Oor my: Ek is 'n sagteware -ontwikkelaar metReeks ervaring in C/C ++, Java, Python, HTML, CSS en JavaScript. Ek bou webwerwe wat mense wil gebruik, wil besoek en selfs verslaaf raak aan die gebruik net om tyd te leer, te herskep en dood te maak, en die belangrikste is dat ek sagteware verkoop. As u 'n idee gehad het om presies te hê hoe u 'n webwerf wou hê om te lyk en te funksioneer, was u bereid om my te ondersteun, sodat ek aan my eie behoeftes kan voldoen terwyl ek aan u behoort, en u is bereid om die koste van die bestuur van 'n webwerf self te dek, Ek sou die volgende YouTube, Tiktok, Twitter, Google of selfs 'n hoë-tegnologie-sekuriteitsprogram vir u bou. In plaas daarvan om my tyd aan u te probeer verkoop, probeer ek die uwe koop: ek wil u praat om 'n app (webwerf) te bou met die inligting wat reeds bestaan, en u leer wat u nodig het om 'n onafhanklike sagteware -ontwikkelaar te wees, Entrepreneur, wat 'n suksesvolle loopbaan lei in watter veld u ook al wil. En laat my duidelik wees, die opvoeding wat ek aan u gee, sal informeel wees. U kan skool toe gaan en dit alles leer met 'nFormele onderwys, of selfs hierdie boek op skool lees, voltooi u opdragte en neem baie van u opleiding weg, maar ek sal u nie formeel in die warm sitplek plaas en u vra om opdragte te voltooi nie. Ek is nie u professor nie, u kan aan my dink soos 'n vriend wat u wil lei na 'n loopbaan wat deur u eie persoonlike sukses gedryf word. En ek verkoop ook nie u sukses nie, u moet dit met u tyd koop. Om te leer kodeer het 'n steil leerkurwe en was nooit maklik of selfs veronderstel om te wees nie. U moet so hard as moontlik werk en aanhou probeer om te misluk en weer te probeer, selfs as u gefrustreerd is om self programme te leer en te bou. Dit is in die aard van die kode self. Kode word bestuur deur 'n samesteller wat ontwerp is om die programmeerfoutboodskappe te gee, en dit sal u leer hoe om te kodeer, selfs al kopieer u die fout in u soekenjin en lees die voorbeelde van ander mense. En ek moet sê, jy hoef nie buitengewoon ryk, slim te wees nie,Essful, of selfs detailgerig of georganiseerd om 'n app te bou. Die rekenaar sorg vir die organisasie vir u. U hoef net deur die proef en fout te volhard, fokus te handhaaf en hard te werk aan wat u doen, en u sal 'n baie suksesvolle loopbaan hê in die geheel van wat u doen. Wie ek is: Ek besef dat die laaste afdeling meer handel oor leer en u maniere uit hierdie boek neem. Wie is ek presies? Dit is 'n ingewikkelde vraag. Ek is onduidelik daaroor, aangesien ek aan mediese toestande ly wat dit vir my moeilik kan maak om hierdie boek selfs soms te kodeer of te skryf, terwyl ek uitdagings aanbied met sosialisering en identiteitskwessies wat my lewe moeiliker maak as dit kom by die bekendstelling van myself . Kortom, as u hierdie boek lees, het u dit huis toe gebring omdat u daardeur geslinger het en gedink het dit is nuttig, of selfs as u net so ver in lees, is ek vir u 'n soortgelyke individu wat wil sien dat u daarin slaag alles wat jy doen. Ek is self 'n ingenieur,Ontwikkelaar en 'n student, en ek skryf hierdie boek vir ander studente wat hul lewens wil vergemaklik deur 'n handboek te hê van die sagteware wat hulle nodig het om hul lewens te vergemaklik deur voorbeelde te gee om te kopieer , Nuttige, groot, funksionele, samehangende en innemende app wat sukses kan veroorsaak, ongeag die onderneming. Dit is grotendeels wat ek doen: ek bou programme om myself en ander mense te help slaag. Ek is ook 'n skrywer, hoewel dit my eerste publikasie is wat ek van plan is om te voltooi om my portefeulje in 'n nuttige dokument saam te stel, en ek is ook 'n kunstenaar. Ek sal dit aan u erken, ek is 'n vreemde persoon. Ek is nie perfek nie, ek het die wetgewing gehad met die wet wat my selfs daartoe gelei het om kolleges en universiteite te verlaat en state te verlaat om myself met meer sukses te probeer noem. Ek is 'n vrou van geboorte af, ek dra grimering, neem foto's van myself, dra rokke en ander damesklere, en ek bly bewus van myself as 'nvroulik van nature. Ek het in die verlede probleme met ander mense gehad wat lei tot sukkel met die skryf en bou van webapps, en ek vra om verskoning dat ek nie vroeër hierdie boek in u hande kon kry nie: u het dit nodig gehad. U sal kode wil lees en skryf wat soos myne lyk en soos myne werk en dieselfde ding doen, maar nog beter, want as u dit kan bekostig om hierdie boek te koop in plaas daarvan om u sleutelbord te fyn soos ek doen net om self 'n boek te skep wat geld vra Daarvoor het u die hulpbronne wat u nodig het om suksesvol te wees in u lewe. Ek het allerhande probleme gehad met die grootword van die gesin, gesondheidstoestande, dokters, die media en die wet, en my kode weerspieël diep die stryd wat feminisme en vroulike natuur in 'n verdeelde en gefrustreerde wêreld is. Hierdie boek is egter iets waarvoor ek diep omgee, my baba, my portefeulje en my bestaan, so ek waardeer u oorweging as u die teks huis toe neem en dit noukeurig daaroor porie om van my te leer. Hou asseblief in gedagte dat ek nie is nieECT, hierdie boek sal foute, hersienings en nuwe uitgawes hê, en u sal so goed as moontlik met u logiese brein moet dink om 'n suksesvolle ervaring met my skryfwerk te hê. Verstaan ​​ook dat ek goed bedoel vir u, selfs as u uitdagings in die gesig staar as u skryf. Dink daaraan: as u net 'n rekenaarstelsel kan huur om alles te doen wat u moontlik in die digitale ruimte kan voorstel, al die inligting wat u teëkom, #$%! Yze en organiseer en dit verstaan, sal u dit verstaan Probleme met die inligting wat u inneem en selfs publiseer. Ek sê dit vir u omdat ek dieselfde probleme ondervind. Gebruik hierdie boek op u eie risiko, werk saam met u gemeenskap en gemeenskappe wat u beskikbaar het om sagteware binne 'n veilige omgewing te bou, en neem nie dinge na persoonlik as u misluk of selfs op die verkeerde manier slaag nie: dit is hoe ek so ver gekom het , en waarom ek hierdie teks vir u kan bring en u kan help om te slaag sonder om af te verskil op 'n waansinAves Me het verwoes, geskeur en verswak terwyl ek die gewone probleme ondervind wat almal op 'n wêreldwye skaal doen danksy die paralellistiese wêreldwye skaal van die netwerk waarop ons sal werk, die internet. U is miskien nie baie vertroud met wie ek met net 'n paar woorde is nie, maar ek moedig u aan om verder te lees, u sal my leer ken as u aanhou om my te lees en te verstaan ​​terwyl u u eie projekte bou om u werk te voltooi. Daar sal geen huiswerk met hierdie boek wees nie, solank u professore of onderwysers u nie toewys nie, maar ek moedig u sterk aan om self 'n portefeulje projekte te bou terwyl u saam lees, sowel as 'n Capstone -projek wat wys hoe u kan Pas toe wat u geleer het. My Capstone -projek is die basis vir die meeste van wat u in hierdie boek sal lees, aangesien dit kode bevat uit my vorige projekte, kode wat ek geskep het en geleer het om metodies met die hand te skryf, en 'n wye verskeidenheid idees en wenke wat my gehelp het slaag tot die punt waar ek 'n eenvoudige app kan opdokTen volle voorliefde en lyk en gedra hulle soos 'n gewilde app wat u kan sien dat u vriend of familie op die internet aan u geadverteer word, of in die nuus. Wat hierdie boek is: Hierdie boek is 'n handleiding volgens voorbeeld. U kan kode hier vind, instruksies vir hoe om te leer om te kodeer, inligting oor ontfoutingskode en foute op te los, stappe op te los, instruksies oor hoe u u kode kan rugsteun en stoor, weer te ontplooi as iemand u kode breek, u kode beveilig, ontplooi, ontplooi U kode, bou interaktiewe webwerwe wat vermaaklik, innemend en verslawend is, en u sal 'n idee kry van wie ek is, waarom dit belangrik is, en hoe u uself, u app en die maatskappy se beeld, sowel as die Sagteware wat u in die absolute beste lig bou om die aantreklikste as moontlik vir u eindgebruikers, die besoekers van u webwerf, te wees. In hierdie boek sal ek 'n aantal voorbeelde van sagteware -ontwerp demonstreer met die fokus op die web as 'n platform sowel as sekuriteit. Ons sal die leerervaring inisieer deur 'n basiese op te bouOJECT met behulp van die Unix Shell, met rugsteun- en skripfunksies. Dan sal ons 'n basiese blogwebwerf ondersoek, ons blog opgradeer met foto- en video -funksies, sowel as om hierdie funksies te gebruik om sekuriteitsoplossings met behulp van gratis sagteware te gebruik, en ons bediener te beveilig met behulp van 'n inprop -verifikasiemodule (PAM). Ons sal dan onder andere die hantering en verwerking van lêer en verwerking, verkenning van videoredigering, stemskenking, strepieskode en optiese karakterherkenning, ondersoek. Langs die pad sal ons API's ondersoek, wat ons sal help om ons sagteware bruikbaar en veilig te maak, met gratis en betaalde opsies. Onderweg sal ons fisiese sekuriteit en militante instrumente soos vuurwapens en ontwerp en vervaardiging van ammunisie ondersoek, insluitend vat en herhaler -ontwerp, rewolwer- en drone -ontwerp, en ander prinsipale wat ons met ons sagteware op die bestaande netwerk sal integreer om ons sagteware te beskerm en demonstreer selfverdediging en resillience. Ons sal pouses neem om speletjies te bou, 2D en 3DEnderering -enjins, en werk met ingebedde hardeware in gevallestudie -voorbeelde van basiese dimensionele weergawesagteware en 'n elektroniese vibrerende massager wat onderskeidelik in silikoonrubber gegiet is. Onderweg gebruik ons ​​ook masjienleeroplossings wat reeds beskikbaar is om ons sagteware beter te beveilig. Ons sal ook voorraadinstrumente beskikbaar vir die web gebruik om die proses te stroomlyn en te beveilig. Hierdie boek is 'n gids vir u sukses in die opbou van 'n webtoepassing en die integrasie van dit met 'n professionele netwerk van rekenaar- en ingebedde meganiese stelsels, en in die algemeen 'n gids vir die bou van sagteware en ingebedde hardeware sonder agtergrondkennis of vorige ervaring. Wat hierdie boek nie is nie: As u regtig 'n webwerf wil hê, kan u net 'n eenvoudige winkel opstel en verkoop wat u nodig het, 'n blog plaas, foto's of video's plaas, of andersins sonder om ooit 'n enkele reël kode te skryf. Hierdie boek is nie so nie. Hierdie boek leer u hoe om sagteware te bou wat meer bruikbaar isGevolglik, funksioneel en veilig as enige sagteware wat u reeds kan vind, omdat dit die nuutste sagteware wat nog prototipes is, ontplooi, kan dit duur wees om op 'n skaal te werk wat ouer ondernemings werk, en nie 'n beroep doen op agtertoe, ingewikkelde maatskappye wat opgestel is nie Maak geld vir mense wat niks doen nie. As u hierdie boek noukeurig volg, wil u kode skryf, navorsingskode skryf, u eie programme bou, en u geld verdien uit wat u doen. Ek sal geld verdien uit hierdie boek, selfs in vroeë stadiums, omdat dit inligting bevat wat mense nodig het en wil lees, en al koop hulle my programme koop of gebruik. Hierdie boek sal nie 'n app vir u bou nie, maar dit sal u in die regte rigting wys en u bewapen met die gereedskap wat u benodig en die vaardighede en wenke wat u eie sukses in die bou van sagteware vir die web sal vergemaklik, met elke reël van kode wat u moet skryf as voorbeeld, gereed om saam te werk in sagteware wat u en u ondersteuners, gaste, klante,Riends, familie, besoekers, kontrakteurs en die mense van die internet wil gebruik en ondersteun. Wat jy sal leer: Hierdie boek leer u hoe om sagteware te bou en te verkoop, regtig funksionele, nuttige sagteware, media -opname, sekuriteitsfunksies soos gesigsherkenning, masjienleesbare sone -strepieskode, Web API's om video- en foto's te verifieer en te lewer, en boodskappe soos Bluetooth uitruil en naby veld (NFC) kommunikasie. Hierdie boek leer u hoe om 'n netwerkrekenaar te gebruik, met die fokus op Debian Linux, hoe om bash -kode te bou om u sagteware 'n naatlose, outomatiese briesie te maak, hoe om Python -kode te bou as 'n backend om dinamiese boodskappe te bedien, styl, styl Dinge met behulp van CSS -style met bootstrap, maak gebruikersaanmeldings en interaktiwiteit deur netwerktoestelle moontlik, bou interaktiewe media en netwerk met ander webwerwe om sekuriteitsfunksies soos sms -boodskappe aan te bied Vir verifikasie of ander doeleindes, ID -skandering, beeld- en video -moderering, dataRansaksies om u sagteware veilig te hou, betalingsverwerking, cryptocurrency -handel, asinchroniese take, en meer. U sal leer hoe om u eie Bluetooth -toestelle te bou, met batterye, laaiers, mikrobeheerders, stroombane, motors en sensors, met behulp van soldeer, draad en 3D -gedrukte sowel as gegote materiale. Ek sal 3D -ontwerphoofde demonstreer wat toegepas word op toevoegingsvervaardiging en gereedskap en die vervaardiging, sodat u u eie ingeboude, hardeware -toestelle met geïntegreerde batterye, laaiers, elektroniese stroombane en funksionele uitsette kan vervaardig. en netwerk met Bluetooth en die web. Spesifiek sal ons twee gevallestudies ondersoek, 'n vibrerende massager en 'n tuisgemaakte vuurwapen, albei geprogrammeer in OpenSCAD, wat beskikbaar is as 'n grafiese koppelvlak of opdragreëlprogram en in 'n web geïntegreer kan word vir vinniger resultate. U sal leer hoe om 'n webwerf van die grond af te bou en te ontplooi sonder enige vorige ervaring, dit funksioneel, veilig, mooi, nuttig en die meeste te maakMortant prakties. U sal leer hoe om masjienleer en rekenaarvisie te gebruik om 'n webwerf veilig en meer prakties te maak, video en klank op u webwerf op te neem, u stem te skenk, musiek te maak en klank te moduleer om nuttige monsters te skep, en hoe u deur die geraas kan breek Gebruik ander webwerwe om die beste moontlike netwerk van webwerwe te bou wat u direk aan u kan koppel om al die nuttige inligting wat u moet bied, te deel, en nog belangriker te maak, bring mense na u sagteware en besigheid. Hierdie boek sal die meeste gefokus wees op media, sekuriteit en masjienleer, wat die belangrikste drie komponente is wat u sal help om nuttige sagteware vir die web op te bou deur die regte gebruikers te betrek en die verkeerde manier te ontkoppel op 'n realistiese, praktiese manier Hands aan en innemend terwyl dit ook outomaties en stewig is. Hierdie boek leer Unix, spesifiek Debian (Ubuntu), Bash Shell, Python, HTML, CSS, JavaScript, en 'n aantal nuttige sagtewarepakkette virn Soos versoeke, sowel as nuttige bash -sagteware soos Git en FFMPEG. Ek sal u ook leer hoe om cryptocurrency outomaties te verhandel en betalings in cryptocurrency of van gewone debietkaarte te neem, terwyl u u besoekers selfs 'n deel van u inkomste uitbetaal as u dit wil doen. Ek sal u leer hoe om geld op u webwerf te verdien deur middel van advertensies, hoe u u app gereed kan maak vir soekenjins en dit vinnig kan maak, op die eerste rangorde gerangskik vir wat u kliënte sal soek om u te vind, en in soveel algemene rangorde te rangskik soektogte as moontlik. Ek sal u leer hoe om u sagteware te verkoop, dit te adverteer, 'n beroep op kliënte te soek wat u dienste soek en 'n naam vir uself op die internet te maak deur middel van moontlikhede wat reeds bestaan, goedkoop is en goed werk. Ek sal u leer hoe om u data te stoor op wolkrekenaars wat vir u werk en u data goedkoop stoor, hoe om 'n webwerf te beplan en te bou wat doen wat u gebruikers wil hê en wat u wil hê, en hoe om u gebruikers besig te houAs u 'n tik op hul telefone is met kennisgewings, e -pos, sms -boodskappe, telefoonoproepe en meer weë om u gebruikers na u webwerf terug te bring tot u beskikking agter die klik van 'n knoppie wat u slegs beveilig het. Hierdie boek fokus op die praktiese van die publikasie en verspreiding van media in groot hoeveelhede, van teks tot foto's tot video's tot klank, 'n goeie indruk op eindgebruikers (u klante) en uself verkoop op enige manier wat u doen om te skep om te skep 'N Webwerf, 'n app wat slegs van u en u is, en u, u sagteware en u onderneming op die beste manier goed lyk. U sal ook 'n paar wenke en truuks van my leer, van koderingswenke, praktiese nietigheid soos grimering en fotografie, modellering en toneelspel, en meer, wat belangrik sal wees om uself en u onderneming in die beste moontlike lig uit te beeld met al die beskikbare instrumente met behulp van al die beskikbare instrumente aan u terwyl u soveel inhoud versprei as wat u nodig het oor 'n gesonde balans van platforms om u te bringe om te werk sonder meer moeite, werk of geld as wat nodig is. Hierdie boek word om 'n rede 'praktiese webgebaseerde diep leer en sekuriteit' genoem: dit handel oor leer om te kode die praktiese doeleindes soos uiteengesit in die teks. Die leerkomponent van hierdie teks omvat ook masjienleer, die kode wat ek u sal wys hoe om te werk vir die web wat rekenaarvisie, gesigsherkenning, beeld- en video -moderering, beeldverbetering, resolusieverbetering, beeldopskrif en ander take sal hanteer Voorspellingstatistieke afkomstig van beelde, soos die aard van die beeld as 'n outentieke, rekenaar-oordraagbare beeld, of 'n optiese kopie ('n foto van 'n afbeelding of 'n gedrukte foto). Masjienleer is baie belangrik as dit kom by websekuriteit en sagteware -sekuriteit, omdat dit take kan voorkom wat andersins onmoontlik was. U rekenaarTeken u aan met 'n wagwoordkode, maar dit kan veiliger wees om dit te gebruik as dit u met u gesig aanmeld. U kan 'n bediener -rekenaar hierdie kluis maak, 'n rekenaar wat u normaalweg 'n gebruikersnaam en ' Gebruik, fundamenteel veilig en kragtige sagteware, dit kan genoeg wees. Om u sagteware te nou aan iemand anders se sagteware te bind, soos 'n e -posdiens of 'n sms -boodskapdiens, is nie genoeg om u sagteware veilig te maak nie, of iemand se (enige webwerf wat u gebruik) nie. Enigiemand wat sagteware bou wat onberispelik veilig is, het 'n mate van gevoel van wat dit impliseer. Sagteware is inherent onseker omdat die toestelle en rekeninge wat ons gebruik om toegang daartoe te kry nie altyd tot ons beskikking is nie, hulle in die hande van iemand met 'n slegte voorneme vir die sagteware kan wees en daarom 'n risiko vir die sagteware self kan inhou. Dit is iets van die fokus van hierdie boek. 'N Netwerkrekenaar is standaardBeveilig met 'n lang sleuteltoken, genaamd en SSH of Secure Shell -sleutel, en is andersins die beste met 'n webbediener beveilig, omdat die webbediener die oop toegang en die stand van die kunsveiligheidsinstrumente op die bediener self bied. Die webbediener het toegang tot die gebruiker se webblaaier, wat waarskynlik die kragtigste deel van die gebruiker se toestel is, want dit is die plek waar die gebruiker toegang tot netwerk -sagteware het. Hierdie gereedskapstel kan teks lewer, die webblaaie wat u sien, en kan ook prente, klank en video opneem (soos 'n foto van 'n gesig of 'n toestand -ID), kan lees en skryf op Bluetooth -radio -toestelle, en kan lees en skryf na Near Field Transponder -etikette, goedkoop sleutelkaarte, fobs, plakkers, ringe en selfs chip -inplantings met unieke reeksnommers wat gelees en geskryf kan word met data wat gegenereer en bekragtig word deur 'n webbediener wat op die webwerf gekoppel is. Gebruik al die gereedskap tot u beskikking, met hierdie boek, sal u uself toerus met die kennis om 'n veilige webwerf te bou, en in die algemeen aURE -netwerk -rekenaarstelsel wat vir u werk, doen u bid en lyk en voel reg. Waar om te begin: U is welkom om verby die afdeling te slaan. Ek begin met hierdie boek met, of enige afdeling, na die presiese kode wat u benodig, veral as u ondervinding het met kodering voorheen of enige van die bogenoemde instrumente wat ek in hierdie boek in detail sal beskryf sowel as om gebruiksgevalle en praktiese voorbeelde daarvan te dokumenteer. As u nie ervaring in die skryf van kode het nie, beveel ek u aan om al hierdie boeke te lees, en beveel veral aan dat u die vorige afdelings lees, om seker te maak dat hierdie boek die beste by u is. As hierdie boek nie die beste by u is nie, oorweeg dit om dit aan 'n vriend of familielid te gee wat miskien belangstel om self oor webontwikkeling te leer, en dit selfs oorweeg om dit terug te leen en by hulle te leer om die leemtes in te vul waar ek u as 'n Onderwyser, of ander onderwysers het voor my gedoen. Begin waar u wil, elke deel van hierdie boek sal nuttig wees as u van plan is om 'n nuttige op te bouPP, en oorweeg dat die beste programme gebou is met die eindgebruiker in gedagte: ken u kliënt. Nou ken jy my, jy ken hierdie boek, en jy is gereed om te begin. Om mee te begin, gryp 'n rekenaar (selfs die goedkoopste skootrekenaar van 'n bokswinkel, Amazon of 'n ou tafelblad werk, en stel dit op 'n manier wat vir u werk. Hoe om hierdie boek te lees: Teks wat uitgelig is, dui aan dat die teks in 'n opdragprompt hoort, waar u die kode wat u uitgevoer het, sal skryf. Die opdragprompt is baie gefokus op die sleutelbord en benodig min tot geen klik nie, bespoedig u werkvloei en maak dit vir u makliker. Aan die gang: Kom ons duik in. Ons begin met die bou van kode op 'n plaaslike masjien en begin sonder om 'n webwerf wat aan die internet gekoppel is, te bou. Dit is veiliger om mee te begin, kos niks, en dit is maklik vir u. Afhangend van u bedryfstelsel, sal dit 'n bietjie anders wees om in 'n bash -dop te kom. Vir Mac OS beveel ek aan dat u op hierdie punt 'n virtuele masjien installeer, aangesien u die meeste verenigbaarheid sal kryvirtuele masjien. Verskeie verskaffers soos VirtualBox en Paralells kan 'n virtuele masjien vir u bestuur, hoewel dit ook moontlik is om Ubuntu direk op die masjien te installeer, as u verkies om 'n inheemse omgewing te gebruik wat aanbeveel word om 'n vinnige, vaartbelynde ervaring te skep. As u Linux of Windows gebruik, wat ek aanbeveel, moet dit maklik wees om 'n projek te skep. Maak u terminale oop, pas die grootte aan soos u inpas, en begin stap 2. As u Windows gebruik, volg Stap 1. Stap 1: - Slegs Windows -gebruikers Open Command Prompt as administrateur en tik in Windows in Windows WSL –install Stap 2: - Gaan hier voort, of slaan stap 1 oor tot hier as u nie Windows gebruik nie In 'n oop terminale (afhangende van u bedryfstelsel, genaamd Ubuntu in Windows, Terminal in Mac of Linux, of 'n soortgelyke naam), begin met die skep van 'n projek. Ons doen dit met die Mkdir -opdrag, wat 'n gids skep. Gebruik dieCD -opdrag om oor te skakel na die gids en en CD/pad/na/gids - Die pad is die gidse (lêers) wat voorafgaan aan u bestemmingsgids, u standaardpad is ~ of/huis/gebruikersnaam (waar gebruikersnaam u gebruikersnaam is). Om na die standaardgids te verander, tik CD of CD ~ in MKDIR Voorbeeld - Vervang 'voorbeeld' met die naam van die gids Nou het u 'n werkende gids vir u projek. Aangesien dit so belangrik is dat hierdie gids gestoor word as u na 'n ander masjien moet oorskakel of die kode wat u skryf, moet ontplooi, sodat dit gereed is vir die web, sal ons 'n skrif bou om u gids in die volgende paar stappe te rugsteun. Maar die bou van 'n skrif neem 'n bietjie kode in, en die kode moet outomaties wees om so bruikbaar as moontlik te wees. Laat ons dus 'n skrif bou om eers skrifte te bou. Laat ons begin deur die skrif te skep en uitvoerbaar te maak. Ons sal Sudo, Chmod en Touch hiervoor gebruik en die skrif noem


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Nou het ons die skrif geskep, dit uitvoerbaar gemaak en is gereed om dit te wysig. Nano is 'n teksredakteur waarmee u teks kan redigeer sonder om te klik, wat baie makliker is as om 'n grafiese gebruikerskoppelvlak te gebruik. Gebruik nano en dan die pad na die lêer om 'n lêer met Nano te wysig. Om 'n draaiboek te maak wat 'n draaiboek maak, is dit redelik soortgelyk aan die maak van ons skrif in die eerste plek. Ons gebruik dieselfde kode as hierbo en vervang die naam van die skrif, 'ASCript' met 'n argumentparameter, $ 1. Hiermee kan ons die skrif noem deur eenvoudig Sudo Astcript Newscript in te tik, op watter punt ons enige nuwe skrif kan skep deur 'newcript' met die naam van u skrif te vervang. Die kode in Nano moet lyk soos:

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
En om Nano te sluit, kan ons die kontrolesleutel vashou en X druk, dan Y om aan te dui dat ons die lêer stoor en op die terugkeer kom. In plaas daarvan om hierdie drie opdragte in te tik om 'n skrif te redigeer, sal ons Sudo Astcript AstScript kan tik om die skrif weer te wysig. Dit werk! En enige nuwe skrif kan maklik uitgevoer word deur dit in die dop te noem. Laat ons nou ons werk stoor: kom ons skryf 'n rugsteunskrip om ons nuwe skrif te stoor en dit dan in ons projekgids te rugsteun, terwyl ons ook die rugsteunskrip rugsteun.

sudo ascript backup
Nou, in Nano:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Waar/pad/na/gids die pad is na die projek wat u met MKDIR geskep het. Later sal ons leer hoe om herhaalde paaie soos hierdie te kopieer met 'n lus en 'n lys, wat minder kode is, maar laat ons dit nou eenvoudig hou en 'n paar reëls hê. Om hierdie skrip uit te voer en u kode te rugsteun, stoor die lêer in nano met control+x, y en return, en tik die onderstaande in u dop

backup
As u enigsins gevra word vir 'n wagwoord tydens die lees van hierdie boek en in die dop volg, voer u gebruikerswagwoord korrek in, u sal drie drieë hê voordat u die opdrag weer moet uitvoer. U kan die pyltjies op en af ​​gebruik om opdragte weer te gee en dit te redigeer as u iets twee keer moet hardloop. Eenvoudig druk op en af ​​af en toe om 'n opdrag te kies voordat u die opdrag met die regter-, linkerpyltjies en die sleutelbord sowel as die sleutelbord redigeer en dit met terugkeer loop. Baie geluk! U het daarin geslaag om 'n ongelooflike rugsteunskrip te skep wat twee belangrike skulpskripte in u werkgids ondersteun. Ons kan later dinge rondbeweeg namate die projek groter word, maar dit werk nou. Laat ons verder gaan met die rugsteun in die wolk, ons sal GitHub hiervoor gebruik (alhoewel daar talle ander git -oplossings vir rugsteun is, is dit alles omtrent dieselfde.) Git is 'n verdelingskontrolesagteware waarmee u wysigings aan u kan rugsteun sagteware soos u dit na 'n bediener maak, terwylStel u ook in staat om volledige kopieë van u sagteware agter 'n wagwoord of sleutel af te laai. Dit is 'n belangrike rol in die stoor van u sagteware, veral as ons na die beveiligde Linux -gevalle migreer wat soms breek as 'n enkele reël kode misluk, wat u uitsluit terwyl u kode nie gerugsteun word as u nie die kans kry om dit te ondersteun nie outomaties, wat ons sal dek. As u op hierdie punt nog nie 'n Ubuntu -virtuele masjien gebruik nie, beveel ek aan dat u 'n Ubuntu -virtuele masjien op hierdie punt gebruik, want dit sal u lewe vergemaklik wanneer u al die nodige pakkette installeer om 'n werkende webwerf te bou en diep leer bewerkings op u rekenaar. Ons sal die kode binne die nabye toekoms na 'n webbediener skuif, maar ons wil seker maak dat daar ten minste 'n paar lae sekuriteit agter ons webbediener is wat bestand is teen phishing, en 'n aantal Linux -pakkette gebruik om dit te kan doen hierdie. As u nog steeds Mac OS wil gebruik, is u welkom om na te soek en te installeerE nodige pakkette aanlyn, maar daar is miskien nie alternatiewe vir elke pakket wat hierdie boek of reeks dek nie. Kom ons voeg 'n paar opdragte by om ons werk met die rugsteunskrip te pleeg deur die opdrag sudo -askrip te voer

# ...
git add –all
git commit -m “backup”
git push -u origin master
Weereens, beheer X om te stoor. Nou moet ons eenmalige konfigurasie vir hierdie projek doen. Aangesien dit binnekort 'n GIT -projek sal wees, hoef ons nie elke opdrag te tik elke keer as ons van 'n Git -bewaarplek gebruik word nie, maar ons kry die weg as ons ons implementeringsskripte skryf. Laat ons eers seker maak dat ons in die regte gids is en die git -bewaarplek initialiseer en SSH -sleutels genereer.

cd /path/to/directory
git init
git branch -m master
ssh-keygen
Nadat ons SSH-Keygen ingetik het, moet die nuwe sleutel in die tuismap gestoor word onder 'n lêergids genaamd .SSH. Dit word ID_RSA.pub genoem. Kom ons vind hierdie sleutel en kopieer dit. Om dit te sien,

cd ~
cat .ssh/id_rsa.pub
Kopieer die teks wat deur die laaste opdrag teruggestuur word, en skep 'n rekening by u GIT -verskaffer (ideaal GitHub) voordat u die SSH -sleutel by u rekening voeg. Sodra u 'n rekening het, klik op die boonste regter -menu en voer instellings in voordat u u SSH -sleutel in SSH- en GPG -sleutels onder toegang in die menu voeg. Kies Voeg 'n SSH -sleutel by en voeg joune by deur dit in te plak en dit 'n titel te gee voordat u stoor en terugkeer na GitHub om 'n nuwe bewaarplek te skep. Dit is soortgelyk vir ander GIT -verskaffers, u moet hul dokumentasie lees. Gee u bewaarplek 'n beskrywende naam in die nuwe bewaarplekkonfigurasie en besluit of u dit wil publiseer, en maak seker dat u nog geen lêers vir insluiting opstel nie. Sodra die bewaarplek geskep is, kopieer die kloon met SSH URL en plak dit in die volgende opdrag.

git remote add git://… (your remote URL)
Nou kan u teruggaan na u bewaarplek met CD, u sal hiermee vertroud wees. Probeer nou u rugsteunskrif met rugsteun Groot! Nou kan ons regtig kodering kry. Laat ons django installeer noudat ons 'n goeie begrip van Bash en Git het. Django laat ons outomaties ons sagteware rugsteun, Bash kan dit ook doen, maar Django moet 'n eenvoudiger veiliger implementering hê (dit kan makliker gedeaktiveer en makliker gekonfigureer word). Om sagteware in Ubuntu te installeer, gebruik ons ​​die Sudo Apt-Get-opdrag. Laat ons eers die sagteware wat ons reeds gehad het, opdateer en opgradeer. Dit kan gedoen word met Sudo Apt-Get Update en Sudo Apt-Get Upgrade -Y. Laat ons nou Python en ons virtuele omgewing, die tuiste van ons kode, installeer, met die volgende opdrag: Sudo apt-Get Install Python-is-Python3 Python3-VENV Dit is al wat u nodig het om met Django aan die gang te kom in terme van sagteware -installasies in die Ubuntu -instansie. Vir Windows en Linux moet dit redelik eenvoudig wees, maar vir Mac wil u miskien 'n virtuele masjien installeer enLinux daarop met behulp van 'n gratis of betaalde virtuele omgewing soos VirtualBox of Paralells Desktop en herskep die bogenoemde stappe om 'n Ubuntu -omgewing op te stel. Ubuntu is in hierdie geval van kritieke belang omdat dit die sagteware is wat die webwerwe bestuur en dit in staat stel om webwerwe met al die bogenoemde sagteware aan te bied. Kom ons grawe in die django. Weer in ons gids, met

python -m venv venv # Skep die virtuele omgewing waar kode gestoor word
source venv/bin/activate # Aktiveer die virtuele omgewing
pip install Django
django-admin startproject mysite . # Waar MySite die projek is, begin ek in my huidige gids.
Django is net besig om ons aan die gang te kry, want Django bied die webbediener aan en doen alles wat ons nodig het om 'n basiese plaaslike webwerf aan die gang te kry. Noudat ons Django geïnstalleer het, laat ons die instellings 'n bietjie wysig om dit te laat werk soos ons nodig het. Laat ons eers 'n nuwe app skep

python manage.py startapp feed
U sal sien dat die eerste app Feed genoem word. Die app moet genoem word wat u wil, en ons sal nuwe programme skep, maar die naam van elke app moet konsekwent wees elke keer as die app in die kode verwys word. Om 'n nuwe app by te voeg, sal ons altyd die instellings.py wysig in die ander gids wat die app geskep het, genoem in StartProject, hierna App. Nano te gebruik,

nano app/settings.py
Vind geïnstalleerde_apps in die instellings en skei die [] in 3 reëls. Gebruik vier spasies op die leë middellyn, voeg 'voer' of die naam van u app by. Hierdie gedeelte van die instellings.py moet lyk soos:

INSTALLED_APPS = [
    'feed',
]
Laat ons toets dat Django werk voordat ons vergeet. Met behulp van die opdrag python management.py runserver 0.0.0.0:8000, kan ons die bediener bestuur en dan in 'n webblaaier op die rekenaar navigeer met die kode na http: // localhost: 8000 en sien 'n voorbeeld van die webblad (dit werk!) Staak die bediener met beheer C, dieselfde as enige ander opdrag. Laat ons nou 'n paar Python -kode skryf. Django het drie hoofkomponente, wat almal heeltemal volgens kode bestuur word. Die komponente word model, aansig en sjabloon genoem, en elkeen is onderskeidelik op 'n hoër en laer vlak voordat die webblad aan die gebruiker gelewer word. Die model is die kode wat inligting in die databasis stoor vir herwinning, sorteer en weergawes. Die siening besluit hoe die model weergegee, gemanipuleer en gewysig word, byna elke siening sal 'n model direk gebruik. Die sjabloon is die HTML -kode met 'n paar ekstra klokkies en fluitjies wat sjabloontaal genoem word. Die sjabloon word weergegee deur die aansig waar dit gevul is met die python -kode enKonteks soos modelle en inligting (USUALL -snare en heelgetalle) van die siening. Django het ook ander komponente, insluitend maar nie beperk nie tot: Instellings, wat die app opstel soos ons bespreek het. URL's, wat patrone is wat die gebruiker volg om toegang tot spesifieke dele van die webtoepassing te verkry. Vorms, wat definieer hoe inligting wat aan die bediener gestuur word, hanteer en aan die databasis sowel as die gebruiker weergegee word. Dit is die basis om inligting aan die bedienerkant te verwerk, en kan enige soort inligting wat die rekenaarwinkels aanvaar, veral teksstringe, nommers en ware/vals Boolese (gewoonlik merkblokkies). Sjablone, wat HTML -kode en sjabloontaal is en die gaping tussen Python en HTML oorbrug, wat beteken dat Python -inligting bedien kan word as HTML -kode wat iemand kan bekom en 'n webwerf met beperkte toegang kan beveilig, terwyl Python -kode toeganklik is vir die web en nuttig maak vir 'n verskeidenheid doeleindes op 'n afgeleë toestel wat dit nie doen nieeed om naby die bediener te wees. Statiese lêers, wat gewoonlik JavaScript is en dit is biblioteke wat die bediener dien en met die sjabloon gekoppel is. Media -lêers, wat die bediener bedien of ekstern aangebied word, of net aan die bediener geskryf is voordat hy verwerk word en na 'n ander bediener ('n emmer) geplaas word vir die aanbieding. Middleware, wat stukke kode is wat op dieselfde tyd as elke siening uitgevoer word en wat as “ingesluit” in die aansig beskou word. Konteksverwerkers, wat die konteks van elke siening verwerk en gebruik word om ekstra konteks by te voeg. Toetse, wat bevestig dat die gebruiker of versoek sekere vereistes aan die aansig gee. Verbruikers, wat bepaal hoe Websockets op kommunikasie hanteer en reageer. Admin, wat gebruik word om modelle te registreer, sodat dit in detail binne die Django -admin -bladsy gemanipuleer kan word, waar die databasis via 'n grafiese koppelvlak toegedien kan word. Seldery, wat asinchroniese take definieer dele van die django -kode kan beginNing voordat u onmiddellik voortgaan met die volgende taak of kode. Django kan baie ander komponente hê, wat ons hier in detail sal bespreek. Daar is baie maniere om Django meer funksioneel te maak, by te voeg van websockets, wat vinnige, vaartbelynde kommunikasiekanale, seldery is, wat asinchroniese take uitvoer, en 'n menigte ander sagteware vir die uitbreiding van django, veral in die sieningsfunksies, waar die meeste is Die kode word uitgevoer. Kykfunksies is die sleutel omdat dit gewoonlik elke stuk kode verklaar wat spesifiek is vir 'n spesifieke URL -patroon, of 'n gedeelte van die bediener. Laat ons eers kykfunksies ondersoek. Kykfunksies begin met invoer wat kode aandui wat in die aansig gebruik sal word, en word gedefinieer met behulp van gewone funksie -definisies of klasse. Die eenvoudigste aansigte word gedefinieer deur die funksie -definisie DEF, en gee 'n HTTPRESPONSE met 'n basiese sjabloon terug. Laat ons begin deur 'n basiese siening te definieer om die teks “Hello World” terug te gee. Onthou dat elke keer as u byvoegAs u 'n stelling soos DEF, indien u, ens, ens, u 4 ruimtes moet byvoeg vir elk van die voorafgaande definisies wat u op u funksie wil toepas. Ons sal binnekort begin wat elkeen hiervan beteken. Bewerk die Feed/Views.py -lêer in die gids van ons webwerf met behulp van nano en voeg die volgende reëls aan die einde van die

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
Django se httpresponse reageer met 'n teksstring, aangedui met die opening en sluiting '. Elke keer as u inligting aan 'n funksie of klas deurgee, soos versoek of 'n string, moet u hakies (, opening en sluiting) gebruik. Dit is nie al wat ons nodig het om ons siening te sien nie. Natuurlik het ons nie aan die bediener gesê waar die uitsig presies is nie; ons moet nog steeds 'n pad definieer waarmee die aansig moet lewer. Laat ons begin deur 'n basiese pad in app/urls.py te definieer, en ons sal later in padgroepe kom. Voeg 'n reël na die invoerstate in App/URLS.py na die begin van die uitsig wat ons pas geskep het.

from feed import views as feed_views
Laat ons nou die uitsigpatroon definieer. Kykpatrone het drie komponente, die padkomponent, wat aan die bediener sê waar die aansig binne die bediener bestaan ​​(die URL -pad wat die gebruiker in die navigasiebalk tik om die webblad in te gaan), die View -komponent waar die aansig gespesifiseer is, en A Vriendelike naam vir die uitsig, so dit is maklik om die patroon te haal as u met 'n sjabloon werk, veral sodat die naam daarvan verander kan word en indien nodig kan word om ruimte te maak vir 'n ander aansig of 'n meer logiese naam aan te neem. Dit is sinvol om dinge op hierdie manier te doen en buigsaam te wees, want u kodebasis sal 'n steeds veranderende omgewing wees wat buigsaamheid en improvisasie nodig het om waardevol en maklik te werk om mee te werk. Hier is hoe u siening sal lyk, u kan dit by die urlpatterns = [gedeelte van app/urls.py voeg. Die sieningspatroon word gedefinieer met die drie komponente hierbo beskryf, en 'n funksie genaamd Path. U URL -patrone is 'n lys, so maak seker dat u elke item altyd daarin beëindigmet 'n komma, want dit skei elkeen. Elke item moet ook op 'n nuwe lyn gaan, weer met vier ruimtes daarvoor, net soos die app in instellings.py. Ons definieer die eerste komponent van die aansig met 'n leë stringfunksie om 'n aansig te skep wat op die wortelgids van die webbediener werk. U urls.py moet nou lyk

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Dit is die basis om 'n webwerf met Django te skep wat heeltemal staties is. Om 'n meer dinamiese webwerf te maak waar ons inligting kan begin, soos prente, video's, klank en meer, moet ons modelle gebruik wat ons volgende gaan ondersoek. Kom ons kyk nou na ons kode en voer die bediener uit. Om die kode vir foute na te gaan, hardloop:

python manage.py check
As daar foutboodskappe is, moet u die veranderinge wat u aan u app aangebring het, noukeurig hersien en kyk of daar iets is wat reggestel moet word, soos 'n vreemde of gebreke ruimte, 'n ekstra karakter, 'n ongeslote string, enige tikfout, enige per ongeluk geskrap karakter, of enigiets anders. As u die foutboodskap deurlees (as u een het), moet u die pad kan sien na 'n lêer wat u geskep of geredigeer het saam met 'n reëlnommer, dus kyk na die lêer en reël en kyk of u iets kan regstel wat daar is . As u die probleem opgelos het, voer die bogenoemde opdrag weer uit. As u sagteware gereed is om te hardloop en werk, sal u die uitset “Stelselkontrole geïdentifiseerde probleme” sien. Nou is jy gereed om te gaan. Begin die bediener met:

python manage.py runserver 0.0.0.0:8000
Maak nou 'n webblaaier oop en navigeer na http: // localhost: 8000. U moet sien dat die teks in u mening in die hakies en aanhalings van die HTTPResponse -funksie teruggestuur word. Dit is net 'n basiese voorbeeld, maar as u dit tot dusver bereik het, verstaan ​​u die basiese beginsels van hoe Linux, Bash, Python en Django werk. Laat ons dieper in 'n paar databasismodellering delf en die krag van 'n Python -klas ondersoek in die stoor van inligting. Dan sal ons begin om HTML en CSS te gryp voordat ons ons webwerf volledig, buigsaam en veilig maak met JavaScript en masjienleer. Klasse word in die modelle.py van u app gestoor. Gebruik nano, wysig app/modelle.py en voeg 'n nuwe klas by. 'N Klas word gedefinieer met die klasdefinisie en word deur 'n superklas geslaag waaruit dit erf, in hierdie geval modelle. Model. Die naam van die klas kom na die klasdefinisie, en na die klasdefinisie a: (kolon) word gebruik voordat die eienskappe en funksionele definisies wat aan die klas gekoppel is, hieronder aangedui word. Ons klasBenodig 'n ID wat ons kan gebruik om dit op te spoor en uniek te hou, en dit benodig ook 'n teksveld om inligting te stoor. Later kan ons 'n tydstempel, lêers, booleërs byvoeg (ware of vals definisies wat ons kode kan help om besluite te neem oor wat om met die model te doen, en kan gebruik word om dit te sorteer), 'n voorbeeld om die model aan 'n gebruiker aan te teken in die bediener, en meer. Kom ons pak die kode uit

from django.db import models # Die invoer wat gebruik word om ons klas en sy eienskappe te definieer

class Post(models.Model): # Die definisie van ons klas self
    id = models.AutoField(primary_key=True) # Die ID van ons model, 'n outomaties gegenereerde sleutel waarmee ons die model kan bevraagteken, dit uniek kan hou en nuttig is as ons met die model moet omgaan sodra dit geskep is.
    text = models.TextField(default='') # Die eienskap wat ons klaswinkel in hierdie geval, in hierdie geval, 'n teks, wat standaard is vir 'n leë string.
Sluit en stoor die lêer soos voorheen om klaar te maak. Daar is baie ander velde en opsies wat ons sal ondersoek wanneer ons hierdie klas opdateer namate ons app ontwikkel, maar dit is die basiese benodigdhede om 'n app te skep om teks te plaas. Hierdie model sal egter nie alleen werk nie. Soos voorheen beskryf, benodig ons 'n pasgemaakte aansig en 'n pasgemaakte URL -patroon om hierdie model te laat werk, en ons sal ook 'n vorm saam met 'n sjabloon benodig. Kom ons ondersoek die vorm eers. Om 'n vorm te definieer, wysig app/vorms.py met nano en voeg die volgende reëls by. Ons benodig twee invoere, ons vormklas, sowel as die model wat ons geskep het (Feed.models.Post), 'n klasdefinisie soortgelyk aan die model, en 'n veld saam met 'n subklas genaamd meta wat die model sal definieer. Die vorm is in wisselwerking met. Die vorm kan ook 'n inisialiseringsfunksie hê wat dit opstel op grond van inligting in die versoek, model of andersins, ons sal dit later ondersoek. Modelvorms is so nuttig omdat dit 'n model kan skep of ook 'n model kan redigeer,Ons sal dit dus vir albei gebruik. Kom ons definieer een in vorms.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 die basiese beginsels van hoe 'n vorm en model lyk. Hierdie modelvorm kan gebruik word om 'n pos te installeer of te redigeer deur die teks wat dit bevat, te verander. Ons sal kyk na die integrasie van hierdie vorm in 'n uitsig. Laat ons eers die migrasies maak en die databasis migreer sodat ons kode met die model kan omgaan as dit loop. Om dit te doen, voer die volgende opdragte uit:

python manage.py makemigrations
python manage.py migrate
Dit sal 'n minuut neem om uit te voer, maar sodra dit dit doen, sal dit u toelaat om toegang tot die model in die aansigte, middelware of op enige ander plek in die sagteware te kry. Laat ons voortgaan deur 'n siening te maak waar ons ons model kan sien. Wysig Feed/Views.py en voeg die volgende kode by, soos aangedui. U hoef niks by te voeg na die # teken nie, die kode is kommentaar wat gebruik word om inligting oor die kode aan te dui. Ons sal begin met die invoer van ons model in die sienings en dit by te voeg tot 'n konteks waar ons dit in 'n sjabloon kan lewer as 'n lys om te vertoon. Vervolgens voeg ons 'n sjabloon by waar ons die vorm en die model met 'n knoppie kan lewer om 'n nuwe voorwerp te skep wat gebaseer is op die model en dit op die bediener kan plaas. Dit klink ingewikkeld, so laat ons dit net stap vir stap neem. Voordat ons klaar is met die aansig, laat ons 'n sjabloon skep wat die model net weergee en seker maak dat ons dit kan sien deur 'n nuwe pos in die dop te skep. Hier is hoe daardie siening moet lyk:

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

def feed(request):
    posts = Post.objects.all() # Vra tot dusver al die plasings in die databasis
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })
Dit lyk alles redelik eenvoudig totdat ons onderaan kom. Weergegee, die waarde wat deur die funksie teruggestuur word in plaas van in 'n HTTP -antwoord soos die vorige voorbeeld, neem altyd 'n versoek as die eerste inset, aanvaar 'n konteks (in hierdie geval die poste in die databasis), wat nou in die sjabloon weergegee kan word , en gee die sjabloon wat in die funksie gedefinieër is, terug. Die sjabloon gaan 'n HTML -dokument wees met 'n bietjie taal genaamd Jinja2, wat Python -inligting in die HTML lewer. Maak twee kaarte in voer om sjablone te begin skep.

mkdir feed/templates
mkdir feed/templates/feed
Bewerk vervolgens 'n sjabloon in die gids hierbo, voer/sjablone/voer, en voeg die kode by vir hierdie voorbeeld. Kom ons kyk na die sjabloon vir hierdie voorbeeld.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Dit is 'n baie eenvoudige sjabloon. Dit definieer die opening en sluiting van HTML -etikette, 'n dokumenttipe -etiket, 'n liggaamsmerk met 'n legende titel, 'n breekplaatjie wat 'n klein lyn oor die skerm voeg, en 'n vir lus wat elke pos in die lys van plasings as 'n paragraaf in die sjabloon. Dit is al wat nodig is om poste te lewer, maar daar is nog niemand in die databasis nie. Laat ons 'n paar met die dop skep. Ons kan die dop met bestuur.py bestuur

python manage.py shell
Laat ons nou ons posmodel invoer

from feed.models import Post
Vervolgens sal ons 'n eenvoudige pos met 'n tou skep en die dop verlaat. Die string kan enigiets wees, solank dit 'n geldige teks is.

Post.objects.create(text='hello world')
exit()
Laastens moet ons 'n URL -patroon by ons voer voeg. Aangesien ons voerprogram verskeie URL's sal gebruik en ons lêergroottes klein wil hou, laat ons 'n plaaslike URL.py skep in ons voerprogram wat so lyk:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
Ons sal ook die URLS.py in die basis -app moet redigeer, wat ons ook al besluit het om dit te noem, dit was die eerste gids wat ons geskep het. Wysig app/app.py en voeg die volgende by die URL -patrone

from django.urls import include # aan die bokant

urlpatterns = [
    # ... Vorige kode hier
    path('feed/', include(('feed.urls'), namespace='feed')),
]
As ons die bediener met Python Manage.py Runserver bestuur, sal ons die bladsy sien wat ons geskep het omdat ons die model, aansig en sjabloon sowel as URL -patroon het, saam met items in die databasis. Laat ons nou die vorm wat ons geskep het, implementeer en begin om ons eie poste te skep. Maar voordat ons te veel kode skryf, laat ons 'n rugsteun maak met behulp van die skrif wat ons vroeër geskryf het, rugsteun. Begin hierdie skrif in die dop, wag 'n paar oomblikke, en al die kode word gerugsteun na ons Git -bewaarplek.

backup
Die implementering van die vorm is relatief eenvoudig. Ons sal ons vorm invoer, 'n postversoekhanteerder by die aansig voeg en die pos in die databasis stoor voordat ons na dieselfde aansig herlei word. Ons kan die herlei -funksie wat ons reeds ingevoer het, gebruik, en 'n ander funksie genaamd omgekeerde om die URL vir die uitsigpatroon te kry. Ons sal dit bevraagteken met die string 'voer: voer', want die naamruimte van die ingeslote patroon is voer, en die uitsig word ook voer genoem.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Vra tot dusver al die plasings in die databasis
    if request.method == 'POST': # Hanteer die posversoek
        form = PostForm(request.POST) # Skep 'n voorbeeld van die vorm en stoor die data daarop
        if form.is_valid(): # Valideer die vorm
            form.save() # Stoor die nuwe voorwerp
        return redirect(reverse('feed:feed')) # Herlei na dieselfde URL met 'n GET -versoek
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # Maak seker dat u die vorm in die konteks deurgee sodat ons dit kan lewer.
        'posts': posts,
    })
Nou moet ons die sjabloon opdateer om die nuwe vorm te verantwoord. Ons kan dit doen deur die
Merk in HTML en lewer die vorm in die HTML -sjabloon met 'n Submit -knoppie. Ons sal ook 'n CSRF -teken benodig, 'n teken wat verhoed dat eksterne webwerwe na die vorm plaas sonder om eers 'n bladsy te laai.
 
<!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>
 
Kom ons breek dit af. Daar is 'n nuwe vormklas, 'n teken, die vorm self en 'n indienknoppie. Redelik eenvoudig, maar as ons daarna kyk, wil ons dit beter laat lyk. Dit werk, ons kan nuwe plasings met die vorm plaas en dit word nou in die databasis gestoor. Daar is 'n paar dinge hier aan die gang. Ons gebruik HTML -etikette om te verklaar dat die dokument 'n HTML -dokument is, ons gebruik 'n sjabloonetiket ({ % ... %}) om die teken vir die vorm te lewer, en 'n ander, {{…}} om die vorm te lewer. Ons het ook 'n lus om die teks te lewer met behulp van bloketikette en 'n sjabloonetiket. Bloketikette is baie belangrik, want ons kan definieer hoe gedeeltes van die sjabloon daarmee gelewer word, en sjabloonetikette vorm die basis van hoe ons veranderlikes in ons kode plaas. Nou moet ons ons app beter laat lyk, want dit lyk nou regtig basies. Ons kan dit doen deur CSS te gebruik, hetsy inlyn, of in klasse wat aan elke voorwerp in die dokument gekoppel is. CSS is regtig lekker, want dit vertel alles op die bladsy hoe dit moet lyk,en kan dit regtig goed laat lyk. Daar is 'n paar biblioteke wat dit kan doen, maar my persoonlike Bootstrap is. Bootstrap kan van hul webwerf afgelaai word,Getbootstrap.com/. As u daar is, druk die knoppie om die installasie -dokumente te lees, en kopieer die kode vanaf die CDN -afdeling. U benodig hierdie kode aan die bokant van u HTML -dokument, in 'n etiket genaamd Head. Laat ons ook voortgaan om 'n basisvorm te skep, sodat ons nie hierdie skakels in elke sjabloon hoef te herskep nie. Maak 'n nuwe gids genaamd sjablone met MKDIR -sjablone, en wysig dan sjablone/basis.html. Dit moet so lyk:
 
<!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>
 
Maak seker dat u die CSS en JavaScript, die .css- en .js -lêers, kopieer, want ons het die JavaScript nodig om ons webwerf in die toekoms meer funksioneel te maak. Laat ons nou terugkeer na die bash -dop en 'n vinnige opdrag uitvoer. Onthou, as u ooit toegang tot die virtuele omgewing moet kry, tik die bron Venv/bin/aktiveer. Hiermee kan u Python -pakkette plaaslik installeer op 'n manier waarmee Django toegang tot hulle kan kry. Om ons vorms wat deur Django Bootstrap -klasse gegenereer word, te gee, gebruik ons ​​'n python -pakket genaamd Crispy Forms. Ons kan dit met die volgende opdrag aflaai

pip install django-crispy-forms
Sodra dit geïnstalleer is, voeg dit by die instellings.py

INSTALLED_APPS = [
    # ... Vorige kode hier
    'crispy_forms',
]
Nou, terug in ons voervorm, kan ons 'n paar dinge verwyder. Kom ons verwyder die begin en einde van die dokument en vervang dit met erfenis van ons basisvorm, met behulp van Extss en die blokdefinisie. Ons sal ook 'n sjabloonfilterinvoer met las en 'n sjabloonfilter by die vorm voeg. Laastens, laat ons 'n bootstrap -klas by die knoppie op die vorm voeg om dit meer soos 'n knoppie te laat lyk. Dit moet so lyk:
 
{% 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 %}
 
Pragtig! Dit is al 'n bietjie kode. Vervolgens moet ons dit toets en seker maak dat ons kan sien dat alles mooi lyk, en ook seker wees dat alles behoorlik werk. Begin die bediener volgens vorige instruksies en maak seker dat die webwerf in orde lyk en werk. Goeie werk! U is gereed om oor te gaan na die volgende stap, waarin ons gebruikersaanmeldingsfunksies sal byvoeg met behulp van soortgelyke URL's, vorms, aansigte en sjablone. Die basisvorm is belangrik, en ons sal voortgaan om dit te verander en veranderings aan te bring, maar laat ons nou fokus om ons webwerf veiliger te maak, deur gebruikers in staat te stel om aan te meld met 'n gebruikersnaam en wagwoordkode, en uiteindelik nog belangriker inligting dat Sal help om u app veilig te hou en u eie rekening slegs deur u toeganklik te wees. Om dit te kan doen, moet ons die gebruikersmodel wat in django ingebou is, gebruik. Die gebruikersmodel is 'n databasismodel, soos ons pos, wat weergegee kan word om 'n gebruiker op die webwerf aan te meld. In die toekoms, voordat ons die webwerf op die internet ontplooi, sal ons dit doenBrei hierdie model uit met ander modelle wat daaraan toegeskryf word, en bou bykomende sekuriteitsmaatreëls vir die aanmelding wat bestand is teen phishing. Ons sal begin met die gebruik van 'n paar ingeboude aanmeldvorms wat Django bied. Laat ons eerstens 'n nuwe app skep wat ons sal gebruik om die sjablone en aansigte vir die basiese aanmeldbladsy weer te gee. Ons sal ook ander programme skep om die voortgesette aanmelduitdagings voor te stel om die app te beveilig, insluitend 'n pincode, gesigsherkenning, naby veldkommunikasie, eksterne toestelle, multi -faktor -verifikasie en vingerafdrukherkenning. Ons het al gepraat oor die begin van 'n app. Vanuit ons gids, binne die virtuele omgewing, slaag bestuur.py hierdie

python manage.py startapp users
Nou moet ons 'n gids vir die nuwe app hê. Laat ons begin deur 'n aansig te skep in die gids wat ooreenstem met die aanmelding van die gebruiker. Django het 'n ingeboude siening vir gebruikersaanmeldings, maar dit is nie geskik vir ons nie, want ons het 'n pasgemaakte aansig nodig, wat verkieslik met 'n definisie gedoen word. In hierdie siening sal ons begin met die ondersoek na 'n posversoek, pasversoek. Post na 'n aanmeldvorm wat vanaf Django ingevoer is, die gebruikersrekening verifieer en die gebruiker aanmeld voordat dit na ons Feed -app herlei word. Voeg die volgende kode in gebruikers/views.py by

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'] # Kry die gebruikersnaam en wagwoord vanaf die posversoek
        password = request.POST['password'] # Verifieer die 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 al wat u nodig het vir 'n basiese aanmeldaansig. Laat ons nou 'n vorm vir die aansig skep deur die basisvorm uit te brei. Ons sal begin met die skep van 'n nuwe gids vir sjablone in die gebruikersmap.

mkdir users/templates
mkdir users/templates/users
Nou moet ons gebruikers/sjablone/gebruikers/login.html kan wysig. Terwyl ons daarmee besig is, sal ons 'n sjabloon skep om die gebruiker ook in staat te stel om aan te meld.

nano users/templates/users/login.html
Nou, in die 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 die basiese beginsels van 'n aanmeldvorm. Dit is regtig net soos die ander sjabloon in struktuur, maar dit lyk effens anders as dit weergegee word. Ons kan hierdie kode kopieer om 'n ander soortgelyke sjabloon met die naam Register.html te bou, waar ons die bewoording sal verander en 'n nuwe vorm sal gebruik wat ons bou. Laat ons eers die sjabloon maak. Wysig gebruikers/sjablone/gebruikers/register.html en voeg die volgende kode by:
 
{% 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 %}
 
Laat ons nou 'n vorm vir ons gebruikersregistrasie bou en terugkyk na die aansigte voordat ons ons gebruikersaanmeldings met 'n model opgradeer. Ons sal hierdie vorm basies maak om mee te begin, maar in die toekoms meer besonderhede en sekuriteitsfunksies soos ooreenkomste en CAPTCHA inkorporeer. Wysig die vorms met nano -gebruikers/vorms.py, en voeg die volgende kode by.

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']
Ons het dus 'n ander vorm hier, wat redelik eenvoudig werk. Dit is 'n gebruikersregistervorm met 'n gebruikersnaam, e -pos en wagwoord, sowel as 'n bevestigingswagwoordveld. Let daarop dat hierdie vorm nie die gewone vorm uitgebrei het nie. Vorm klas, dit is 'n modelvorm wat beteken dat dit 'n meta het. Een veld word net so gedefinieer, en die klas Meta definieer die model Die vorm stem ooreen met die res van die inligting wat aan die vorm geskryf sal word. Die meeste hiervan bestaan ​​reeds in Django se ingeboude UserCreationForm, daarom sal ons dit as basis vir die klas gebruik (in die hakies). Vervolgens sal ons die aansig ondersoek om 'n gebruiker te registreer, noudat ons 'n vorm en 'n sjabloon het. Dit is 'n Modelform, net soos die een in die nuwe posbeskouing. Wysig gebruikers/views.py en voeg die volgende kode by:

# ... bedrae
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 al wat ons nodig het om 'n gebruiker te laat geregistreer, maar ons moet meer inligting hê. Ons wil weet die tyd wat die gebruiker geregistreer het, hoe laat dit op die webwerf was, 'n bietjie inligting daaroor, soos 'n biografie, tydsone, ens. model- en attribuutposte aan elke gebruiker. Om dit te kan doen, sal ons die modelle.py in albei programme opdateer. Laat ons begin met die redigering van die voermodel. Dit moet nou so lyk:

from django.db import models # ... invoer
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 hierdie reël by
    text = models.TextField(default='')
Let op die tweede reël wat by die lêer gevoeg is. Dit is 'n vreemde sleutel wat elke pos aan 'n enkele gebruiker per pos sal toeskryf, sodat ons kan sorg dat ons die poste op 'n gebruiker-per-gebruiker-basis stoor en dat geen pos gemaak kan word sonder om dit aan 'n gebruiker toe te skryf nie. Ons definieer hierdie vreemde sleutel met die klas wat dit verteenwoordig, 'n delete -argument om te verseker dat poste met gebruikers, nul en leë argumente geskrap word om seker te maak dat ons die gebruiker kan verwyder indien nodig, en om te akkommodeer vir die gebrek aan 'n gebruiker op poste wat ons reeds kan doen geskep, en 'n verwante naam wat ons kan gebruik om te verwys na die postvoorwerpe wat die gebruiker skep. Hierdie verwante naam, in teenstelling met Post.Author, die skrywer van die pos, gee ons die gebruiker wat die pos self gepos het. Ons kan nou die plasings kry wat 'n gebruiker gemaak het deur user.posts.all () of out author.posts.all () te laat loop. Laat ons nou ons aanmeldings meer veerkragtig maak. Ons kan ons webwerf reeds baie minder kwesbaar maak vir phishing deur bloot die aantal kere te beperk wat ons toelaat om 'n aanmelding by diewebwerf, dit is redelik maklik. Laat ons ook begin om inligting oor elke gebruiker te stoor, terwyl ons voortgaan om ons app te ontwikkel. Redigering van gebruikers/modelle.py, voeg die volgende by

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='')
Let daarop dat hierdie model redelik soortgelyk is aan die POST -model. Ons het 'n addisionele invoer, TimeSone, wat ons in staat sal stel om standaard op die datetime -velde in te stel, en ons het ook 'n karakterfeild en textfield soos die pos. Deur al hierdie tydstempels te gebruik, kan ons die webwerf beveilig en die gebruik daarvan verstaan, en die teksvelde laat ons inligting oor elke gebruiker of outeur op die webwerf lewer. Die OnetOnefield moet die enigste geringe oorweging wees, dit tree presies dieselfde op as 'n voorafgaande, maar slegs een per daaropvolgende model. Op hierdie manier het die gebruiker slegs een profiel, terwyl hulle baie poste het. Laat ons nou ons aanmeld- en registreer -aansigte verbeter om die profiel te verantwoord. Eerstens, wysig gebruikers/views.py en fokus op die registeraansig:

# ... bedrae
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) # Maak seker dat u hierdie reël byvoeg om 'n profiel vir die gebruiker te skep
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Dit skep eenvoudig 'n profiel vir die gebruiker sonder om enige van die inligting in te vul. Nou wil ons seker maak dat die gebruikersrekening nie te gereeld by aangemeld kan word nie, of dat daar ten minste nie te gereeld wagwoorde probeer word nie, so laat ons die aanmeldaansig opdateer.

# ... bedrae
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(): # Let daarop dat ons nou kyk of die gebruiker kan aanmeld
            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: # As die aanmelding nie suksesvol was nie,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Dit is die deel waar ons die gebruikersprofiel opdateer
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Hulle kan dus nie 'n paar sekondes weer aanmeld nie
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Dit is die basiese fundamentele van sekuriteit. Maak seker dat die webwerf nie kwesbaar is vir iemand wat bloot elke moontlike wagwoordkombinasie probeer nie, of selfs 'n paar van hulle terselfdertyd. Dit sal nie frustrerend wees vir die gewone gebruiker wat hul wagwoord ken nie en net 'n paar toestelle aanmeld, maar dit sal talle phishing -robotte uit die app hou. Let daarop dat ons 'n IF -stelling bygevoeg het met 'n veranderlike, can_login, wat in die verlede 'n tyd moet wees, en dit opdateer met elke onsuksesvolle aanmelding met dieselfde gebruikersnaam. Op hierdie manier kan 'n kwaadwillige gebruiker 'n wagwoord nêrens so vinnig raai nie. Die aantal sekondes in die datetime.timedelta () kan ook opgedateer word, en die webwerf is meer veerkragtig, maar tog effens minder bruikbaar met meer sekondes. Ek beveel 15 aan om mee te begin. Onthou, ons het 'n rugsteunskrip gebou om ons werk te red, so laat ons voortgaan met die wat ons tot dusver het om seker te maak dat ons alles stoor. Voer die opdrag uit:

sudo backup
Weereens sal dit u werk tot dusver red. Ek beveel aan dat u gereelde rugsteun doen om u werk te stoor, en u wil selfs outomaties 'n rugsteunwerk doen. U kan dit doen met behulp van 'n UNIX -nut genaamd Cron. Om hierdie nut te aktiveer, voer die volgende opdrag uit en voer u wagwoord in:

sudo crontab -e
As u nog nie opsie 1 vir Nano gekies het nie, moet die teksredakteur u alreeds vertroud wees, en blaai na die onderkant van die lêer met die pyltjie -sleutels. Voeg die volgende reël by:

0 * * * * sudo backup
Cron gebruik die formaat minuut, uur, dag van maand, maand, dag van week, waar 'n * of 'n nommer verteenwoordig wanneer om die opdrag uit te voer. Met behulp van 'n 0 vir die minuut en * vir die res van die opsies, kan ons 'n opdrag op die eerste minuut van elke uur aan die begin van die minuut uitvoer. Dit laat ons die kode outomaties rugsteun. Al Cron se poste as hy met Sudo uitgevoer word, hardloop as wortel, so ons hoef nie elke uur 'n wagwoord in te tik nie. Om dit makliker te maak om ons kode te rugsteun sonder om 'n wagwoord te gebruik, laat ons die wagwoord vir ons rugsteunopdrag deaktiveer. Ons sal dit doen deur die volgende opdrag uit te voer en 'n wagwoord in te voer:

sudo visudo
Laat ons nou na die onderkant van die lêer blaai en 'n ander reël byvoeg:

ALL ALL=NOPASSWD: /bin/backup
Hiermee kan ons die opdrag “rugsteun” as enige gebruiker sonder 'n wagwoord uitvoer. Die formaat hiervoor is maklik, maak net die lyn voor met “All All = Nopasswd:/bin/” en eindig met die opdrag, byvoorbeeld/bin/rugsteun, wat bestaan ​​in/usr/bin/. Laat ons nou met e -pos begin werk. E -pos is baie belangrik vir webwerwe, want dit is 'n manier om 'n webwerf veiliger te hou, te verifieer dat gebruikers regte mense is en selfs produkte of dienste aan kliënte bemark. Baie mense wat die internet gereeld besoek, kyk daagliks na hul e -pos en ontvang allerhande bemarkings -e -pos oor produkte en dienste waarin hulle belangstel. Daar is 'n paar opsies om e -pos op 'n django -webwerf in te stel, en jy is welkom om te kies wat ook al die beste vir u werk. Eerstens kan u betaal vir 'n e -posdiens wat u in staat stel om e -pos vanaf u domein te stuur en minimale kode benodig. Daar is baie dienste wat dit aanbied, soos Google Workspace, SendinBlue, Mailgun en meer. Andersins is u goed besig om te bouU eie e -posdiens binne u bediener van nuuts af. Ek beveel hierdie opsie aan, al is dit meer kode en kan dit spesiale aanbiedings benodig. U kan nie waarskynlik 'n e -posbediener vanaf u tuisrekenaar begin nie, so laat ons die konfigurasie en kode ondersoek om e -pos te stuur voordat ons 'n bediener in die wolk begin en ons eie e -posbediener binne skep. Eerstens, wysig instellings.py met die volgende

nano app/settings.py
Waar die app die naam is van die app wat u met StartApp geskep het. Voeg die volgende reëls by:

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)
Maak seker dat u dit verander as u gereed is om u app te ontplooi. Ons sal dit later weer besoek. Die e -pos_address -instelling moet die e -pos wees waaruit u wil stuur, en die wagwoord (e -pos_host_password) moet ingestel word op die wagwoord wat u vir die bediener genereer. Ek laai die wagwoord in 'n config -lêer om dit uit die kode te hou met behulp van die volgende logika, bo hierdie reëls in instellings.py:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Dan het ek 'n JSON -lêer opgestel met die config in /etc/config.json met behulp van nano soos volg. Om die lêer te wysig:

sudo nano /etc/config.json
Voeg die volgende reëls by:

{
	“EMAIL_HOST_PASSWORD”: “<some password here>”
}
Ons sal voortgaan om die config -lêer te wysig en al die wagwoorde en sleutels wat ons in die app sal gebruik, by te voeg. Laat ons nou vinnig ondersoek hoe om e -pos met Python te stuur. Laat ons eerstens 'n sjabloon skep vir 'n verifikasie -e -pos wat ons aan ons gebruikers kan stuur, en dit in die gebruikersjabloongids kan plaas. Hierdie sjabloon sal in HTML geskryf word.

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>
 
Hierdie e -pos is redelik eenvoudig. Dit neem 'n konteks van 'n gebruiker, die basis -URL vir die webwerf, en 'n gebruikers -ID en teken wat gebruik word om die e -pos van die gebruiker te verifieer. Definieer die basis -URL in instellings.py voordat ons 'n Python -kode skryf om die sjabloon weer te gee. Gaan voort en voeg die volgende reëls by App/Instellings.py, naby die begin.

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

BASE_URL = PROTOCOL + '://' + DOMAIN
Uiteindelik, wanneer u webwerf gereed is vir die internet en u dit ontplooi, sal u u domein wil definieer as die domeinnaam wat u koop om die webwerf te verteenwoordig. Dit is die naam wat u in die Navbar sal tik om toegang tot u webwerf te kry. Vir nou kan u die domein leeg laat of 'n plekhouer gebruik. U sal ook die webwerf van die webwerf wil verander na 'n naam wat u wil gee, van u keuse. Voordat ons e -pos stuur, laat ons 'n token -kragopwekker skep, sodat ons 'n rekeningaktiveringstoken kan hê wat nooit verval nie. Ons kan dit doen deur 'n rekeningaktiveringstoken op te bou en in te voer wat soos die volgende lyk. Wysig die lêer:

nano users/tokens.py
Voeg die volgende kode by:

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()
Hierdie basiese tokengenerator genereer 'n teken dat ons die gebruiker in 'n URL kan stuur en die gebruiker kan gebruik om hul e -pos te verifieer en hul rekening te aktiveer. Kom ons kyk hoe om 'n e -pos te stuur. Gebruik nano, wysig gebruikers/e -pos.py.

nano users/email.py
Die stuur van die verifikasie HTML -e -pos sal so lyk:

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 redelik eenvoudig. Ons voer die funksies in wat ons nodig het om die e -pos te stuur, die e -pos met sjablone en ons instellings te lewer, en dan definieer ons die e -pos met die naam van die sjabloon en stuur dit na die gebruiker met behulp van 'n funksie. U sal sien dat ons nog nie die funksie gedefinieer het om die e -pos, send_html_email te stuur nie, so kom ons skryf dit onder die kode wat ons reeds by gebruikers/e -pos.py gevoeg het

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 'n bietjie meer ingewikkeld, en ons is nog nie gereed om al hierdie kode uit te voer nie. Let op dat ons 'n unsub_link definieer, die skakel wat die gebruiker kan gebruik om uit ons e -pos te teken. Dit is belangrik, want gebruikers sal ons e -posse moet kies, tensy hulle dit te eniger tyd wil sien. Ons voeg ook 'n teksalternatief vir ons boodskap, wat die HTML -boodskap is wat van HTML -etikette gestroop is. Laastens kyk ons ​​of die e -pos gestuur is, en of dit nie so is nie, merk ons ​​die profiel van die gebruiker dat hul e -pos nie geldig is nie. Kom ons gaan terug na die gebruikersmodelle sodat ons dit alles kan laat werk. Ons moet 'n funksie definieer om 'n skakel na uit te teken, en 'n Boole -veld te definieer om te merk dat die e -pos van die gebruiker nie geldig is nie. Voeg eers die volgende invoer aan die bokant van gebruikers/modelle.py

nano users/models.py

# ...
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
Laat ons nou funksies by die gebruikersmodel voeg om die teken te maak en kyk na die teken wat gebruik word om die e -pos te aktiveer, sowel as die veld om te stoor of die gebruiker hul pos suksesvol ontvang. Voeg die volgende kode by gebruikers/modelle.py weer by die einde van die model (ingedrukte kode)

# ...
    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 vir 30 dae
        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 redelik eenvoudig; ons gebruik 'n tydstempel -signer, wat 'n basiese kriptografie -instrument is, om 'n teken te skep wat na 'n sekere tyd sal verval, en ons gebruik ook 'n ander funksie om te kyk of dit geldig is. Ons gebruik hierdie tokens twee keer, een keer om die e -pos te verifieer, en een keer vir 'n skakel wat u nie opskryf nie. Noudat ons dit het, is die laaste van die werk wat ons moet doen, in die sienings. Laat ons kyke na die e -posadres en om uit te teken, binne gebruikers/views.py.

nano users/views.py
Voeg eers die volgende invoer by. Ek het 'n paar ekstra ingegooi, sodat ons nie later weer meer items hoef in te voer nie.

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 # Maak seker dat u die verifikasie -e -pos stuurfunksie invoer
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
Miskien het u al 'n paar van hierdie invoere, maar dit is nie seer om dit te herhaal nie. U sal die verifikasie -e -pos stuurfunksie moet invoer, sowel as Account_Activation_Token van gebruikers.Tokens, onder andere. Voeg die volgende kode aan die onderkant van die lêer by:

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)):
        # teken hulle uit
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    # Andersins herlei na aanmeldbladsy
    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 (versoek, 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 baie kode. Kom ons breek dit af. Die eerste funksie, skoon en eenvoudig, skryf die gebruiker uit die poslys uit. Die tweede funksie aktiveer hul e -pos, en u sal agterkom dat ek 'n kommentaar -funksie bygevoeg het, SendWelMeAmail. U is welkom om 'n e -pos -sjabloon en funksie -definisie te gebruik om 'n welkome e -pos te stuur, ek het nog nie. Die laaste funksie wat ek ingegooi het, is belangrik, want aktiverings -e -posse verval. Daarom sal ons die aktivering van die aktivering sommige van die tyd moet weergee. Ons kan 'n basiese vorm hiervoor gebruik en die funksie noem om die verifikasie -e -pos te stuur. Voordat ons dit doen, laat ons seker maak dat dit in die eerste plek gestuur word deur 'n funksie -oproep by die registeraansig te voeg. Voeg hierdie reël by net voor die herleiding in die Register View, DEF -register, in gebruikers/views.py.

nano users/views.py

# ... (Na) Def Register (versoek):
            send_verification_email(user)
# ... (voor) herlei (
U hoef nie die eerste en laaste reëls in die kode -stuk by te voeg nie, maak net seker dat die registeraansig die verifikasie -e -pos aan die gebruiker stuur. Dit moet so lyk:

# ... bedrae
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) # Maak seker dat u hierdie reël byvoeg!
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Nou sal ons 'n vorm moet byvoeg om die aktiverings -e -pos weer te gee. Voeg die volgende vorm by gebruikers/vorms.py by:

# ... (bedrae)
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)
Ons sal ook 'n sjabloon benodig wat ooreenstem met hierdie resend -e -posaktiveringsvorm. Kom ons voeg hierdie sjabloon in. Wysig die lêer:

nano users/templates/users/resend_activation.html
Voeg dan die volgende kode by die lêer.

{% 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 %}
Whew, dit is baie! As ons die kode na ons bediener ontplooi, sal ons HTML -e -pos kan stuur en gebruikersrekeninge met 'n klik in die e -pos kan aktiveer. Ons wil miskien ook 'n eenvoudige welkome e -pos stuur, so kom ons kyk hoe om dit te doen. Terug in gebruikers/e -pos.py, voeg die volgende kode by:

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)
Ons het ook 'n sjabloon nodig om al hierdie inligting te lewer. Op my webwerf lyk die sjabloon soos hieronder, maar u is welkom om dit te formateer soos u wil.
 
<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>
 
Let daarop dat ons nie 'n sluitingsliggaam of HTML -etikette het nie, want ons voeg dit in wanneer ons die HTML -intekenaar -skakel byvoeg. Dit is belangrik, maar ons wil dit nie twee keer definieer nie. So, wat is volgende? Ons het 'n lang pad gekom. Ons moet regtig gereed wees om die webwerf na 'n bediener te ontplooi. Ons kan die @login_required versierder byvoeg en ons sienings veilig maak, gebruikersaanmeldings neem, e -posadres stuur en inligting oor die kas stuur, wat die basis vorm van wat 'n webwerf moet doen om relevant te bly. Ons sal 'n paar meer nuttige funksies byvoeg, en dan 'n basis bou vir die ontplooiing van ons kode op 'n afstandbediener, die opstel van 'n e -posbediener, domeinkonfigurasie en filters om ons webwerf veilig en toepaslik te maak. Ons het ook 'n wagwoord vir die herstel van die wagwoord nodig, so laat ons dit vinnig vinnig byvoeg. Django se ingeboude wagwoord Reset View is in sommige funksies gebreek, maar ons sal kyk hoe ons ons eie aansig, e -pos -sjabloon, vorms en URL -patrone kan skryf. Hier is hoe die uitsig lyk, in gebruikers/views.py

# ... invoer
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)
Hierdie vorm is ingebou in Django, maar ons het 'n sjabloon nodig om die wagwoord te bevestig, gebruikers/sjablone/gebruikers/wagwoord_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 %}
 
Ons het ook 'n sjabloon om 'n e -pos met 'n eenvoudige vorm, met 'n eenvoudige vorm, in gebruikers/sjablone/gebruikers/wagwoord_reset.html te stuur
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Request Password Reset</button>
            </div>
        </form>
{% endblock content %}
 
Die sjabloon vir die e -pos self is eenvoudig; dit is 'n basiese HTML -lêer wat 'n skakel weergee om die wagwoord terug te stel, in gebruikers/sjablone/gebruikers/wagwoord_reset_email.html. Django sal hierdie lêer outomaties interpreteer.
 
<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>
 
Ons het ook nog twee sjablone nodig. Die eerste is om te bevestig dat die e -pos gestuur is. Uitsigte hiervoor is reeds in Django, so ons moet dit net in die URLS.py aanspreek. Hierdie sjabloon is by gebruikers/sjablone/gebruikers/wagwoord_reset_done.html geleë
 
{% 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 laastens, om te bevestig dat die wagwoord van die wagwoord voltooi is, gebruikers/sjablone/gebruikers/wagwoord_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 %}
 
Nou benodig ons URL -patrone vir hierdie sienings. Voeg die volgende URL -patrone by gebruikers/urls.py by:

urlpatterns = [
    # ... Vorige 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 sjablone, dit is baie! Maar nou kan ons seker wees dat ons die gebruiker se wagwoord kan herstel wanneer ons dit nodig het, alles vanaf die webblaaier. Ek verstaan ​​dat dit baie kode is. As dit 'n bietjie oor jou kop lyk, is dit in orde. U sal verbeter, u begrip sal verbeter, en u sal binnekort baie bekwaam wees met die kode. As u heeltemal verlore is, beveel ek aan dat u later terugkom na hierdie sagteware nadat u aan 'n self-tempo geleer het om kursus aanlyn te kodeer. Dit is gewoonlik gratis om aan die gang te kom, en sal u lei deur alles wat u nodig het om suksesvol te wees as u terugkom na hierdie projek. As u voel dat u gereed is om voort te gaan, verder te lees, sal ons u kode na 'n afgeleë bediener bespreek en 'n e -posbediener opstel, sowel as u implementering met behulp van bash outomatiseer, sodat u altyd 'n nuwe projek kan opstel met 'n paar eenvoudige opdragte. Die laaste ding wat ons moet doen voordat ons na 'n afgeleë bediener ontplooi, is om ons webwerf 'n bietjie veiliger te maak. Jy salLet op dat die aanmeldaansig slegs 'n gebruikersnaam en wagwoord neem, en daar is geen multifaktorverifikasie of eenmalige kode nie. Dit is 'n maklike oplossing, en met dieselfde kode kan ons ons webwerf sms -boodskappe laat stuur en selfs reageer op sms -boodskappe wat na die bediener gestuur word. Om mee te begin, gaan ons terug na die gebruikersmodelle en voeg 'n tydstempel -ondertekenaar by wat elke aanmelding sal voorstel. Ons sal ook 'n unieke, roterende identifiseerder by die gebruikersmodel voeg wat gebruik sal word om ekstra sekuriteit by ons aanmelding te voeg. Die gebruikersmodelle, gebruikers/modelle.py, voeg die volgende by

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# Maak seker dat u die UUID, tydstempel -ondertekenaar en URL -kragopwekker (omgekeer) invoer
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 hierdie kode hier by
    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 hierdie funksie by
    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 vir 3 minute
        except (BadSignature, SignatureExpired):
            return False
        return True
Maak seker dat u gebruikers/modelle.py so lyk, behalwe die opmerkings (kode op die reëls met #). As u dit afbreek, is dit eenvoudig. Ons het 'n paar invoere, 'n tydstempel -siganger, wat 'n kriptografiese nut is wat 'n veilige kode kan genereer en dit kan verifieer om seker te maak dat dit geldig is, slegs een keer gebruik is, en nie ouer as 'n sekere aantal sekondes nie. Ons gebruik ook 'n UUID, wat 'n unieke identifiseerder is wat ons gebruiker identifiseer in die ondertekening van die teken, en in die URL waar die token aan die gebruiker gestuur word. Ons sal hierdie basiese kriptografie gebruik om 'n twee -faktor -verifikasie -aansig te bou. Voordat ons iets anders doen, laat ons die migrasies uitvoer, sodat ons gebruikersmodelle opgedateer word. Voer die volgende opdragte in die gids met bestuur.py om die migrasies te maak en te voltooi.

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Dit is belangrik, want elke keer as ons veranderings aan die modelle aanbring, moet ons die tabelle skep en die databasis met verstekke opdateer voordat ons die modelle kan gebruik. Laat ons nou ons aanmelduitsig improviseer om na 'n sekondêre verifikasie -aansig te herlei. Verwyder die aanmeldfunksie in gebruikers/views.py en herlei na die URL wat ons pas in die gebruikersmodelle gegenereer het.

# ... bedrae

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(): # Let daarop dat ons nou kyk of die gebruiker kan aanmeld
            # Verwyder die autor
            messages.success(request, 'Your password was accepted. Please continue.')
            if user.profile.mfa_enabled:
                return redirect(user.profile.create_auth_url()) # Let daarop dat ons hier na 'n nuwe URL herlei
            else: # As die gebruiker nie multifaktor-verifikasie gebruik nie, meld dit dan aan.
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # As die aanmelding nie suksesvol was nie,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Dit is die deel waar ons die gebruikersprofiel opdateer
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Hulle kan dus nie 'n paar sekondes weer aanmeld nie
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Dit is dus redelik eenvoudig, ons het nou 'n manier om na die twee faktor -verifikasie -aansig te herlei wanneer ons dit skep. Ons het ook 'n terugslag vir die geval dat die gebruiker nie 'n telefoonnommer bygevoeg het nie. Ons sal 'n basiese aansig byvoeg om binnekort 'n telefoonnommer by te voeg en binnekort met 'n SMS aan te meld. Eerstens het ons 'n maklike manier nodig om 'n SMS -boodskap uit ons kode te stuur. Om dit te kan doen, kan ons kies uit 'n aantal API's, maar die maklikste is na my mening Twilio. Dit bied ook goeie pryse vir kleiner projekte, sowel as grootmaatafslag. Skep 'n rekening op Twilio.com, vul 'n paar besonderhede oor u projek in, koop 'n telefoonnommer en kopieer u API -sleutels na u instellings.py. Voeg dan hierdie kode by onder 'n nuwe lêer, gebruikers/sms.py.

nano users/sms.py

# Voer al die nodige pakkette in
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

# Hierdie kode stuur die teks 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())

# 'N Helperfunksie om 'n nommer met soveel syfers te kry
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# Stuur die teks om die gebruiker te verifieer
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 'n gebruiker enige teks met hierdie funksie
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# Valideer die kode met hierdie funksie
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 die tyd
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
Maak seker dat u u instellings toepaslik verander, en voeg hierdie reëls by u sleutels by:

# Sorg dat u dit vanaf u Twilio Dashboard kopieer
TWILIO_ACCOUNT_SID = “<your sid>”
TWILIO_AUTH_TOKEN = “<your token>”
PHONE_NUMBER = “<your twilio phone number>”
SITE_NAME = “<Your site name>”
AUTH_VALID_MINUTES = 3 # Die aantal minute Die TFA -bladsy is aktief sodra dit geïnisieer is
Eerstens sal ons vorms benodig vir ons twee faktore -verifikasie -sienings. Redigering van gebruikers/vorms.py, voeg die volgende kode by.

# ... bedrae
from django import forms

# 'N vorm om ons telefoonnommer in te voer
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

# 'N vorm om te verifieer
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.'
    }
Laat ons nou die aansigte in gebruikers/views.py skep

# ... bedrae
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})
Ons sal ook sjablone benodig vir albei hierdie sienings. Kom ons voeg eers die MFA -sjabloon by.

nano users/templates/users/mfa.html
Voeg hierdie HTML -kode by die 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 redelik vanselfsprekend. Die vorm stuur 'n kode of 'n leë kode, en u sal in die aansig sien dat ons die kode stuur as ons 'n leë kode ontvang. Dan het ons net twee submit -knoppies, en op hierdie manier kan ons die kode met een van die knoppies stuur. Vervolgens voeg ons 'n eenvoudige vorm by om 'n telefoonnommer by te voeg.

nano users/templates/users/mfa_onboarding.html
Voeg die volgende html by:
 
{% 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 %}
 
Hierdie vorm is baie eenvoudiger, dit maak net die telefoonnommervorm wat ons geskep het, en laat die gebruiker 'n telefoonnommer byvoeg. Dit lyk regtig goed! Solank alles behoorlik opgestel is, moet ons boodskappe kan stuur en die gebruiker met hul telefoonnommer kan aanmeld sodra ons die URL -patrone byvoeg. Die laaste ding wat ons moet opstel, is 'n profielaansig, sodat ons kan sorg dat die gebruiker hul telefoonnommer kan verander sonder om aan te meld. Uiteindelik sal ons 'n 'Stop to ophou' -opsie wil byvoeg, sodat die gebruiker kan sms “Stop” om van toekomstige sms -boodskappe te kies. Kom ons voeg 'n profielaansig by die gebruikers/views.py. Hierdie siening sal die bio, e -pos, gebruikersnaam en telefoonnommer van die gebruiker opdateer, en ons kan ook multi -faktore -verifikasie moontlik maak. Eerstens het ons nog twee vorms in gebruikers/vorms nodig.

# ... invoer
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 kan ons 'n siening skep om albei hierdie vorms te gebruik. Wysig gebruikers/views.py en voeg die aansig by.

# Voeg hierdie invoer by
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)
Ons het ook 'n sjabloon vir hierdie siening nodig.

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 %}
 
U sal agterkom dat dit 'n redelike eenvoudige vorm is, maar 'n JavaScript het wat die inhoud van die vorm outomaties plaas soos dit opgedateer word. Dit is nuttig om te hê, sodat u in staat is om wysigings aan te bring sonder om elke keer in te dien. Vervolgens benodig ons URL's wat al hierdie sienings in die gebruikers URL -patters voorstel. Wysig gebruikers/urls.py en voeg hierdie kode by:

# ... vorige kode, invoer
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
# ... URL -patrone wat ons voorheen ingevoer het, voeg die volgende drie reëls by
    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 nou 'n goeie tyd om ons projek te toets. Maar laat ons eers weer 'n rugsteun hardloop.

backup
En bestuur die bediener. Voordat ons na 'n Linux -bediener ontplooi, is dit 'n goeie idee om twee faktore -verifikasie op die rekening moontlik te maak. Ons sal dit doen om na ons profiel -URL,/gebruikers/profiel/te gaan, en die kassie te merk om verifikasie in te skakel nadat ons ons telefoonnommer ingevoer het, en dan die vorm in te dien.

python manage.py runserver localhost:8000
Besoek die webblad deur na u webblaaier te gaan, ek gebruik Google Chrome in hierdie voorbeeld en voer die URL https in: // localhost: 8000/rekeninge/profiel/ U kan indien nodig aanmeld en twee faktore -verifikasie moontlik maak. Hierdie projek het 'n bediener nodig om aan te gaan, sodat dit regtig e -pos kan stuur. Maar eers het ons 'n manier nodig om foute te sien. U sal sien dat as u die bediener in die ontfoutmodus gebruik, met instellings.Debug gelyk aan True, die bediener outomaties foute toon. Om foute te wys sonder om die ontfoutmodus te gebruik, wat onveilig op 'n produksiebediener is, moet ons 'n aansig daarvoor byvoeg. Die belangrikste foute wat ons moet hanteer, is: Fout 500 - 'n Probleem met ons kode Fout 404 - 'n bladsy wat nie gevind is nie (gebreekte URL) Fout 403 - 'n Toestemming geweierde fout Kom ons voeg 'n nuwe app by om hierdie foute, genaamd foute, te hanteer.

python manage.py startapp errors
Voeg dit by die instellings.py soos ons voorheen in die Installed_Apps -instelling gedoen het, en begin deur verwysings na sommige sienings in app/urls.py toe te voeg, waar App die naam van u Django -projek is.

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
Dit is al wat ons nodig het, behalwe foutaansigte, sjablone en 'n bietjie middelware. Kom ons definieer dit so:

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

# Skep u sienings hier.
@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.'})
Laat ons dan die middelware definieer om hierdie foute te hanteer. Ons sal dit doen deur eers by die middelware_klasse in instellings.py te voeg, met die naam van ons middelware.

MIDDLEWARE_CLASSES = [
    # ... Vorige middelware
    'errors.middleware.ExceptionVerboseMiddleware,
]
Laat ons nou die middelware byvoeg.

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.')
Ons voeg 'n funksie by om die huidige uitsondering te kry deur 'n draad van die draad te gebruik, wat ons help om enige foute in ons kode op te spoor. Wat sjablone betref, het ons slegs een nodig, want ons definieer die titel dinamies in die aansig. Die sjabloon moet net die titel en 'spoor', ons foutopsporing vanuit die konteks, weergee.

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
Dit is ons eenvoudigste sjabloon nog, maar dit is hoe maklik dit is om die foute in ons projek te sien. Laat ons nou die ontfout in instellings deaktiveer.

nano app/settings.py
Soek hierdie reël waar dit op waar gestel is, en verander dit na vals

DEBUG = False
Gaan voort en rugsteun nou die app. Ons is gereed om na 'n afgeleë Linux -bediener te ontplooi en hou aan om funksies daarvandaan by te voeg.

sudo backup
Voordat ons hierdie kode op 'n bediener plaas, moet ons oorweeg dat daar probleme met die kode kan wees. Afhangend van die saak, sal webwerwe wat inligting wat aan hulle geplaas is, probleme ondervind met spam wat geplaas word en probleme met die verwydering van die strooipos. Dit behoort nie onmiddellik te gebeur nie, maar as dit gebeur, sal ons later ondersoek hoe om outomaties spam op die webwerf te modereer en dit moeiliker te maak vir robotte om toegang tot die webwerf te kry, tesame met hoe om gebruikersrekeninge te deaktiveer, en die identiteit van 'n gebruiker te verifieer 'n skandering van hul ID of 'n biometriese skandering, soos 'n vingerafdruk of gesigsherkenning. As ons kyk na die voorbeeld van multifaktorverifikasie wat ons in produksie ondersoek het, kan dinge anders wees. Let op hoe ons koersbeperkingsaanmeldings is en tekens verval. As robotte toegang tot 'n webwerf kry, kan twee faktore -verifikasie moeiliker wees, aangesien dit kodes kan invoer op dieselfde tyd as die gebruiker. Laat ons 'n model in die gebruikersmodelle gebruik om dit te bekamp en te verklaar hoe ons met die webwerf omgaanverifieer met behulp van multifaktorverifikasie met 'n telefoonnommer. Ons sal ook 'n opsie byvoeg om met e -pos te verifieer. Begin deur die gebruikersmodelle te redigeer met

nano users/models.py
Dit is hoe die model wat ons byvoeg, moet lyk. Ons het geen metodes nodig nie, net veranderlikes om 'n ID, die gebruiker, die tydstempel, verstryking, lengte en pogings teen enige multifaktorverifikasie te stoor ('n kode soos 123456 wat na 'n telefoon of e -pos gestuur word).

# 'N Basiese teken wat gebruik word om by die webwerf aan te meld
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)
Laat ons ook 'n voorreg by ons gebruiker voeg, en ons sal dit vir nou met die hand stel voordat ons uiteindelik migreer om voorgilegte gebruikers outomaties aan te wend. Voeg hierdie reël in die profiel in die gebruikersmodelle:

    vendor = models.BooleanField(default=False)
Soos met enige veranderinge aan die databasis, moet ons migrasies maak en die databasis migreer wanneer ons 'n modelle.py -lêer in django wysig. Onthou, om dit te doen, gebruik ons ​​eers die bron (as dit nog nie gebruik is sedert die terminale oop was nie) en dan Python Manage.py om die migrasies te maak en te migreer.

cd project-directory-you-named # (indien nodig)
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Voorlopig kan u enige rekeninge wat u as verkopers geskep het, inskakel deur die dop te gebruik.

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
Laat ons nou ons multi -faktor -verifikasie -aansig ontwikkel om hierdie teken te gebruik. Eerstens moet ons ons MFA Helper Utilities verander. Nano te gebruik,

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 die gebruiker met behulp van hul e -pos of telefoonnommer
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() # Filter die teken deur die waarde wat in die URL geslaag is ('n 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)) # Skep dit as hierdie sessie nog nie geskep is nie
    user = User.objects.filter(id=token.user.id).first() # Kry die gebruiker van die token
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # Teken dit aan as hulle reeds geverifieer is
    if not user: raise PermissionDenied() # Ontken as geen gebruiker gevind is nie
    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): # Kyk na die Auth -token
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Meld die gebruiker aan as hulle nie reeds aangemeld is nie
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # Stel 'n verstryking op hul multifaktorverifikasie
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # Herlei die gebruiker na die volgende bladsy
    if not user.profile.mfa_enabled: # Kyk of MFA geaktiveer is
        if not check_verification_time(user, token): # Kyk na die tyd
            user.profile.mfa_enabled = False # Maak die telefoonnommer skoon
            user.profile.enable_two_factor_authentication = True # Aktiveer MFA
            user.profile.phone_number = '+1' # Skakel die telefoonnommer uit
            user.profile.save() # Stoor die profiel
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Teken die gebruiker in as hul MFA nie geaktiveer is nie
            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): # As die versoek 'n posversoek is
        form = TfaForm(request.POST) # Die vorm instel
        code = str(form.data.get('code', None)) # Kry die kode
        if code and code != '' and code != None: # Maak seker dat dit nie leeg is nie
            token_validated = user.profile.check_auth_token(usertoken) # Kyk na die Auth -token
            p = user.profile
            is_verified = check_verification_code(user, token, code) # Gaan die kode na
            p.mfa_authenticated = is_verified
            if token_validated: # As alles
                if is_verified: #  Is in order
                    user.profile.mfa_enabled = True # Aktiveer MFA (indien nie reeds geaktiveer nie)
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Meld die gebruiker aan
                    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(): # Bou 'n navraagstring vir die volgende parameter (indien enige)
                        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) # Herlei
                    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: # As die teken 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: # As daar te veel pogings was
                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 die e -pos (of teks)
                send_mfa_verification_email(user, token)
            else:
                send_verification_text(user, token)
            messages.success(request, "Please enter the code sent to your phone number or email. The code will expire in 3 minutes.")
        elif user.profile.can_send_mfa < timezone.now() + datetime.timedelta(seconds=115):
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    if request.user.is_authenticated: return redirect(reverse('/'))
    # Lewer die vorm (vir GET -versoeke)
    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'})
As ons hierdie kode byvoeg, moet u die funksie invoer om 'n e -pos te stuur. Aan die bokant van die lêer sien die gebruiker (met ander invoer), voeg by

from .mfa import send_verification_email as send_mfa_verification_email
Nou moet ons die funksie skryf voordat enige hiervan sal werk. Dit moet ons stuur -e -posfunksie uitbrei en 'n e -pos aan die gebruiker stuur met die verifikasiekode.

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))
Dit werk dus goed, nou het ons 'n multifaktor -verifikasiestelsel wat 'n telefoonnommer of e -pos afhang om aan te meld. Maar ons het ook 'n manier nodig om gebruikers te verwyder of ten minste weg te steek wat nie met ons voorwaardes saamwerk nie. Dit kan spammers, robotte of iemand wees wat nie goed vir ons werk bedoel nie. Kyk na die siening wat ek het om gebruikers op my webwerf te monitor:

# hoeveelhede
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor # Ons sal hierdie toets moet opstel

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # Kry 'n lys van 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', { # Gebruikers terug in 'n sjabloon
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
Let daarop dat hierdie kode 'n toets gebruik, ons moet hierdie toets in 'n toetse.py -lêer verklaar en dit invoer. Redigering van gebruikers/toetse.py, laat ons die toets skep.

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
Dit is in samewerking met die gebruikers/gebruikers.html -sjabloon, wat so lyk:
 
{% 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 %}
 
Let daarop dat die sjabloon 'n ander sjabloon bevat, gebruikers/_user.html. As u 'n sjabloon met 'n subtemplaat gebruik en nie uitbrei nie, is dit 'n goeie idee om 'n onderstreep (_) by te voeg voordat die naam van die lêer uitbrei, om sjablone te onderskei. Let daarop dat dit baie jinja is, dat u moontlik nie al hierdie veranderlikes gedefinieër het nie. Maar dit is hoe my kode lyk.
 
{% load app_filters %}
<div>
<img src="{{ user.profile.get_image_url }}" alt="@{{ user.profile.name }}'s profile photo" width="120" height="120" align="left" style="margin-top:5px; margin-right:10px; margin-bottom:10px; border-radius: 50%;"/>
    <div class="article-metadata">
      <p class="mr-2">@{{ user.username }} - {{ user.profile.name }} ({{ user.profile.preferred_name }})</p>
      <small class="text-muted">Last seen {{ user.profile.last_seen|date:"F d, Y" }} {{ user.profile.last_seen|time:"H:i" }}</small>
      <small class="text-muted">Joined on {{ user.profile.date_joined|date:"F d, Y" }} {{ user.profile.date_joined|time:"H:i" }}</small>
      <small>{{ user.email }}</small>
      {% if user.profile.phone_number %}<small><i class="bi bi-phone-fill"></i>{{ user.profile.phone_number }}</small>{% endif %}
      {% if user.verifications.last %}
      <small>'{{ user.verifications.last.full_name }}'</small>
      <small><i class="bi bi-123"></i> {{ user.verifications.last.document_number }}</small>
      <small><i class="bi bi-calendar-heart-fill"></i> {{ user.verifications.last.birthdate }}</small>
      <a href="{{ user|document_front }}" class="btn btn-sm btn-outline-primary" title="ID front"><i class="bi bi-person-badge-fill"></i> ID front</a>
      <a href="{{ user|document_back }}" class="btn btn-sm btn-outline-primary" title="ID back"><i class="bi bi-upc-scan"></i> ID back</a>
      {% endif %}
      <small># {{User.id}} </small>
      <small>{% if user.profile.subscribed %}Subscribed{% else %}Not subscribed{% endif %}</small>
    </div>
    {%if not user.is_superuser %}
    <div style="float: right;">{% include 'users/toggle_active.html' %}</div>
    {% endif %}
    {% autoescape off %}    
    <p class="article-content">{{ user.bio }}</p>
    {% endautoescape %}
    <hr>
    <p>{% if user.profile.identity_verified %}Verified user.{% else %}Unverified user.{% endif %} Verifications: {{ user.verifications.count|nts }}</p>
 
Ons het ook nog 'n subtemplaat, woggle_active.html nodig. Hierdie sjabloon moet 'n vorm wees waarmee ons kan skakel of 'n gebruiker aktief 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>
 
Ons sal ook 'n aansig moet byvoeg om gebruikersaktiwiteit en toepaslike URL -patrone te skakel. Laat ons 'n aansig byvoeg om 'n gebruiker te verwyder as ons dit nodig het.

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


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

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

    def test_func(self): # Toets of die gebruiker supergebruiker is en toestemming het om dit uit te vee
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
Alhoewel dit prakties is indien nodig, moet die verwydering van 'n gebruiker die meeste van die tyd nie nodig wees nie, maar ons kan net die sigbaarheid van gebruikers wat die webwerf besoek, skakel as ons dit moet ontslaan. Die URL -patrone wat ons bygevoeg het, lyk so. Met nano, wysig gebruikers/urls.py en voeg hierdie reëls by:

nano users/urls.py
Die reëls moet op die lys van paaie in die gebruikersaansigte gaan, voor die eind “]”, maar na die 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'),
# ...
Maak nou seker dat u die webwerf rugsteun sodat u dit op die webbediener kan aflaai waaraan ons sal voortgaan. Van die opdragreël,

sudo backup
Nou is ons webwerf gerugsteun. Nou het ons 'n paar meer nuttige funksies. Maar wat van die groot prentjie hier? Hierdie kode is nog steeds nie van die internet af beskikbaar nie, ons het nog geen e -posbediener nie, en ons moet ons app uitbrei om 'n uitgebreide verifikasieproses sowel as gladde uitlegte in te sluit om ons te help om die webwerf te verken, saam met veilige protokolle om bevoorregte gebruikers te verifieer . Ons sal dit alles regkry. Die belangrikste ding vir nou is net om hierdie kode aanlyn te kry, wat ons met net 'n paar reëls bash op 'n Ubuntu -bediener kan doen. U moet egter 'n bediener hiervoor huur, tensy u 'n bediener tuis het en 'n internet -intekening op die internet het waarmee u poorte kan oopmaak. Ek het persoonlik my webwerf bestuur op 'n HP Z440 wat in my woonstel geïnstalleer is, maar dit is gewoonlik baie goedkoper vir basiese behoeftes om 'n virtuele private bediener (VPS) te huur. Hou in gedagte dat die kode wat ons nou loop relatief dun is, dit moet onderhou en verbeter word voordat ons dit isGereed om te gebruik wat ons moet bou. Maak seker dat u versigtig is wat u met die internet doen, maak seker dat u hierdie webwerf in die openbaar op die web op 'n Linux -bediener ontplooi, u 'n plan het om ongewenste interaksies met u webwerf te blokkeer. Dit sal waarskynlik aanvanklik nie 'n probleem wees nie, maar ons sal 'n verskeidenheid oplossings ondersoek om dit te bekamp, ​​insluitend masjienleer, kunsmatige intelligensie en rekenaarvisie. As dit 'n probleem word, kyk verder in hierdie teks vir 'n oplossing. Wat 'n VPS huur, is daar baie plekke waarheen u kan gaan. Google Cloud het VPS -bedieners, Ionos, Kamatera, Amazon AWS, en meer verskaffers bied wolkbedienersoplossings aan wat by ons behoeftes pas. U moet deur hul vorms klik en 'n plan kies om aan die gang te kom. U kan met 'n basiese plan saam met enige verskaffer gaan, maar maak seker dat die verskaffer u toelaat om Port Mail Server -poorte oop te maak om e -pos te stuur (dit moet poort 587 en poort 25 wees), sommige verskaffers blokkeer hierdie poorte. Tot dusver het ek dieEST -ervaring met Ionos en Kamatera, albei sal my toelaat om onbeperkte e -pos te stuur en hul pryse is redelik goedkoop. U sal aan u nuwe bediener koppel oor 'n protokol genaamd SSH of Secure Shell, waarmee u op afstand koppelvlak met die bediener kan koppel, presies soos u persoonlike rekenaar, vanaf u persoonlike rekenaar. As u die bediener opstel, sal die gasheerverskaffer u waarskynlik vra om 'n SSH -sleutel by te voeg, of hulle sal u 'n gebruikersnaam en wagwoord gee. Die SSH -sleutel is hoe u vanaf die opdragreël by die bediener sal aanmeld om die kode te wysig. Gebruik die onderstaande SSH-keygen-opsies om 'n SSH te genereer

ssh-keygen
Stoor die lêer en skryf dit oor as u dit nodig het, dit is goed om u SSH -sleutels te draai as u dit nog nie gedoen het nie. Nou kan u die volgende opdrag gebruik om u SSH -sleutel te sien. U wil dit na u afstandbediener kopieer, sodat u dit kan gebruik om te verifieer.

cat ~/.ssh/id_rsa.pub
As u nie 'n SSH-sleutel kon sien wanneer u die opdrag tik nie ('n lang string syfers en letters wat begin met “ssh-rsa aaa”), probeer om 'n RSA-sleutel te genereer (hulle is veiliger, so ek raai aan om dit te gebruik .) Die volgende kode genereer 'n 4096 bit RSA SSH -sleutel.

ssh-keygen -t rsa -b 4096
Skep 'n VPS wat Ubuntu bestuur, maar u beplan om dit te doen. Nadat u 'n VPS geskep het deur deur die vorms op die verskafferswebwerf (Kamatera.com, Ionos.com of soortgelyk) te klik, wil u aanmeld. Om dit te doen, gebruik die SSH -opdrag met u IP -adres (die adres (die adres Dit lyk soos xx.xx.xx.xx). U moet ook sensitief wees vir die standaard -gebruikersnaam op die bediener wat ons geskep het, byvoorbeeld Ubuntu.

ssh ubuntu@XX.XX.XX.XX
U kan gevra word vir 'n wagwoord, as u gevra word vir 'n wagwoord, voer dit in. Ons sal nie die standaardgebruikernaam gebruik nie, so laat ons begin deur 'n nuwe gebruiker te skep en 'n SSH -sleutel by hul rekening te voeg. Laat ons begin deur 'n nuwe SSHD_CONFIG -lêer by te voeg, wat aan die bediener sê hoe om SSH te gebruik.

nano sshd_config

# Dit is die SSHD-bediener-stelselwye konfigurasielêer.  Sien
# SSHD_CONFIG (5) vir meer inligting.

# Hierdie SSHD is saamgestel met pad =/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# Die strategie wat gebruik word vir opsies in die standaard sshd_config wat saam met
# OpenSSH is om opsies met hul standaardwaarde te spesifiseer waar
# moontlik, maar laat hulle kommentaar lewer.  Ongeastemmenteerde opsies oorskry die
# Standaardwaarde.

# Hawe 22
# Adresfamilie enige
# Lysadres 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

# Kodes en keying
# REKEYLIMIT standaard geen

# Aanmelding
# SyslogFacility Auth
# Loglevel -inligting

# Verifikasie:

# LOGRINGRACETIME 2M
# Permitrootlogin Verbod-paswoord
# Strictmodes ja
# Maxauthtries 6
# Maxessions 10

PubkeyAuthentication yes

# Verwag .SSH/gemagtigde_Keys2 sal in die toekoms by verstek nie in ag geneem word nie.
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# Gemagtigde PrincipalSfile Geen

# Gemagtigde keyScommand Geen
# Gemagtigde keyscommanduser niemand

# Om dit te laat werk, benodig u ook gasheerleutels in/etc/ssh/ssh_bekend_hosts
# Gasheergebasettingsverskaffing nr
# Verander na ja as u nie vertrou nie ~/.ssh/geken_hosts vir
# Gasheergebaseerde oormatigheid
# IgnoreUser bekendhosts nee
# Lees nie die gebruiker se ~/.rhosts en ~/.Shosts -lêers nie
# Ignorerhosts ja

# Om Tunnel -duidelike tekswagwoorde te deaktiveer, verander hier na nee!
PasswordAuthentication no
# PermitEmptypasswords no

# Verander na Ja om uitdagings vir uitdagings-respons moontlik te maak (pasop probleme met
# Sommige PAM -modules en drade)
KbdInteractiveAuthentication no

# Kerberos -opsies
# Kerberosauthentication no
# Kerberosorlocalpasswd ja
# Kerberosticketcleanup ja
# KerberosGetAFSToken no

# GSSAPI -opsies
# Gssapiauthentication no
# Gssapicleanupcredentials ja
# Gssapistrictacceptorcheck ja
# GSSAPIKEEXCHANGE NEE

# Stel dit op 'Ja' om PAM -verifikasie, rekeningverwerking moontlik te maak,
# en sessieverwerking. As dit geaktiveer is, sal PAM -verifikasie
# toegelaat word deur die KBD -interaktiewea -verifiëring en
# WagwoordAuthentication.  Afhangende van u PAM -konfigurasie,
# PAM -verifikasie via kbdinteractiveauthentication kan omseil
# die instelling van "Permitrootlogin sonder paswoord".
# As u net wil hê dat die PAM -rekening en sessie -tjeks moet loop sonder
# PAM -verifikasie, stel dit dan in staat, maar stel Passwordauthentication
# en kbdinteractiveauthentication to 'No'.
UsePAM yes

# Laat die voorwaardes toe
# AllowTCPForwarding Ja
# Gatewayports no
X11Forwarding yes
# X11DisplayOffset 10
# X11uselocalhost ja
# Permittty ja
PrintMotd no
# Printlastlog ja
# TCPKEEPALIVE JA
# Permittu -omgewing in
# Kompressie vertraag
# Klientale interval 0
# Clientalivecountmax 3
# Gebruikns in
# Pidfile /run/sshd.pid
# MaxStartups 10: 30: 100
# Pemittunl nee
# Chrootdirectory geen
# Weergawe addendum geen

# Geen standaardbanierpad nie
Banner /etc/banner

# Laat die kliënt toe om plaaslike veranderlikes te slaag
AcceptEnv LANG LC_*

# die standaard van geen substelsels te oorskry nie
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Voorbeeld van die oorheersende instellings op 'n per-gebruiker basis
# Pas gebruiker anoncvs
# X11 Forward No
# ALLE
# Toelatety in
# ForceCommand CVS -bediener
PermitRootLogin no
Onthou, Ctrl+X en Y om die lêer te stoor. Kom ons skryf dan 'n basiese skrif genaamd Initialize (alles in die standaard tuisgids van ons gebruiker).

nano initialize
Voeg hierdie reëls by die lêer en vervang ditMet u SSH -sleutel het u met CAT gevind. (.ssh/id_rsa.pub)

# !
sudo apt install -y nano git openssh-server
sudo cp sshd_config /etc/ssh/sshd_config
sudo service ssh restart
sudo service sshd restart
echo "/root/.ssh/id_rsa" | sudo su root -c "ssh-keygen -t rsa -N ''"
echo "root ssh key:"
sudo su root -c "cat /root/.ssh/id_rsa.pub"
sudo adduser --disabled-password --gecos "" team
sudo passwd -d team
sudo usermod -aG sudo team
echo "/home/team/.ssh/id_rsa" | su team -c "ssh-keygen -t rsa -N ''"
cat /home/team/.ssh/id_rsa.pub >> /home/team/.ssh/authorized_keys
echo '<key here>' >> /home/team/.ssh/authorized_keys
echo "team ssh key:"
cat /home/team/.ssh/id_rsa.pub
Laat ons lyn vir lyn begin om u deur hierdie lêer te lei. Die eerste reël sê vir die samesteller dat dit 'n bash -skrif is. Dan installeer ons afhanklikhede, kopieer SSHD_CONFIG na die regte gids, begin SSH weer, genereer SSH -sleutels vir Root, voeg die gebruiker 'Team' by (u kan 'n naam kies waarvoor u hiervoor wil gebruik, gebruik die adduser -opdrag met hul naam en gestremde wagwoord vir nou). Ons voeg ook span by die Sudo -groep, genereer hul SSH -sleutel, voeg ons sleutel by tot gemagtigde sleutels en hulle s'n, en druk hul sleutel. Hierdie nuwe gebruiker is hoe ons by die webwerf aanmeld. Gaan voort in 'n nuwe terminale en maak die bediener weer oop.

ssh team@XX.XX.XX.XX
U moet hierdie keer nie 'n wagwoord nodig hê nie, omdat u 'n SSH -sleutel het. Ons het ook die aanmelding met 'n wagwoord gedeaktiveer om die webwerf veiliger te hou. Nou begin hierdie bediener heeltemal leeg met geen inligting daaroor nie. Laat ons begin met die kloning van ons projek van Git, sodat ons dit op die afgeleë masjien kan aflaai en uitvoer. Druk eers u SSH -sleutel op die afgeleë bediener wat oor SSH gekoppel is:

cat ~/.ssh/id_rsa.pub
Plak dan hierdie sleutel in die Git -instellings soos ons voorheen gedoen het om ons Git -bewaarplek op te stel. Ons kan nou ons projek direk na die bediener kloon. Maak seker dat u eers die projek plaaslik gerugsteun het, sodat dit op die Git -bediener is om af te laai.

git clone git://github.com/you/yourproject.git
Perfek. Nou is al die lêers hier. Ons kan hulle met LS sien

ls
Laat ons nou begin om die bediener op te stel. Kopieer eers u projekgids in 'n eenvoudige, onvergeetlike naam wat ons vir die projek sal gebruik.

cp -r yourproject whatyoucalledit
Waar “What YouCalledit” die nuwe naam van u projek is. Vervolgens moet ons 'n basiese nut opbou om die bediener op te stel. Ons sal hierdie nut stoor en dit in die toekoms gebruik. Om hierdie nut op te bou, laat ons 'n gebruiker binêre skep om te definieer hoe ons 'n skrip wysig. Gebruik bash, wysig/usr/bin/ascript

sudo nano /usr/bin/ascript
Maak seker dat u Sudo daar gebruik, sodat u toestemmings het om die lêer te wysig. Voeg hierdie reëls in die lêer by:

# !
if [ ! -f /usr/bin/$1 ]; then
    sudo touch /usr/bin/$1
    echo "# !
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
    echo $1 | sudo tee -a /etc/ascripts
else
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
fi
Onthou dat hierdie skrif 'n argument, die skrifnaam, as $ 1 neem. Eerstens kyk dit of die lêer bestaan, of andersins skep, voeg die eerste reël by om die skrif te verklaar, is bash, verander sy toestemmings, wysig dit en voeg die naam by /etc /ascripts waarmee ons die name van die skrifte wat ons stoor, stoor skep. As die lêer reeds bestaan, verander dan die toestemmings en wysig dit. Stoor die lêer, en daarna sal ons die toestemmings verander. Solank ons ​​hierdie skrif gebruik, hoef ons dit nie weer te doen nie.

sudo chmod a+x /usr/bin/ascript
Perfek. Laat ons nou 'n skrif met die naam Setup skep. Eerstens, om jou nie te oorweldig nie, maar kyk hoe my opstellingsskrif lyk. Ons sal deurloop hoe hierdie skrif in u projek moet lyk, u het nie alles in my skrif nodig om mee te begin nie.

# !
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
# Sudo Chmod A+X Scripts/UserSetup
# ./scripts/usersetup
# Ssh-keyen
# Projekgids
DIR="/home/team/femmebabe"
USER="team"
# Log opdragte
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# Nano config
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git 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
# Opdatering en installeer
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
# Aktiveer clamav antivirus
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Stel gasheernaam in
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Stel post -post -grense op
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;"
# Stel rugsteundatabasis op
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
# Gestremde 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
# Stel postfix op
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
# Skep 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
# Stel virtueurenv op
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# Kry en bou afhanklikhede
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 -reëls op
cd $DIR
# Installeer PYPI -afhanklikhede
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 Installeer 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
# Run certbot
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# Herlaai posbediener
sudo systemctl restart opendkim postfix dovecot
# Kopiesertserts
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privkey.pem
# sudo cp /etc/lettesencrypt/live/femmebabe.com/cert.pem cert.pem
# Lap
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 gebruikersinstellings in
sudo gpasswd -a www-data users
# Stel toestemmings in
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# Sudo Chown -R -span: gebruikers/var/run/
# sudo chown wortel: wortel/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 konfigurasies en stel toestemmings 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
# Databasisopstelling
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"
# Spuit PAM -konfigurasie en verwyder foutiewe SSH -konfigurasie
# 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 -skrifte en stel toestemmings 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
# Herlaai en dienste in staat stel
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
# Aktiveer Apache -modules
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
# Deaktiveer standaardwebwerf
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# Aktiveer vir die webwerf
sudo a2ensite femmebabe-le-ssl
# Herlaai Daemon en herbegin Apache, Postfix en Opendkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# Stel toestemmings in
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# Ruilkonfigurasie
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 -onderskrifmotor
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
# Stel git op
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 vir domeinkonfigurasie
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}'
# Opstel voltooi
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."
Dit is baie opgestel! Kortom, hierdie kode logs opdragte, stel nano en git, kopieë oor lêers, downloads en installeer ubuntu -aptasies, python -afhanklikhede, stel postfix in, stel postgreSQL (die databasisbediener) op en laai die databasis, konfigureer UFW ('n ongekompliseerde firewall), Deaktiveer iptables, laai 'n antivirus af, maak kaarte, klone Afhankings, installeer sertifikate en stel die bediener op, installeer konfigurasie, begin en stel die Sever, ken ruil toe, stel toestemmings in, en druk die IP, IPv6 -adres en Opendkim -sleutel uit. Redelik eenvoudig, maar dit lyk soos baie kode. Ons sal nie baie hiervan nodig hê nie, want ons het nie die afhanklikhede nie, ons gebruik nie seldery, CeleryBeat of Daphne nie, maar ons sal in elk geval sommige daarvan installeer om aan die gang te kom. Let op dat hierdie kode 'n domein verskeie kere verklaar het. Ons sal ook 'n domeinnaam moet koop (wat 'n klein jaarlikse fooi is). Ek beveel Squarespace aan vir die aankoop van 'n domein, hul uitleg isintuïtief en maklik om te gebruik. U kan enige domein van u keuse koop, maar ek gebruik die domein femmebabe.com in hierdie voorbeeld. Nadat u 'n domein gekoop het, gaan na die Squarespace DNS -konfigurasiepaneel en voeg 'n rekord by wat u domein met die IP -adres op die bediener wys. Dit moet so lyk: @ A xx.xx.xx.xx Met die @ -operateur as gasheer, wat beteken dat alle subdomeine onder hierdie domein en die worteldomein almal na die bediener herlei word. Daar is meer rekords om te verklaar, maar ons kan hierna oorgaan sodra ons gereed is om e -pos te stuur. Hou in gedagte, dit kan 'n paar dae duur voordat u e -pos van die bediener kan stuur. Die DNS -rekords wat ons stel, sal tyd neem om te versprei. Hoe dit ook al sy, die enigste rekord wat ons moet begin, is 'n rekord. Nou kan ons die onderstaande skrif volgens ons projek invul en dit uitvoer. Laat ons begin met 'n kleiner opstellingsskrip om net te installeer wat ons nodig het vir 'n basiese vordering. Ons sal nog nie soveel afhanklikhede of PostgreSQL gebruik nie, ons sal netOp 'n basiese HTTP -bediener en bekommerd wees om dit te sertifiseer wanneer dit gedoen is. Onthou, om 'n HTTPS -sertifikaat te kry en die bediener veilig uit te voer, moet ons 'n domein koop saam met die huur van 'n bediener. Vervang nou vir nou 'Team' in hierdie lêer met die naam van u gebruiker, 'DIR' met die gids van u projek, en voorsien u e -pos en domein in die <> tags. Voordat ons hierdie kode uitvoer, moet ons die instellings verander na die firewall wat die gasheerverskaffer ondersteun, indien enige. Gewoonlik is dit in die 'Networks' -oortjie van u gasheerverskaffer, of as u self aanbied, is dit in die' Port Forward' -gedeelte van u router. U wil ook 'n statiese IP via u router opstel met die adres van u bedienermasjien, as u selfhosting gebruik. U moet die volgende poorte oopmaak vir lees-/skryftoegang. 22 (SSH) 25 (pos) 587 (pos) 110 (Poskliënt) 80 (http) 443

# !
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
# Log opdragte
echo "Logging commands"
sudo cp log/commands.log /var/log/commands.log
sudo chmod -R a+w /var/log
sudo chown -R :syslog /var/log
echo $'alias venv="source /home/team/femmebabe/venv/bin/activate"' | sudo tee -a /home/team/.profile
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /etc/bashrc
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a "/home/team/.bashrc"
echo $'PROMPT_COMMAND=\'RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" )"\'' | sudo tee -a /root/.bashrc
echo "source /etc/bashrc" | sudo tee -a /home/team/.profile
echo "/var/log/commands.log" | sudo tee -a /etc/logrotate.d/syslog
echo "local6.*    /var/log/commands.log" | sudo tee -a "/etc/rsyslog.d/bash.conf"
sudo service rsyslog restart
# Nano config
echo "set tabsize 4" >> .nanorc
echo "set tabstospaces" >> .nanorc
# Git 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
# Opdatering en installeer
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
# Aktiveer clamav antivirus
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Stel gasheernaam in
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
# Stel rugsteundatabasis op
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
# Gestremde 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
# Stel virtueurenv op
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
# Run certbot
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# Stel gebruikersinstellings in
sudo gpasswd -a www-data users
# Stel toestemmings in
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# Sudo Chown -R -span: gebruikers/var/run/
# sudo chown wortel: wortel/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 ./
# Herlaai en dienste in staat stel
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Aktiveer Apache -modules
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
# Herlaai Daemon en herbegin Apache, Postfix en Opendkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# Toon IPv6 en Opendkim vir domeinkonfigurasie
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
Voordat u hierdie kode uitvoer, moet u seker maak dat die domein wat u gekoop het, aan die bediener gekoppel is. Om dit te kan doen, maak 'n terminale op u plaaslike masjien oop en voer hierdie opdrag met u domein uit:

ping femmebabe.com # Voeg u domein hier in, na ping
As alles goed lyk en die bediener antwoorde stuur, is ons gereed om die skrip uit te voer en pakkette te installeer, sowel as om ons Apache -bediener in te skakel, in staat te stel. Dit is nie al die opstelling wat nodig is om Postfix te konfigureer nie; ons sal later meer na die opstelling kyk. Begin nou hierdie opstellingskode en dit moet 'n paar minute neem om u bediener te installeer en te sertifiseer. Maak weereens seker dat u naam, e -pos en domeinnaam in die skrip vervang volgens die naam wat u gekoop het. Noudat die bediener voorsien word, kan u na die URL in enige webblaaier gaan en kyk of die bediener HTTPS gebruik. As dit nie so is nie, probeer dan om 'n rukkie te wag vir die DNS -rekords om in te haal en voer dan die volgende opdrag uit om CertBot -sertifisering weer te gee:

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
Solank u alles reg gekonfigureer het, moet u toegang tot Apache se standaardbladsy kan kry net om te weet dat u kode werk en 'n regstreekse webblad vertoon. Laat ons dan die instellings.py wysig om ons standaard -ontfoutmodus na produksie te verander. Ons sal ook die domein in die instellings, sowel as interne IP's, opstel.

nano yourproject/settings.py
Verander/voeg hierdie lyne in die instellings.

DEBUG = False

# Werfkonfig
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',
]
Nou sal ons Apache2 moet opstel. Kom ons wysig die config -lêer wat ons met hierdie reël sal ontplooi:

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
Hierdie config -lêer moet ons domeinnaam daarin hê, en die naam van die gebruiker en projek. Ek gebruik die domeinnaam femmebabe.com, die gebruikersnaamspan en die projeknaam 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>
Sorg dat u die naam van die projek, kaarte en domein in hierdie voorbeeldkode vervang wanneer u u bediener opstel. Nou moet ons die standaardwebwerf deaktiveer. Dit kan gedoen word met Bash.

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
Vervolgens kan ons die standaardwebwerf in staat stel en Apache2 herlaai, ook met Bash. Onthou om femmebabe te vervang met die naam van die lêer wat u verklaar het tydens die redigering van/etc/apache2/webwerwe-beskikbaar/.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Gaan terug na u domein in die Navbar. U moet die webwerf sien wat u in u webblaaier gekonfigureer het. Baie geluk! As u dit nie sien nie, moet u dalk 'n paar veranderinge aanbring. Lees die instellings in u projek, Apache -konfigurasie, noukeurig, en maak seker dat u geen foute het nie, en voer die volgende opdragte uit om die projek vir foute na te gaan.

cd projectname
source venv/bin/activate
python manage.py check
As u foute in u Python -projek het, moet u dit opspoor na waar hulle is en regmaak. U kan dalk nie al u foute sien nie, afhangende van waar hulle is, so as u 'n fout het wat sê: "Populate is nie herintrant nie", wysig die volgende lêer in die virtuele omgewing, register.py, om die blootstelling te ontbloot fout.

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Blaai na reël 83, waar hierdie runtime -fout geopper word (Raise RuntimeError (“Populate () is nie weer herintrant nie”)), en voeg 'n opmerking voor hierdie reël by, en voeg dan met dieselfde inkeping by, self.app_configs = {}. Dit lyk so:

            if self.loading:
                # Voorkom reentrantoproepe om te verhoed dat AppConfig.ready ()
                # metodes twee keer.
# Raise RuntimeError ("Populate () is nie herintrant nie")
                self.app_configs = {}
            self.loading = True
U kan dan weer die projek nagaan en die fout blootstel.

python manage.py check
Dan kan u die fout sien en dit regstel. As u dit regstel en die kode sonder foute saamstel, moet u die lêer terug verander, sodat dit so lyk:

            if self.loading:
                # Voorkom reentrantoproepe om te verhoed dat AppConfig.ready ()
                # metodes twee keer.
                raise RuntimeError("populate() isn't reentrant")
# self.app_configs = {}
            self.loading = True
Mits die bediener aanlyn is, moet ons die volgende opdrag gebruik om die bediener te herlaai as ons verdere veranderinge daaraan aanbring:

sudo systemctl reload apache2
Awesome! Maar wat van die stuur van e -pos? Om e -pos te stuur, moet ons eers die domeinkonfigurasie opdateer. Dit moet in u DNS -paneel in Squarespace wees, of watter domeinnaamregistrateur u ook al gekies het. Ons sal ook konfigurasie moet installeer en byvoeg en 'n paar opdragte uitvoer. Laat ons eers die IPv6 -adres van die bediener kry. Ons sal dan u DNS oopmaak en die rekords byvoeg. Gebruik hierdie opdrag om die IPv6 -adres van die bediener te kry:

ip -6 addr
Nou kan ons die volgende rekords by die DNS -instellings voeg. My rekords lyk so. Vir u rekords moet u egter die IP -adres met u IP vervang (nie 75.147.182.214, dit is myne). Voeg ook u domein in die plek van femmebabe.com, sowel as u IPv6 -adres wat met die vorige opdrag gevind is (u kan nie myne gebruik nie, Fe80 :: 725A: FFF: FE49: 3E02). Moenie bekommerd wees oor die Domainkey vir nou nie, dit word geskep wanneer ons Postfix, die e -posbediener, met OpenDkim opstel en die sleutel druk. Ons sal dit laaste opstel. @ N N/A 75.147.182.214 @ MX 10 femmebabe.com @ Ptr N/A femmebabe.com @ Txt N/A TXT @ V = SPF1 MX IP75.147.182.214IP6: FE80 :: 725A: FFF: FE49: 3E02 ~ ALL DEFAULT._BIMI Txt N/A v = bimi1; l = https: //femmebabe.com/media/static/femmebabe.svg _dmarc Txt N/A v = dmarc1; P = Geen sendonly._domainkey Txt N/ANou moet ons 'n paar volgehoue ​​konfigurasie vir postfix byvoeg. Al wat ons hoef te doen is om seker te maak dat ons die domeinnaam, femmebabe.com, vervang met die domeinnaam wat u gebruik. Kom ons kyk na al die config -lêers een vir een en installeer dit in 'n gids genaamd Config in ons projek, om op die bedryfstelsel te installeer.

nano config/etc_postfix_main.cf
Voeg hierdie teks by die lêer

# Kyk /usr/share/postfix/main.cf.dist vir 'n kommentaar, meer volledige weergawe


# Debian -spesifiek: Spesifisering van 'n lêernaam sal die eerste veroorsaak
# reël van die lêer wat as die naam gebruik moet word.  Die Debian standaard
# is /etc /e -posnaam.
# Myorigine = /etc /e -posnaam

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

# bykomende .domein is die werk van die MUA.
append_dot_mydomain = no

# Die volgende reël om 'n vertraagde pos 'waarskuwings te genereer
# vertraging_warning_time = 4h

readme_directory = no

# Kyk http://www.postfix.org/compatibility_readme.html - standaard tot 3.6 op
# vars installasies.
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 konfigurasie
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 konfigurasie!

nano config/etc_postfix_master.cf
Voeg hierdie lyne by:

# 
# Postfix Master Process Configuration File.  Vir meer inligting oor die formaat
# van die lêer, sien die Master (5) Handleiding Bladsy (Opdrag: "Man 5 Master" of
# On-line: http://www.postfix.org/master.5.html).
# 
# Moenie vergeet om "Postfix Reload" uit te voer nadat u hierdie lêer geredigeer het nie.
# 
# ======================================================================= ==========================
# Dienstipe Privaat Unpriv Chroot Wakeup MaxProc Command + Args
# (ja) (ja) (nee) (nooit) (100)
# ======================================================================= ==========================
smtp      inet  n       -       y       -       -       smtpd
# SMTP Inet N - Y - 1 Postcreen
# SMTPD PASS - - Y - - SMTPD
# Dnsblog unix - - y - 0 dnsblog
# TLPROXY UNIX - - Y - 0 TLPROXY
# Kies een: Aktiveer indiening slegs vir Loopback -kliënte, of vir enige kliënt.
# 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/indiening
# -o smtpd_tls_security_level = Encrypt
# -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_RESTRICTS
# -o SMTPD_SENDER_RESTRICTS = $ MUA_SENDER_RESTRICTS
# -o smtpd_recipient_trival =
# -o smtpd_relay_restrictions = permit_sasl_authenticated, verwerp
# -O milter_macro_daemon_name = oorsprong
# Kies een: Aktiveer SMTP's slegs vir Loopback -kliënte, of vir enige kliënt.
# 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_RESTRICTS
# -o SMTPD_SENDER_RESTRICTS = $ MUA_SENDER_RESTRICTS
# -o smtpd_recipient_trival =
# -o smtpd_relay_restrictions = permit_sasl_authenticated, verwerp
# -O milter_macro_daemon_name = oorsprong
# 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
# 
# ======================================================================= ===================
# Koppelvlakke na nie-postfix-sagteware. Ondersoek die handleiding
# Bladsye van die nie-postfix-sagteware om uit te vind watter opsies hy wil hê.
# 
# Baie van die volgende dienste gebruik die postfix -pyp (8) aflewering
# agent.  Raadpleeg die pyp (8) vroublad vir inligting oor $ {ontvanger}
# en ander opsies vir die koevert van boodskappe.
# ======================================================================= ===================
# 
# MailDrop. Raadpleeg die Postfix MailDrop_Readme -lêer vir meer inligting.
# Spesifiseer ook in main.cf: MailDrop_Destination_Recipient_limit = 1
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# ======================================================================= ===================
# 
# Onlangse Cyrus -weergawes kan die bestaande "LMTP" Master.cf -inskrywing gebruik.
# 
# Spesifiseer in cyrus.conf:
# lmtp cmd = "lmtpd -a" luister = "localhost: lmtp" proto = tcp4
# 
# Spesifiseer in Main.cf een of meer van die volgende:
# mailbox_transport = lmtp: inet: localhost
# Virtuele_transport = lmtp: inet: localhost
# 
# ======================================================================= ===================
# 
# Cyrus 2.1.5 (Amos Gouaux)
# Spesifiseer ook in main.cf: cyrus_destination_recipient_limit = 1
# 
# Cyrus unix - n n - - pyp
# vlae = drx gebruiker = cyrus arg =/cyrus/bin/aflewer -e -r $ {sender} -m $ {uitbreiding} $ {gebruiker}
# 
# ======================================================================= ===================
# Ou voorbeeld van aflewering via Cyrus.
# 
# Ou -cyrus unix - n n - - pyp
# vlae = r gebruiker = cyrus argv =/cyrus/bin/aflewer -e -m $ {uitbreiding} $ {gebruiker}
# 
# ======================================================================= ===================
# 
# Raadpleeg die postfix uucp_readme -lêer vir konfigurasiebesonderhede.
# 
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# 
# Ander eksterne afleweringsmetodes.
# 
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 die Opendkim -konfigurasie. Opendkim identifiseer e -posbedieners met domeinksleutels om hulle veiliger te maak. Daarsonder is e -pos nie onderteken nie en kom dit miskien nie na 'n inkassie nie.

nano config/etc_default_opendkim
Voeg hierdie lyne by:

# Opmerking: dit is 'n nalatenskapskonfigurasielêer. Dit word nie deur die Opendkim gebruik nie
# SystemD -diens. Gebruik die ooreenstemmende konfigurasieparameters in
# /etc/opendkim.conf in plaas daarvan.
# 
# Voorheen sou 'n mens die standaardinstellings hier wysig en dan uitvoer
# /lib/opendkim/opendkim.service.
# /etc/systemd/system/opendkim.service.d/override.conf en
# /etc/tmpfiles.d/opendkim.conf. Alhoewel dit nog moontlik is, is dit nou
# Aanbeveel om die instellings direk aan te pas in /etc/opendkim.conf.
# 
# Daemon_opts = ""
# Verander na/var/spoel/postfix/run/opendkim om 'n unix -sok met
# Postfix in 'n chroot:
# Rundir =/was/spoel/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Onkomment om 'n alternatiewe sok te spesifiseer
# Let daarop dat die instelling daarvan enige sokwaarde in OpenDkim.conf sal ignoreer
# verstek:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Luister op alle koppelvlakke op poort 54321:
# Sok = inet: 54321
# Luister op Loopback op poort 12345:
# Sok = inet: 12345@localhost
# Luister is 192.0.2.1 is poort 12345:
# Sok = 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 hierdie lyne by:

0-master.conf 
# DEFAULT_PROCESS_LIMIT = 100
# DEFAULT_CLIENT_LIMIT = 1000

# Standaard VSZ (virtuele geheue -grootte) limiet vir diensprosesse. Dit is hoofsaaklik
# bedoel om prosesse te vang en dood te maak wat die geheue lek voordat hulle eet
# alles.
# DEFAULT_VSZ_LIMIT = 256M

# Aanmeldingsgebruikers word intern gebruik deur aanmeldprosesse. Dit is die mees onbetroubaarste
# Gebruiker in Dovecot -stelsel. Dit moet glad nie toegang tot iets hê nie.
# DEFAULTE_LOGIN_USER = DOEVOUDL

# Interne gebruiker word deur onbevoorregte prosesse gebruik. Dit moet apart van
# Aanmeldingsgebruiker, sodat aanmeldprosesse nie ander prosesse kan steur nie.
# DEFAULT_INTERNAL_USER = DOVECOT

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

  # Aantal verbindings om te hanteer voordat u met 'n nuwe proses begin. Tipies
  # Die enigste nuttige waardes is 0 (onbeperk) of 1. 1 is veiliger, maar 0
  # is vinniger. <doc/wiki/loginprocess.txt>
  # service_count = 1

  # Aantal prosesse om altyd te wag vir meer verbindings.
  # Proses_min_avail = 0

  # As u Service_Count = 0 stel, moet u dit waarskynlik laat groei.
  # vsz_limit = $ 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
  }

  # Skep slegs 'n luisteraar as u die bogenoemde Unix -aansluiting nie kan gebruik nie
  # inet_lister lmtp {
    # Vermy LMTP sigbaar vir die hele internet
    # Adres =
    # poort =
  # }
}

service imap {
  # Die meeste van die geheue gaan na mmap () lêers. Miskien moet u dit verhoog
  # Beperk as u groot posbusse het.
  # vsz_limit = $ default_vsz_limit

  # Maks. Aantal IMAP -prosesse (verbindings)
  # Proses_limit = 1024
}

service pop3 {
  # Maks. Aantal POP3 -prosesse (verbindings)
  # proses_limit = 1024
}

service submission {
  # Maks. Aantal SMTP -indieningsprosesse (verbindings)
  # Proses_limit = 1024
}

service auth {
  # Auth_socket_path wys standaard na hierdie userDB -aansluiting. Dit is tipies
  # gebruik deur Dovecot-Lda, Doveadm, moontlik IMAP-proses, ens.
  # Volledige toestemmings vir hierdie sok kan 'n lys kry van alle gebruikersname en
  # Kry die resultate van almal se USERDB -op soek.
  # 
  # Die standaard 0666 -modus stel iemand in staat om aan die sok te koppel, maar die
  # UserDB Soeke sal slegs slaag as die USERDB 'n "UID" -veld teruggee
  # Pas die UID van die oproeperproses. Ook as die UID of GID van die beller ooreenstem met die
  # SOCKET se UID of GID Die opsoek slaag. Enigiets anders veroorsaak 'n mislukking.
  # 
  # Stel die modus op om die oproeper volle toestemmings te gee om alle gebruikers op te soek
  # iets anders as 0666 en Dovecot laat die kern die
  # Toestemmings (bv. 0777 laat almal volle toestemmings toe).
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # Auth -werkersproses word standaard as wortel uitgevoer, sodat dit toegang kan kry
  # /etc/skaduwee. As dit nie nodig is nie, moet die gebruiker verander word na
  # $ DEFAULT_INTERAL_USER.
  # user = root
}

service dict {
  # As DICT -instaanbediener gebruik word, moet e -posprosesse toegang tot die sok hê.
  # Byvoorbeeld: modus = 0660, groep = Vmail en Global Mail_access_Groups = Vmail
  unix_listener dict {
    # Modus = 0600
    # Gebruiker =
    # groep =
  }
}
Maak weereens seker dat u die domein in al hierdie lêers, femmebabe.com, vervang met die domein wat u gekies het. Wysig die volgende lêer, Dovecot's Config,

nano config/etc_dovecot_dovecot
En voeg hierdie lyne by

## Ovecot -konfigurasielêer

# As u haastig is, sien http://wiki2.dovecot.org/quickconfiguration

# "Doveconf -N" -opdrag gee 'n skoon uitset van die veranderde instellings. Gebruik dit
# In plaas daarvan om lêers te kopieer en te plak wanneer u na die Dovecot -poslys gepos word.

# '# 'Karakter en alles nadat dit as opmerkings behandel word. Ekstra ruimtes
# en oortjies word geïgnoreer. As u een van hierdie eksplisiete wil gebruik, plaas die
# value inside quotes, eg.: key = "# char en agterruimte "

# Die meeste (maar nie alle) instellings kan deur verskillende protokolle en/of
# Bron/bestemming IPS deur die instellings binne gedeeltes te plaas, byvoorbeeld:
# Protokol imap {}, plaaslik 127.0.0.1 {}, afstand 10.0.0.0/8 {}

# Standaardwaardes word vir elke instelling getoon, dit is nie nodig om te kom nie
# daai. Dit is egter uitsonderings hierop: geen afdelings nie (bv. Naamruimte {})
# Of instellings word standaard bygevoeg, dit word slegs as voorbeelde gelys.
# Paaie is ook net voorbeelde met die regte standaard wat gebaseer is op Configure
# opsies. Die paaie wat hier gelys word, is vir Configure --Prefix =/USR
# --sysconfdir =/etc--localstatedir =/var

# Aktiveer geïnstalleerde protokolle
!include_try /usr/share/dovecot/protocols.d/*.protocol

# 'N Komma -geskeide lys van IP's of gashere waar u moet luister na verbindings.
# "*" Luister in alle IPv4 -koppelvlakke, "::" Luister in alle IPv6 -koppelvlakke.
# As u nie-default-poorte of iets meer ingewikkeld wil spesifiseer,
# wysig conf.d/master.conf.
# Luister = *, ::

# Basisgids Waar om runtime -data te stoor.
# base_dir =/var/run/dovecot/

# Naam van hierdie instansie. In multi-instansie-opstelling Doveadm en ander opdragte
# kan -i <instance_name> gebruik om te kies watter instansie gebruik word ('n alternatief
# na -c <config_path>). Die naam van die instansie word ook by Dovecot -prosesse gevoeg
# in PS -uitset.
# instansie_name = Dovecot

# Groetboodskap vir kliënte.
# login_greeting = Dovecot gereed.

# Ruimte -geskeide lys van betroubare netwerkreekse. Verbindings hiervan
# IP's word toegelaat om hul IP -adresse en poorte te ignoreer (vir houtkap en
# vir verifikasie -tjeks). deaktiveer_plaintext_auth word ook geïgnoreer vir
# hierdie netwerke. U sal gewoonlik u IMAP Proxy -bedieners hier spesifiseer.
# login_trusted_networks =

# Ruimte -geskeide lys van aanmeldtoegangskontrole -voetstukke (bv. TCPWrap)
# login_access_sockets =

# Moenie doen met 'n proxy_maybe = ja as proxy -bestemming ooreenstem met een van hierdie IP's nie
# volmag. Dit is normaalweg nie nodig nie, maar kan nuttig wees as die bestemming
# IP is bv. 'N Load Balancer se IP.
# Auth_proxy_self =

# Toon meer verbose prosesstitels (in PS). Wys tans gebruikersnaam en
# IP -adres. Nuttig om te sien wie die IMAP -prosesse gebruik
# (bv. Gedeelde posbusse of as dieselfde UID vir verskeie rekeninge gebruik word).
# Verbose_proctitle = NEE

# As alle prosesse doodgemaak word wanneer die Dovecot -meesterproses afskakel.
# Om dit op "nee" in te stel, beteken dat Dovecot opgegradeer kan word sonder
# die bestaande kliëntverbindings te dwing om te sluit (hoewel dit ook kan wees
# 'N Probleem as die opgradering bv. as gevolg van 'n sekuriteitsoplossing).
# shutdown_clients = ja

# As dit nie nul is nie, voer e-posopdragte via hierdie vele verbindings na Doveadm Server uit,
# in plaas daarvan om dit direk in dieselfde proses te laat loop.
# doveadm_worker_count = 0
# Unix Socket of Host: Port wat gebruik word om aan Doveadm Server te koppel
# doveadm_socket_path = doveadm-server

# Ruimte -geskeide lys van omgewingsveranderlikes wat op Dovecot bewaar word
# begin en oorgedra na al sy kinderprosesse. Jy kan ook gee
# Sleutel = waardepare om altyd spesifieke instellings in te stel.
# Import_en omgewings = tz

## 
## Woordeboekbedienerinstellings
## 

# Woordeboek kan gebruik word om sleutel = waardeslyste te stoor. Dit word deur verskeie gebruik
# plugins. Die woordeboek kan direk óf verkry word óf 'n
# Woordeboekbediener. Die volgende DICT -blokkaarte -woordeboekname aan URI's
# Wanneer die bediener gebruik word. Daar kan dan verwys word met behulp van URI's in formaat
# "Proxy :: <naam>".

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

# Hieronder word die meeste van die werklike konfigurasie ingesluit. Die lêernaam is
# eers volgens hul ASCII -waarde gesorteer en in daardie volgorde ontleed. Die 00-voorvoegsels
# In lêernaam is bedoel om dit makliker te maak om die bestelling te verstaan.
!include conf.d/*.conf

# 'N Config -lêer kan ook probeer om ingesluit te word sonder om 'n fout te gee indien
# Dit word nie gevind nie:
!include_try local.conf

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

protocols = imap pop3

# Laat Dovecot toe om na alle invoerverbindings te luister (IPv4 / IPv6)

listen = *, ::
Voeg 'n wagwoord by vir die Dovecot -gebruiker:

nano config/etc_dovecot_passwd
Die eerste deel van die lêer, voor die kolon, is die gebruikersnaam. Die laaste deel, "YourPassword", dui die wagwoord aan wat u wil aan u e -posbediener gee.

team:{plain}yourpassword
Vervolgens, die OpenDkim Config

nano config/etc_opendkim.conf
En voeg hierdie lyne by:

# Dit is 'n basiese opset vir ondertekening en verifiëring. Dit kan maklik wees
# aangepas om by 'n basiese installasie te pas. Sien Opendkim.conf (5) en
# /usr/share/doc/opendkim/examples/opendkim.conf.sample vir volledig
# Dokumentasie van beskikbare konfigurasieparameters.

Syslog			yes
SyslogSuccess		yes
# Log, waarom nee

# Algemene ondertekening en verifikasieparameters. In Debian is die 'van' kop
# oorgeteken, omdat dit dikwels die identiteitsleutel is wat deur reputasiestelsels gebruik word
# en dus ietwat sekuriteitsgevoelig.
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# Onderteken domein, selector en sleutel (vereis). Voer byvoorbeeld ondertekening uit
# vir domein "voorbeeld.com" met selector "2020" (2020._domainkey.example.com),
# Gebruik die privaat sleutel gestoor in /etc/dkimkeys/example.private. Meer korrelvormig
# Opstellingsopsies kan gevind word in /usr/share/doc/opendkim/readme.opendkim.
# Domein voorbeeld.com
# Selector 2020
# Keyfile /etc/dkimkeys/example.privaat

# In Debian werk Opendkim as gebruiker "Opendkim". 'N umask van 007 is nodig wanneer
# Gebruik 'n plaaslike sok met MTA's wat toegang tot die sok as 'n nie-bevoorregte
# Gebruiker (byvoorbeeld Postfix). Miskien moet u die gebruiker "postfix" by die groep voeg
# "Opendkim" in daardie geval.
UserID			opendkim
UMask			007

# Sok vir die MTA -verbinding (benodig). As die MTA in 'n chroot -tronk is,
# Daar moet verseker word dat die aansluiting toeganklik is. In Debian hardloop Postfix in
# 'n chroot in/var/spoel/postfix, daarom sal 'n unix -aansluiting moet wees
# gekonfigureer soos getoon op die laaste reël hieronder.
# Socket plaaslik: /run/opendkim/opendkim.sock
# Socket Inet: 8891@localhost
# SOCKET INET: 8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Die gasheer waarvoor u moet onderteken eerder as om te verifieer, is 127.0.0.1. Sien die
# Operasie -afdeling van Opendkim (8) vir meer inligting.
# Internalhosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# Die trustanker stel DNSSEC in staat. In Debian word die trustankerlêer voorsien
# deur die pakket DNS-Root-data.
TrustAnchorFile		/usr/share/dns/root.key
# Nameservers 127.0.0.1

# Kaartdomeine van adresse na sleutels wat gebruik word om boodskappe te onderteken
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# 'N stel interne gashere wie se pos onderteken moet word
InternalHosts       /etc/opendkim/trusted.hosts

nano config/etc_default_opendkim
En voeg hierdie lyne by

# Opmerking: dit is 'n nalatenskapskonfigurasielêer. Dit word nie deur die Opendkim gebruik nie
# SystemD -diens. Gebruik die ooreenstemmende konfigurasieparameters in
# /etc/opendkim.conf in plaas daarvan.
# 
# Voorheen sou 'n mens die standaardinstellings hier wysig en dan uitvoer
# /lib/opendkim/opendkim.service.
# /etc/systemd/system/opendkim.service.d/override.conf en
# /etc/tmpfiles.d/opendkim.conf. Alhoewel dit nog moontlik is, is dit nou
# Aanbeveel om die instellings direk aan te pas in /etc/opendkim.conf.
# 
# Daemon_opts = ""
# Verander na/var/spoel/postfix/run/opendkim om 'n unix -sok met
# Postfix in 'n chroot:
# Roundir =/var/spoel/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Onkomment om 'n alternatiewe sok te spesifiseer
# Let daarop dat die instelling daarvan enige sokwaarde in OpenDkim.conf sal ignoreer
# verstek:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Luister op alle koppelvlakke op poort 54321:
# Sok = inet: 54321
# Luister op Loopback op poort 12345:
# Sok = inet: 12345@localhost
# Luister is 192.0.2.1 is poort 12345:
# Sok = inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
As ons gereed is om ons postfix -bediener op te stel, sal ons die onderstaande kode uitvoer, met die toepaslike domeinnaam ingebed. Begin deur 'n draaiboek te skep

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
Nou, in Nano, die teksredakteur, wysig hierdie lêer, sodat dit u domeinnaam in plaas van femmebabe.com insluit.

# !
# Stel postfix op
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}'
Begin nou die voltooide skrif om Postfix, Opendkim en Dovecot op te stel.

./scripts/postfixsetup
Sodra hierdie skrip uitgevoer is, kopieer die laaste reël wat dit afdruk en plak dit in u DNS -konfigurasie as die waarde vir SendOnly._Domainkey. Dit is die OpenDkim -sleutel wat gebruik word om u domein te identifiseer wanneer u veilige pos stuur. Awesome! Binne 'n paar dae moet u e -pos vanaf die bediener kan stuur, mits alles korrek gekonfigureer is. As u net die DNS vir u e -posbediener gekonfigureer het, moet dit minder as 72 uur duur voordat die rekords opdateer. Dit is gewoonlik baie vinniger. U kan kyk of u bediener werk deur hierdie opdrag te gebruik, u e -pos voorsien:

echo “test” | mail -s “Test Email” youremail@gmail.com
As alles lyk of dit reg werk, moet u e -pos met u bediener kan stuur. As dit nie werk nie, probeer dan om na die logs te kyk om te sien wat die fout kan wees.

tail –lines 150 /var/log/mail.log
Dit sal mondelinge inligting bied oor e -pos wat deur die bediener gestuur word en of dit goed werk. U moet ook die e -pos in u inkassie kan sien, as dit nie daar is nie, kyk na u spammap. U moet ook u instellings in u instellings.py opstel, sodat u e -posbediener met u Django -app, die projek, kan praat. Voeg of vervang hierdie lyne in u instellings

EMAIL_HOST = DOMAIN
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = 'team@femmebabe.com'
EMAIL_HOST_USER = 'team' # 'Love@mamasheheen.com'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
Let op dat ons 'n config -lêer gebruik om die wagwoord te kry. Kom ons laai hierdie lêer in die instellings soos so, aan die begin van die lêer:

import os
import json

# Oop en laai Config
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Kom ons skep hierdie lêer en voeg 'n geheime sleutel daarby, sowel as die poswagwoord. Om 'n geheime sleutel te genereer, gebruik hierdie opdrag, met watter lengte u aan die einde wil hê:

openssl rand -base64 64
Kopieer nou die teks wat OpenSSL gegenereer en redigeer /etc/config.json

sudo nano /etc/config.json
Voeg die volgende reëls by u lêer, met die sleutel wat OpenSSL as die geheime sleutel gegenereer word.

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
JSON -formaat is eenvoudig en maklik om te gebruik, ons kan ook ander sleutels wat ons in ons projek wil gebruik, ook op hierdie manier verklaar en hulle apart van ons projekgids hou, sodat ander gebruikers nie aan hulle kan skryf nie en dat hulle nie gelees kan word nie uit ons projekgids alleen. Dit word aanbevole praktyk vir API -sleutels, waarvan ons meer as 'n paar hier sal gebruik. U sal ook u projek wil rugsteun om seker te maak dat alles gestoor is en dat u later u werk kan herstel, selfs as u nie meer 'n bediener wil huur nie.

sudo backup
Probeer nou om 'n HTML -e -pos van die webbediener te stuur, mits die stuur van een van die opdragreël werk. Vra u gebruikersinstansie in die dop, en stuur 'n HTML -e -pos aan die gebruiker via django. Verander my naam in die kode, Charlotte, na u 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()
As die eerste opdrag nie werk nie, maak seker dat u dit gebruik

source venv/bin/activate
Mits alles korrek opgestel is, kry u nou 'n welkome e -pos in u posbus wat deur u webprogram gestuur word. Goeie werk! Jy het 'n lang pad gekom. Ek wou byvoeg, as u ooit met enige foute sukkel terwyl u aan 'n projek soos hierdie werk, moet u huiwer om antwoorde te soek en hulp te vra. Google, onder andere soekenjins, is wonderlike hulpbronne om na programmeringshulp te soek. Soek eenvoudig na die fout wat u kry, en u kan sien hoe ander mense die probleem oplos. U is ook welkom om my, u opvoeders (onderwysers, professore, tutors), enige eweknieë op die internet wat beskikbaar is vir programmeringshulp, of weer hierdie boek of ander bronne te raadpleeg om oplossings te vind vir die probleme wat u ervaar. Ek verstaan ​​dat dit nie maklik is nie, maar selfs as u in hierdie verre gelees het en geen kode skryf nie, leer u baie oor die bou van 'n webprogram van nuuts af. Klap jouself agterop, jy doen 'n wonderlikewerk. Dankie dat u die tyd geneem het om hierdie derde uitgawe webontwikkelingsgids te lees. In toekomstige uitgawes sal ek meer van die belangrike voorbeelde wat aan die begin van die dokument bespreek is, insluit, en ons sal baie dieper in die wêreld van sagteware en hardeware -ontwikkeling duik. Bly ingeskakel vir wat gaan kom, en ek sien uit daarna om u te leer hoe om ongelooflike sagteware te bou. Sien jou in die volgende






Dig
Bladsy 1
Spring
Sien volledige artikel
Gaan voort met die lees

Koop | Koop met crypto



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


(Klik of tik om die prentjie af te laai)
Professionele vermaak, foto's, video's, klank, lewende stroom en toevallige spel, sowel as ID -skandering, webontwikkeling en surrogasiedienste.

Laat my 'n wenk in Bitcoin met behulp van hierdie adres: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

Diensvoorwaardes