Apprendimento pratico basato sul Web e sicurezza tramite l'esempio

DaisyFoto del profilo

Di Daisy

Deep Learning e sicurezza pratici basati sul web per esempio Terza edizione Charlotte Harper 3 luglio 2024 Prefazione: Le considerazioni sulla sicurezza nella costruzione di software per il Web sono una parte importante del piano e dell'esecuzione di qualsiasi sviluppatore Web, mentre ingegnerono un prototipo affidabile, stabile e utile per scopi pratici. Il DOM (Document Object Markup), con l'implementazione di HTML, JavaScript e CSS, nonché software di backend che implementano Python, C/C ++, Java e Bash, offrono agli sviluppatori Web la libertà e il potere di creare un'ampia varietà di progetti che esprimono creatività, fornire facilità d'uso e funzionalità, ritrarre umiltà e carattere e fornire facilità d'uso, nonché comodità e servizi importanti che sono tutti attraenti per il Joe medio, l'utente finale che cerca di Uccidi il tempo o fai qualcosa su Internet, di solito su un dispositivo per smartphone touchscreen. La maggior parte delle persone non saprebbe nemmeno da dove cominciare quando vogliono costruire un sito Web da zero,Tenderebbero a iniziare sul sito Web di un'altra persona e costruire qualcosa di limitato in funzionalità, affidabilità, facilità d'uso e soprattutto creatività quando avrebbero potuto avere tutti gli ultimi potenti strumenti a loro disposizione per costruire qualcosa di utile senza perdere tempo a premere i pulsanti e Soprattutto sprecando denaro pagando abbonamenti costosi al software che poche persone volevano utilizzare comunque dato le limitazioni con facilità d'uso e flessibilità. Se hai qualche minuto per leggere questo libro e imparare cosa voglio insegnarti, o addirittura parlare con me personalmente dei tuoi obiettivi e ottenere una guida nella giusta direzione e sei motivato a imparare a codificare e scrivere il tuo software , Porta questo libro a casa e metti da parte un po 'di tempo per imparare a costruire la prossima applicazione Web influente, potente, semplificata e importante, un sito Web che è tutto su di te e fa esattamente quello che desideri e soddisfa le esigenze del tuo pubblico. Su di me: Sono uno sviluppatore di software con un ampioAnge of Experience in C/C ++, Java, Python, HTML, CSS e JavaScript. Costruisco i siti Web che le persone vogliono usare, vogliono visitare e persino essere dipendenti dall'uso solo per imparare, ricreare e uccidere il tempo e, soprattutto, vendo software. Se avessi un'idea su come volevi che un sito Web guardasse e funzionino, eri disposto a supportarmi in modo da poter soddisfare le mie esigenze mentre incontro le tue e sei disposto a coprire i costi di gestione di un sito Web da solo, Ti costruirei il prossimo YouTube, Tiktok, Twitter, Google o persino un'app di sicurezza ad alta tecnologia che solo tu puoi accedere. Invece di provare a venderti il ​​mio tempo, sto cercando di acquistare il tuo: voglio convincerti a costruire un'app (sito Web) da solo con le informazioni che esiste già e ti insegnano ciò di cui hai bisogno per essere uno sviluppatore di software indipendente, Imprenditore, conducendo una carriera di successo in qualunque campo desideri. E lascia che sia chiaro, l'educazione che ti do sarà informale. Potresti andare a scuola e imparare tutto questo con unRMAL Education, o addirittura leggi questo libro a scuola, completa i tuoi incarichi e toglie molto dalla tua istruzione, ma non ti metterò formalmente sul posto caldo e ti chiederò di completare gli incarichi. Non sono il tuo professore, puoi pensare a me come un amico che vuole guidarti verso una carriera guidata dal tuo successo personale. E non sto vendendo nemmeno il successo, dovrai acquistarlo con il tuo tempo. Imparare a programmare ha una curva di apprendimento ripida e non è mai stato facile, o addirittura dovrebbe esserlo. Devi lavorare più duramente possibile e continuare a provare a fallire e riprovare anche quando sei frustrato per imparare e costruire le app da solo. Questo è nella natura del codice stesso. Il codice è gestito da un compilatore progettato per fornire messaggi di errore del programmatore e questi ti insegnerà come codificare, anche se stai semplicemente copiando l'errore nel motore di ricerca e leggendo gli esempi di altre persone. E devo dire che non hai bisogno di essere estremamente ricco, intelligente, di successo,EN DETTAGLIO ORTICOLATO O ORGRIAZIONE PER CREDITA UNA APP. Il computer si occupa di quell'organizzazione per te. Devi solo perseverare attraverso la prova ed errore, mantenere la concentrazione e lavorare sodo per quello che fai e avrai una carriera di grande successo in tutto ciò che fai. Chi sono: Mi rendo conto che l'ultima sezione riguardava più l'apprendimento e il tuo modo di fare un modo da questo libro. Chi sono esattamente? Questa è una domanda complicata. Non sono chiaro su questo, poiché soffro di condizioni mediche che possono rendermi difficile anche il codice o scrivere questo libro a volte, mentre presentavo sfide con i problemi di socializzazione e identità che rendono la mia vita più difficile quando si tratta di introdurmi . In breve, se stai leggendo questo libro, l'hai portato a casa perché l'hai sfogliato e hai pensato che fosse utile, o anche se hai appena letto così lontano, a te sono un individuo affini che vuole vederti avere successo in tutto quello che fai. Sono un ingegnere da solo, un softwaresviluppatore e uno studente, e sto scrivendo questo libro per altri studenti che vogliono semplificare la propria vita avendo un manuale del software di cui hanno bisogno semplificando la propria vita dando esempi da copiare che si adattano come un grande puzzle in un lavoro , App utile, grande, funzionale, coesa e coinvolgente in grado di guidare il successo, indipendentemente dalla linea di attività. In gran parte, questo è quello che faccio: costruisco app per aiutare me stesso e le altre persone ad avere successo. Sono anche un autore, anche se questa è la mia prima pubblicazione che intendo completare per mettere insieme il mio portafoglio in un documento utile e sono anche un artista. Ti ammetterò questo, sono una specie di strana persona. Non sono perfetto, ho fatto correre con la legge che mi ha anche portato a lasciare college e università e lasciare gli stati per cercare di farmi un nome con più successo. Sono una donna di nascita, indosso trucco, scatto foto di me stesso, indosso abiti e altri abiti da donna e rimango consapevole di me stesso come unmaschio per natura. Ho avuto problemi con altre persone in passato che hanno portato a lotte con la scrittura e la costruzione di WebApps, e mi scuso per non essere stato in grado di mettere questo libro in mano prima: ne avevi bisogno. Ti consigliamo di leggere e scrivere un codice che assomiglia al mio e che funzioni come il mio e fa la stessa cosa, ma anche meglio, perché se puoi permetterti di acquistare questo libro invece di schiacciare la tastiera come faccio solo per creare un libro da solo chiedendo denaro Per questo, hai le risorse di cui hai bisogno per avere successo nella tua vita. Ho avuto tutti i tipi di problemi con la famiglia che cresce, le condizioni di salute, i medici, i media e la legge e il mio codice riflettono profondamente la lotta che è il femminismo e la natura femminile in un mondo diviso e frustrato. Tuttavia, questo libro è qualcosa di cui tengo profondamente, il mio bambino, il mio portfolio e il mio sostentamento, quindi apprezzo la tua considerazione quando porti il ​​testo a casa e ci metti con cura per imparare da me. Per favore, tieni presente che non sono perfetto,Il libro avrà errori, revisioni e nuove edizioni e dovrai pensare con il tuo cervello logico nel miglior modo possibile per avere un'esperienza di successo con la mia scrittura. Inoltre, capisci che intendo bene per te anche quando affronti sfide durante la scrittura. Pensaci in questo modo: quando puoi semplicemente noleggiare un sistema informatico per fare qualsiasi cosa tu possa immaginare nello spazio digitale, archiviare tutte le informazioni che incontri, #$%! Yze e organizzarlo e vieni a capirlo, lo farai Incontrare inevitabilmente difficoltà con le informazioni che stai ingerisce e persino pubblicando. Te lo dico perché incontro le stesse difficoltà. Usa questo libro a proprio rischio, lavora con la tua comunità e le comunità a tua disposizione per costruire software in un ambiente sicuro e non prendere le cose per personalmente quando fallisci o addirittura avrai successo nel modo sbagliato: è così che sono arrivato così lontano e perché posso portarti questo testo e aiutarti ad avere successo senza divertire su un percorso di follia che lasciaIo rovinato, strappato e sfilacciato mentre incontro i problemi ordinari che tutti fanno su scala globale grazie alla scala globale paralellistica della rete su cui lavoreremo, Internet. Potresti non avere molta familiarità con chi sono con poche parole, ma ti incoraggio a leggere, mi conoscerai mentre continuerai a leggermi e capirmi mentre costruisci i tuoi progetti per completare il tuo lavoro. Non ci saranno compiti a casa con questo libro, purché i tuoi professori o insegnanti non ti assegnino nessuno, ma ti incoraggio vivamente a costruire un portafoglio di progetti da solo mentre leggi, nonché un progetto Capstone che mostra come puoi Applica ciò che hai imparato. Il mio progetto Capstone è la base per la maggior parte di ciò che leggerai in questo libro, in quanto incorpora il codice dei miei progetti precedenti, il codice che ho creato e imparato a scrivere metodicamente a mano e una vasta gamma di idee e suggerimenti che mi hanno aiutato riuscire al punto in cui posso far girare una semplice app che èUlly è apparso e sembra e si comporta come un'app popolare che potresti vedere il tuo amico o la tua famiglia usare, su Internet, pubblicizzato a te o nelle notizie. Cos'è questo libro: Questo libro è un tutorial per esempio. Puoi trovare il codice qui, le istruzioni su come imparare a codificare, le informazioni sul debug del codice e la correzione di errori, la riso...
Apprendimento pratico basato sul Web e sicurezza tramite l'esempio

Deep Learning e sicurezza pratici basati sul web per esempio Terza edizione Charlotte Harper 3 luglio 2024 Prefazione: Le considerazioni sulla sicurezza nella costruzione di software per il Web sono una parte importante del piano e dell'esecuzione di qualsiasi sviluppatore Web, mentre ingegnerono un prototipo affidabile, stabile e utile per scopi pratici. Il DOM (Document Object Markup), con l'implementazione di HTML, JavaScript e CSS, nonché software di backend che implementano Python, C/C ++, Java e Bash, offrono agli sviluppatori Web la libertà e il potere di creare un'ampia varietà di progetti che esprimono creatività, fornire facilità d'uso e funzionalità, ritrarre umiltà e carattere e fornire facilità d'uso, nonché comodità e servizi importanti che sono tutti attraenti per il Joe medio, l'utente finale che cerca di Uccidi il tempo o fai qualcosa su Internet, di solito su un dispositivo per smartphone touchscreen. La maggior parte delle persone non saprebbe nemmeno da dove cominciare quando vogliono costruire un sito WebScratch, tenderebbero a iniziare sul sito Web di un'altra persona e costruire qualcosa di limitato in funzionalità, affidabilità, facilità d'uso e in particolare creatività quando avrebbero potuto avere a disposizione tutti gli ultimi potenti strumenti per costruire qualcosa di utile senza perdere tempo a premere i pulsanti , e soprattutto sprecare denaro pagando abbonamenti costosi al software che poche persone volevano utilizzare comunque, dato le limitazioni con facilità d'uso e flessibilità. Se hai qualche minuto per leggere questo libro e imparare cosa voglio insegnarti, o addirittura parlare con me personalmente dei tuoi obiettivi e ottenere una guida nella giusta direzione e sei motivato a imparare a codificare e scrivere il tuo software , Porta questo libro a casa e metti da parte un po 'di tempo per imparare a costruire la prossima applicazione Web influente, potente, semplificata e importante, un sito Web che è tutto su di te e fa esattamente quello che desideri e soddisfa le esigenze del tuo pubblico. Su di me: Sono uno sviluppatore di software conGamma di esperienza in C/C ++, Java, Python, HTML, CSS e JavaScript. Costruisco i siti Web che le persone vogliono usare, vogliono visitare e persino essere dipendenti dall'uso solo per imparare, ricreare e uccidere il tempo e, soprattutto, vendo software. Se avessi un'idea su come volevi che un sito Web guardasse e funzionino, eri disposto a supportarmi in modo da poter soddisfare le mie esigenze mentre incontro le tue e sei disposto a coprire i costi di gestione di un sito Web da solo, Ti costruirei il prossimo YouTube, Tiktok, Twitter, Google o persino un'app di sicurezza ad alta tecnologia che solo tu puoi accedere. Invece di provare a venderti il ​​mio tempo, sto cercando di acquistare il tuo: voglio convincerti a costruire un'app (sito Web) da solo con le informazioni che esiste già e ti insegnano ciò di cui hai bisogno per essere uno sviluppatore di software indipendente, Imprenditore, conducendo una carriera di successo in qualunque campo desideri. E lascia che sia chiaro, l'educazione che ti do sarà informale. Potresti andare a scuola e imparare tutto questo con unIstruzione formale, o addirittura leggi questo libro a scuola, completa i tuoi incarichi e toglie molto dalla tua istruzione, ma non ti metterò formalmente sul posto caldo e ti chiederò di completare gli incarichi. Non sono il tuo professore, puoi pensare a me come un amico che vuole guidarti verso una carriera guidata dal tuo successo personale. E non sto vendendo nemmeno il successo, dovrai acquistarlo con il tuo tempo. Imparare a programmare ha una curva di apprendimento ripida e non è mai stato facile, o addirittura dovrebbe esserlo. Devi lavorare più duramente possibile e continuare a provare a fallire e riprovare anche quando sei frustrato per imparare e costruire le app da solo. Questo è nella natura del codice stesso. Il codice è gestito da un compilatore progettato per fornire messaggi di errore del programmatore e questi ti insegnerà come codificare, anche se stai semplicemente copiando l'errore nel motore di ricerca e leggendo gli esempi di altre persone. E devo dire che non hai bisogno di essere estremamente ricco, intelligente,Essful, o addirittura orientato ai dettagli o organizzati per costruire un'app. Il computer si occupa di quell'organizzazione per te. Devi solo perseverare attraverso la prova ed errore, mantenere la concentrazione e lavorare sodo per quello che fai e avrai una carriera di grande successo in tutto ciò che fai. Chi sono: Mi rendo conto che l'ultima sezione riguardava più l'apprendimento e il tuo modo di fare un modo da questo libro. Chi sono esattamente? Questa è una domanda complicata. Non sono chiaro su questo, poiché soffro di condizioni mediche che possono rendermi difficile anche il codice o scrivere questo libro a volte, mentre presentavo sfide con i problemi di socializzazione e identità che rendono la mia vita più difficile quando si tratta di introdurmi . In breve, se stai leggendo questo libro, l'hai portato a casa perché l'hai sfogliato e hai pensato che fosse utile, o anche se hai appena letto così lontano, a te sono un individuo affini che vuole vederti avere successo in tutto quello che fai. Sono un ingegnere io stesso,sviluppatore e uno studente, e sto scrivendo questo libro per altri studenti che vogliono semplificare la propria vita avendo un manuale del software di cui hanno bisogno semplificando la propria vita dando esempi da copiare che si adattano come un grande puzzle in un lavoro , App utile, grande, funzionale, coesa e coinvolgente in grado di guidare il successo, indipendentemente dalla linea di attività. In gran parte, questo è quello che faccio: costruisco app per aiutare me stesso e le altre persone ad avere successo. Sono anche un autore, anche se questa è la mia prima pubblicazione che intendo completare per mettere insieme il mio portafoglio in un documento utile e sono anche un artista. Ti ammetterò questo, sono una specie di strana persona. Non sono perfetto, ho fatto correre con la legge che mi ha anche portato a lasciare college e università e lasciare gli stati per cercare di farmi un nome con più successo. Sono una donna di nascita, indosso trucco, scatto foto di me stesso, indosso abiti e altri abiti da donna e rimango consapevole di me stesso come unfemmina per natura. Ho avuto problemi con altre persone in passato che hanno portato a lotte con la scrittura e la costruzione di webapps, e mi scuso per non essere stato in grado di mettere questo libro in mano prima: ne avevi bisogno. Ti consigliamo di leggere e scrivere un codice che assomiglia al mio e che funzioni come il mio e fa la stessa cosa, ma anche meglio, perché se puoi permetterti di acquistare questo libro invece di schiacciare la tastiera come faccio solo per creare un libro da solo chiedendo denaro Per questo, hai le risorse di cui hai bisogno per avere successo nella tua vita. Ho avuto tutti i tipi di problemi con la famiglia che cresce, le condizioni di salute, i medici, i media e la legge e il mio codice riflettono profondamente la lotta che è il femminismo e la natura femminile in un mondo diviso e frustrato. Tuttavia, questo libro è qualcosa di cui tengo profondamente, il mio bambino, il mio portfolio e il mio sostentamento, quindi apprezzo la tua considerazione quando porti il ​​testo a casa e ci metti con cura per imparare da me. Per favore, tieni presente che non lo sonoECT, questo libro avrà errori, revisioni e nuove edizioni e dovrai pensare con il tuo cervello logico nel miglior modo possibile per avere un'esperienza di successo con la mia scrittura. Inoltre, capisci che intendo bene per te anche quando affronti sfide durante la scrittura. Pensaci in questo modo: quando puoi semplicemente noleggiare un sistema informatico per fare qualsiasi cosa tu possa immaginare nello spazio digitale, archiviare tutte le informazioni che incontri, #$%! Yze e organizzarlo e vieni a capirlo, lo farai Incontrare inevitabilmente difficoltà con le informazioni che stai ingerisce e persino pubblicando. Te lo dico perché incontro le stesse difficoltà. Usa questo libro a proprio rischio, lavora con la tua comunità e le comunità a tua disposizione per costruire software in un ambiente sicuro e non prendere le cose per personalmente quando fallisci o addirittura avrai successo nel modo sbagliato: è così che sono arrivato così lontano e perché posso portarti questo testo e aiutarti ad avere successo senza divertire su un percorso di folliaAves Me rovinato, strappato e sfilacciato mentre incontro i problemi ordinari che tutti fanno su scala globale grazie alla scala globale paralellistica della rete su cui lavoreremo, Internet. Potresti non avere molta familiarità con chi sono con poche parole, ma ti incoraggio a leggere, mi conoscerai mentre continuerai a leggermi e capirmi mentre costruisci i tuoi progetti per completare il tuo lavoro. Non ci saranno compiti a casa con questo libro, purché i tuoi professori o insegnanti non ti assegnino nessuno, ma ti incoraggio vivamente a costruire un portafoglio di progetti da solo mentre leggi, nonché un progetto Capstone che mostra come puoi Applica ciò che hai imparato. Il mio progetto Capstone è la base per la maggior parte di ciò che leggerai in questo libro, in quanto incorpora il codice dei miei progetti precedenti, il codice che ho creato e imparato a scrivere metodicamente a mano e una vasta gamma di idee e suggerimenti che mi hanno aiutato riuscire al punto in cui posso far girare una semplice app cheCompletamente descritto e sembra e si comporta come un'app popolare che potresti vedere il tuo amico o la tua famiglia usare, su Internet, pubblicizzato a te o nelle notizie. Cos'è questo libro: Questo libro è un tutorial per esempio. Puoi trovare il codice qui, le istruzioni su come imparare a codificare, le informazioni sul debug del codice e la correzione di errori, la risoluzione dei problemi, le istruzioni su come eseguire il backup e salvare il codice, ripercaricare se qualcuno interrompe il codice, protegge il codice, distribuisce Il tuo codice, crea siti Web interattivi che sono divertenti, coinvolgenti e avvincenti e avrai un'idea di chi sono, perché questo è importante e come ritrarre te stesso, la tua app e l'immagine dell'azienda, nonché il software Costruisci nella migliore luce in assoluto per essere la più attraente possibile per gli utenti finali, i visitatori del tuo sito Web. In questo libro, dimostrerò una serie di esempi di progettazione di software con particolare attenzione al Web come piattaforma e sicurezza. Inizieremo l'esperienza di apprendimento costruendo una baseOject usando la shell UNIX, con funzionalità di backup e scripting. Quindi, esamineremo un sito Web del blog di base, aggiorneremo il nostro blog con funzionalità fotografiche e video e utilizzeremo queste funzionalità per utilizzare soluzioni di sicurezza utilizzando il software gratuito e proteggere il nostro server utilizzando un modulo di autenticazione pluggable (PAM). Esamineremo quindi la gestione e l'elaborazione dei file, esplorando l'editing video, la donazione vocale, la scansione dei codici a barre e il riconoscimento ottico dei personaggi, tra gli altri concetti. Lungo la strada esamineremo le API che ci aiuteranno a rendere il nostro software più utile e sicuro, con opzioni gratuite e a pagamento. Lungo la strada, esploreremo strumenti di sicurezza fisica e militanti come armi da fuoco e manifatturieri e manifatturiero tra cui il design a barile e ripetitore, la progettazione di torretta e drone e altri principi che integreremo con il nostro software sulla rete esistente al fine di proteggere il nostro software e dimostrare l'autodifesa e la resilcienza. Faremo pause lungo la strada per costruire giochi, 2D e 3Dmotori di tensione e lavorare con hardware incorporato nei casi di studio esempi di software di rendering dimensionale di base e un massaggiatore vibrante elettronico fuso in gomma siliconica rispettivamente. Lungo la strada, utilizzeremo anche soluzioni di apprendimento automatico già disponibili per proteggere meglio il nostro software. Impiegheremo anche strumenti di borsa disponibili per il Web al fine di semplificare e proteggere il processo. Questo libro è una guida al tuo successo nella costruzione di un'applicazione Web e nell'integrazione con una rete professionale di computer e sistemi meccanici incorporati e nel complesso una guida per la costruzione di software e hardware incorporato senza conoscenza di base o esperienza precedente. Quello che questo libro non è: Se vuoi davvero avere un sito Web, potresti semplicemente impostare un semplice negozio e vendere ciò di cui hai bisogno, pubblicare un blog, pubblicare foto o video o altrimenti senza mai scrivere una singola riga di codice. Questo libro non è quello. Questo libro ti insegnerà come creare software più utile, completamentein primo piano, funzionale e sicuro rispetto a qualsiasi software che puoi già trovare, perché distribuisce il software più recente che è ancora prototipi, può essere costoso da eseguire in una scala di società anziane a operare e non si appella a aziende contorte a backwards impostato Fai soldi per le persone che non stanno davvero facendo nulla. Se segui da vicino questo libro, vorrai scrivere codice, codice di ricerca, creare le tue app e fare soldi da ciò che fai. Farò soldi da questo libro, anche nelle prime fasi, perché contiene informazioni che le persone hanno bisogno e vogliono leggere e stanno già acquistando quando acquistano o usano le mie app. Questo libro non costruirà un'app per te, ma ti indicherà la giusta direzione e ti armato con gli strumenti di cui hai bisogno e le capacità e i suggerimenti che faciliteranno il tuo successo nella costruzione di software per il Web, con ogni linea di Codice dovrai scrivere come esempio, pronto per essere messo insieme nel software tu e i tuoi sostenitori, ospiti, clientela,Riends, famiglia, visitatori, appaltatori e le persone di Internet vogliono usare e supportare. Cosa imparerai: Questo libro ti insegnerà come creare e vendere software, software davvero funzionale, utile, registrazione dei media, funzionalità di sicurezza come riconoscimento facciale, scansione dei codici a barre delle zone leggibili da macchina, API Web per autenticare, registrare e rendere video e foto e scambiare messaggi come Bluetooth e vicino alla comunicazione sul campo (NFC). Questo libro ti insegnerà come utilizzare un computer in rete, concentrandosi su Debian Linux, come costruire il codice bash per rendere l'installazione e il backup del tuo software una brezza senza soluzione di continuità e automatizzata, come costruire il codice Python come back -end per servire messaggi dinamici, stile di stile Le cose che utilizzano bene gli stili CSS con bootstrap, abilitano gli accessi degli utenti e l'interattività tramite dispositivi in ​​rete, crei supporti interattivi e rete con altri siti Web per offrire funzionalità di sicurezza come messaggi di testo per la verifica o Altri scopi, scansione ID, moderazione immagine e video, datiRansazioni per mantenere il tuo software sicuro, elaborazione dei pagamenti, trading di criptovaluta, attività asincroni e altro ancora. Imparerai come costruire i tuoi dispositivi Bluetooth, con batterie, caricabatterie, microcontrollori, circuiti, motori e sensori, utilizzando materiali di saldatura, filo e 3D stampati e fusioni. Dimostrerò i principi di progettazione 3D applicati alla produzione additiva e agli strumenti e alla making, in modo da essere in grado di produrre i tuoi dispositivi hardware incorporati con batterie integrate, caricabatterie, circuiti elettronici e uscite funzionali. e in rete con Bluetooth e il Web. In particolare, esamineremo due casi studio, un massaggiatore vibrante e un'arma da fuoco fatta in casa, entrambi programmati in OpenScad, che è disponibile come interfaccia grafica o utilità della linea di comando e può essere integrato in una rete per risultati più rapidi. Imparerai come costruire e distribuire un sito Web da zero senza un'esperienza precedente, renderlo funzionale, sicuro, bello, utile e la maggior parteMortalmente pratico. Imparerai come utilizzare l'apprendimento automatico e la visione informatica per rendere un sito sicuro e più pratico, registrare video e audio dal tuo sito Web, donare la tua voce, fare musica e modulare l'audio per creare campioni utili e come sfondare il rumore Sfruttare altri siti Web per creare la migliore rete possibile di siti Web che puoi collegare direttamente alla tua per condividere tutte le informazioni utili che hai da offrire e, soprattutto, portare le persone al tuo software e al tuo business. Questo libro si concentrerà molto su media, sicurezza e apprendimento automatico, che sono i tre componenti principali che ti aiuteranno a creare software utili per il Web coinvolgendo gli utenti giusti e disimpegnando quelli sbagliati in un modo realistico, pratico, mani e coinvolgenti pur anche automatici e robusti. Questo libro insegna UNIX, in particolare Debian (Ubuntu), Bash Shell, Python, HTML, CSS, JavaScript e una serie di utili pacchetti software pern come richieste, nonché un utile software bash come GIT e FFMPEG. Ti insegnerò anche come scambiare automaticamente la criptovaluta e prendere i pagamenti in criptovaluta o da carte di debito regolari, pur pagando ai tuoi visitatori una quota delle tue entrate se scegli di farlo. Ti insegnerò come fare soldi anche dal tuo sito Web attraverso la pubblicità, come preparare la tua app per i motori di ricerca e renderla veloce, classificata nella prima classifica per ciò che i tuoi clienti cercheranno per trovarti e classificarti in tasso comune cerca il più possibile. Ti insegnerò come vendere il tuo software, pubblicizzarlo, fare appello ai clienti che cercano i tuoi servizi e fatti un nome su Internet attraverso viali che già esistono, sono economici e funzionano bene. Ti insegnerò come salvare i tuoi dati sui cloud computer che funzionano per te e salvare i tuoi dati a buon mercato, come pianificare e creare un sito Web che faccia ciò che i tuoi utenti desiderano e ciò che desideri e come coinvolgere i tuoi utentiing tuo sito un tocco sui loro telefoni con notifiche, e -mail, messaggi di testo, telefonate e altre strade per riportare i tuoi utenti sul tuo sito Web a tua disposizione dietro il clic di un pulsante fissato solo a te. Questo libro si concentrerà sulla praticità della pubblicazione e della distribuzione dei media in grandi quantità, dal testo alle foto ai video all'audio, facendo una buona impressione sugli utenti finali (la tua clientela) e venduti in qualsiasi modo per creare Un sito Web, un'app rappresentativa solo di te e di te e rende il tuo software e la tua azienda nel miglior modo possibile. Imparerai anche alcuni suggerimenti e trucchi da me, da consigli di codifica, vanità pratica come il trucco e la fotografia, la modellazione e la recitazione e altro ancora, il che sarà importante per interpretare te stesso e la tua azienda nella migliore luce possibile utilizzando tutti gli strumenti disponibili a te distribuendo tutti i contenuti di cui hai bisogno su un sano equilibrio di piattaforme per portare il tuoE per realizzare senza sforzo, lavoro o denaro di quanto sia necessario. Questo libro si chiama "Practical Based Deep Learning and Security per esempio" per un motivo: si occupa dell'apprendimento per il codice, in particolare per il Web, in particolare con un focus sulla sicurezza, da un punto di vista pratico, con esempi di codice di lavoro che serve Gli scopi pratici delineati nel testo. Il componente di apprendimento di questo testo comprende anche l'apprendimento automatico, il codice che ti mostrerò come eseguire per il Web che gestirà la visione informatica, il riconoscimento facciale, la moderazione delle immagini e il video, il miglioramento delle immagini, il miglioramento della risoluzione, i sottotitoli e altre attività come compiti come Metriche di previsione provenienti da immagini, come la natura dell'immagine come un'immagine autentica e trasferuta per computer o una copia ottica (una foto di un'immagine o una foto stampata). L'apprendimento automatico è molto importante quando si tratta di sicurezza web e sicurezza del software, perché può preformarsi attività altrimenti impossibili. Il tuo computerAccedi con un passcode, ma potrebbe essere più sicuro usarlo se ti accede con il viso. Puoi creare un computer server in modo sicuro, un computer che normalmente ti chiederebbe un nome utente e un passcode e accedervi, forse con un token di conferma per ogni nuovo accesso o nuovo indirizzo IP, ma se stai costruendo su larga scala, facile Utilizzo, fondamentalmente sicuro e potente software, questo potrebbe essere sufficiente. Legare il tuo software troppo da vicino al software di qualcun altro, come un servizio di posta elettronica o un servizio di messaggi di testo, non è sufficiente per rendere sicuro il tuo software o chiunque (qualsiasi sito che usi). Chiunque costruisca software che sia impeccabilmente sicuro ha un certo senso di ciò che ciò implica. Il software è intrinsecamente insicuro perché i dispositivi e gli account che utilizziamo per accedervi non sono sempre a nostra disposizione, potrebbero essere nelle mani di chiunque abbia un cattivo intento per il software e quindi potrebbero rappresentare un rischio per il software stesso. Questo è un focus di questo libro. Un computer in rete è per impostazione predefinitaSesso con un fulmine a chiave, chiamato e SSH o Secure Shell Key, ed è altrimenti meglio protetto con un server Web, poiché il server Web fornisce l'accesso aperto e gli strumenti di sicurezza artistici in esecuzione sul server stesso. Il server Web ha accesso al browser Web dell'utente, che è probabilmente la parte più potente del dispositivo dell'utente, perché è il luogo in cui l'utente può accedere al software in rete. Questo toolkit può rendere il testo, le pagine Web che vedi e può anche registrare immagini, audio e video (come una foto di una faccia o un ID statale), può leggere e scrivere su dispositivi radio Bluetooth e può leggere e scrivere su un campo vicino Tag transponder, schede chiave economiche, FOB, adesivi, anelli e persino impianti di chip con numeri di serie unici che possono essere letti e scritti con i dati generati e validati da un server Web legati al sito Web. Utilizzando tutti gli strumenti a tua disposizione, con questo libro ti dovererai le conoscenze per costruire un sito Web sicuro e nel complesso ASistema informatico in rete URE che funziona per te, fa le tue offerte e sembra e si sente bene. Da dove cominciare: Sei il benvenuto per saltare oltre la sezione con cui inizio questo libro, o qualsiasi sezione, al codice esatto di cui hai bisogno, specialmente se hai esperienza con la codifica prima o uno degli strumenti di cui sopra che descriverò in dettaglio in questo libro come oltre a documentare casi d'uso e esempi pratici di ciò. Se non hai esperienza nella scrittura del codice, ti consiglio vivamente di leggere tutto questo libro e in particolare ti consiglio di leggere le sezioni precedenti, per assicurarti che questo libro sia giusto per te. Se questo libro non è giusto per te, considera di regalarlo a un amico o un parente che potrebbe essere interessato a conoscere lo sviluppo del web stesso e persino prendere in considerazione il prestito e l'apprendimento da loro per colmare le lacune in cui ti ho deluso come un insegnante o altri insegnanti lo hanno fatto davanti a me. Inizia dove farai, ogni parte di questo libro sarà utile se si intende costruire un utilePP e considera che le migliori app sono costruite pensando all'utente finale: conosci il tuo cliente. Ora mi conosci, conosci questo libro e sei pronto per iniziare. Per iniziare, prendi un computer (anche il laptop più economico da un box store, Amazon o un vecchio desktop funziona e impostalo in un modo che funzioni per te. Come leggere questo libro: Testo evidenziato, indica che il testo appartiene a un prompt dei comandi, in cui scriverai il codice eseguito. Il prompt dei comandi è fortemente focalizzato sulla tastiera e richiede poca o nessun clic, accelerando il flusso di lavoro e rendendo le cose più facili su di te. Iniziare: Ci immergiamo. Iniziamo costruendo il codice su una macchina locale e inizieremo senza costruire un sito Web connesso a Internet. Questo è più sicuro per cominciare, non costa nulla ed è facile per te. A seconda del sistema operativo, entrare in una conchiglia di bash sarà un po 'diverso. Per Mac OS, ti consiglio di installare una macchina virtuale a questo punto, poiché otterrai la massima compatibilità conmacchina virtuale. Vari provider come VirtualBox e Palells possono eseguire una macchina virtuale per te, sebbene sia anche possibile installare Ubuntu direttamente sulla macchina, se si preferisce utilizzare un ambiente nativo che è consigliato per creare un'esperienza rapida e snella. Se stai usando Linux o Windows, che ti consiglio, dovrebbe essere abbastanza facile creare un progetto. Apri il tuo terminale, regola il dimensionamento come si vede adatta e inizia il passaggio seguente 2. Se si utilizza Windows, seguire il passaggio 1. Passaggio 1: - Solo utenti di Windows In Windows, apri il prompt dei comandi come amministratore e digita WSL –Install Passaggio 2: - Continua qui o salta il passaggio 1 a qui se non si utilizza Windows In un terminale aperto, (a seconda del sistema operativo, chiamato Ubuntu in Windows, terminale in Mac o Linux o un nome simile), inizia creando un progetto. Lo facciamo con il comando MKDIR, che crea una directory. Se è necessario creare una directory per archiviare il tuo progetto, che è consigliato, utilizzare ilcomando CD per passare alla directory e e CD/PATH/TO/Directory - Il percorso è le cartelle (file) che precedono la directory di destinazione, il percorso predefinito è ~ o/home/nome utente (dove il nome utente è il tuo nome utente). Per passare alla directory predefinita, digitare CD o CD ~ Esempio MKDIR - Sostituisci "Esempio" con il nome della directory Ora hai una directory di lavoro per il tuo progetto. Essere come è così importante salvare questa directory nel caso in cui sia necessario passare a una macchina diversa o distribuire il codice che scrivi in ​​modo che sia pronto per il Web, costruiremo uno script per eseguire il backup della tua directory nei prossimi passaggi. Ma la creazione di uno script richiede un po 'di codice e il codice deve essere automatizzato per essere il più utile possibile. Quindi costruiamo prima una sceneggiatura per creare script. Cominciamo creando lo script e rendendolo eseguibile. Useremo sudo, chmod e tocht per questo e chiameremo lo script


sudo touch /usr/bin/ascript
sudo chmod a+x /usr/bin/ascript
sudo nano /usr/bin/ascript
Ora abbiamo creato lo script, reso eseguibile e siamo pronti a modificarlo. Nano è un editor di testo che ti consente di modificare il testo senza fare clic, il che è molto più semplice rispetto all'utilizzo di un'interfaccia utente grafica. Per modificare un file con nano, utilizzare nano e quindi il percorso del file. Per creare una sceneggiatura che produce una sceneggiatura, è abbastanza simile a fare la nostra sceneggiatura in primo luogo. Useremo lo stesso codice di cui sopra, sostituendo il nome dello script, "ascript" con un parametro argomento, $ 1. Questo ci consente di chiamare lo script digitando semplicemente sudo ascript Newscript, a quel punto possiamo creare qualsiasi nuovo script sostituendo "Newscript" con il nome del tuo script. Il codice in nano dovrebbe apparire:

sudo touch /usr/bin/$1
sudo chmod a+x /usr/bin/$1
sudo nano /usr/bin/$1
E per chiudere Nano, possiamo tenere premuto il tasto di controllo e premere X, quindi Y per indicare che stiamo salvando il file e prendiamo il ritorno. Ora invece di digitare questi tre comandi per modificare uno script, saremo in grado di digitare sudo ascript ascript per modificare nuovamente lo script. Questo funziona! E qualsiasi nuovo script può essere eseguito facilmente chiamandolo nella shell. Salviamo il nostro lavoro ora: scriviamo uno script di backup per salvare il nostro nuovo script e poi eseguirlo nella nostra directory del progetto, eseguendo anche il backup dello script di backup.

sudo ascript backup
Ora, in nano:

sudo cp /usr/bin/backup /path/to/directory/
sudo cp /usr/bin/ascript /path/to/directory/
Dove/path/to/directory è il percorso del progetto creato con MKDIR. Successivamente impareremo come copiare percorsi di ripetizione come questo con un ciclo e un elenco, che è meno codice, ma per ora manteniamolo semplice e abbiamo alcune righe. Per eseguire questo script e eseguire il backup del codice, salva il file in nano con Control+X, Y e Return e digita il di seguito nella shell

backup
Se ti viene richiesto una password durante la lettura di questo libro e si seguono nella shell, inserisci correttamente la password dell'utente, avrai tre tentativi prima di dover ripetere il comando. È possibile utilizzare le frecce su e giù per riesarcizzare i comandi e modificarle, se hai bisogno di eseguire qualsiasi cosa due volte. Semplice premere su e giù in modo intermittente per selezionare un comando, prima di modificare il comando con le frecce destra, sinistra ed eliminare il tasto oltre alla tastiera e eseguirlo con reso. Congratulazioni! Sei riuscito a creare uno script di backup fantastico che esegue il backup di due importanti script di shell nella tua directory di lavoro. Potremmo muovere le cose più tardi quando il progetto diventa più grande, ma per ora funziona. Andiamo a fare il backup nel cloud, useremo GitHub per questo (anche se ci sono numerose altre soluzioni GIT per il backup, sono tutte più o meno lo stesso.) Git è un software di controllo delle verisioni che ti consente di eseguire il backup delle modifiche al tuo software mentre li fai a un server, mentreTi consente anche di scaricare intere copie del tuo software dietro una password o una chiave. È determinante nel salvare il tuo software, soprattutto quando migriamo su istanze di Linux protette che a volte si rompono quando una singola riga di codice fallisce, lasciandoti bloccato mentre il codice potrebbe non essere eseguito il backup se non hai la possibilità di sostenerlo Superlo automaticamente, che copriremo. Se non stai già utilizzando una macchina virtuale Ubuntu a questo punto, a questo punto mi consiglierò utilizzando una macchina virtuale di Ubuntu perché renderà la vita più semplice durante l'installazione di tutti i pacchetti necessari per costruire un sito Web funzionante e preformare il deep learning Operazioni sul tuo computer. Sposteremo il codice su un server Web nel prossimo futuro, ma vogliamo assicurarci che ci siano almeno alcuni livelli di sicurezza dietro il nostro server web resistenti al phishing e impiegano una serie di pacchetti Linux per fare Questo. Se vuoi ancora utilizzare Mac OS, sei invitato a cercare e installareE i pacchetti necessari online, ma potrebbero non esserci alternative per ogni pacchetto che questo libro o serie coprirà. Aggiungiamo alcuni comandi per commettere il nostro lavoro con lo script di backup eseguendo il comando sudo ascript

# ...
git add –all
git commit -m “backup”
git push -u origin master
Ancora una volta, controlla X per salvare. Ora dobbiamo fare una configurazione una volta per questo progetto. Poiché presto sarà un progetto GIT, non abbiamo bisogno di digitare ogni comando ogni volta che distribuiamo da un repository Git, ma avremo la sospensione di questo quando scriviamo i nostri script di distribuzione. Per iniziare, assicuriamoci di essere nella directory giusta e inizializzare il repository Git e generare chiavi SSH.

cd /path/to/directory
git init
git branch -m master
ssh-keygen
Dopo aver digitato SSH-Keygen, la nuova chiave dovrebbe essere salvata nella cartella domestica in una cartella chiamata .SSH. Si chiama id_rsa.pub. Troviamo questa chiave e copialo. Per vederlo,

cd ~
cat .ssh/id_rsa.pub
Copia il testo che viene restituito dall'ultimo comando e crea un account con il tuo provider GIT (idealmente GitHub), prima di aggiungere la chiave SSH al tuo account. Una volta che hai un account, fai clic sul menu in alto a destra e immetti le impostazioni, prima di aggiungere il tasto SSH in tasti SSH e GPG sotto accesso nel menu. Seleziona Aggiungi una chiave SSH e aggiungi il tuo incollandolo e dandogli un titolo, prima di salvare e tornare a GitHub per creare un nuovo repository. Questo è simile per altri fornitori di GIT, dovrai leggere la loro documentazione. Nella nuova configurazione del repository, dai al tuo repository un nome descrittivo e decidi se si desidera pubblicarlo e assicurarsi di configurare nessun file per l'inclusione. Una volta creato il repository, copiare il clone con URL SSH e incollarlo nel comando seguente.

git remote add git://… (your remote URL)
Ora puoi tornare al tuo repository con CD, avrai familiarità con questo. Prova ora il tuo script di backup con backup Grande! Ora possiamo davvero ottenere la codifica. Installiamo Django ora che abbiamo una buona comprensione di Bash e Git. Django ci consentirà di eseguire il backup automatico del nostro software, anche Bash può farlo, ma Django dovrebbe avere un'implementazione più sicura più sicura (può essere disabilitato e configurato più facilmente). Per installare il software in Ubuntu, utilizzeremo il comando sudo apt-get. Innanzitutto, aggiorniamo e aggiorniamo il software che abbiamo già avuto. Questo può essere fatto con Sudo Apt-get Update e sudo Apt-get Upgrade -y. Successivamente, installamo Python e il nostro ambiente virtuale, la casa del nostro codice, con il seguente comando: sudo apt-get Installa Python-is-Python3 Python3-Venvv Questo è tutto ciò che serve per andare avanti con Django in termini di installazioni di software nell'istanza di Ubuntu. Per Windows e Linux questo dovrebbe essere abbastanza semplice, ma per Mac potresti voler installare una macchina virtuale eLinux su di esso utilizzando un ambiente virtuale gratuito o a pagamento come VirtualBox o Palells Desktop e ricreare i passaggi sopra per configurare un ambiente Ubuntu. Ubuntu è fondamentale in questo caso perché è il software eseguito i siti Web e consente loro di ospitare siti Web con tutto il software sopra menzionato. Scaviamo nel Django. Di nuovo nella nostra directory, con

python -m venv venv # Crea l'ambiente virtuale in cui il codice viene archiviato
source venv/bin/activate # Attiva l'ambiente virtuale
pip install Django
django-admin startproject mysite . # Dove mysite è il progetto che sto iniziando nella mia attuale directory.
Django ci sta appena iniziando, perché Django ospita il server Web e sta facendo tutto il necessario per ottenere un sito Web locale di base attivo e funzionante. Ora che abbiamo installato Django, modifichiamo un po 'le impostazioni per farlo funzionare come abbiamo bisogno. Innanzitutto, creiamo una nuova app

python manage.py startapp feed
Noterai che la prima app si chiama feed. L'app dovrebbe essere chiamata come vuoi e creeremo nuove app, ma il nome di ogni app deve essere coerente ogni volta che l'app viene referenziata nel codice. Per aggiungere una nuova app, modificheremo sempre le impostazioni.py nella directory creata dall'app, denominata in startProject, in seguito app. Usando nano,

nano app/settings.py
Nelle impostazioni, trova Instald_Apps e separa il [] in 3 righe. Usando quattro spazi sulla linea centrale vuota, aggiungi "feed" o il nome della tua app. Questa sezione di impostazioni di impostazione dovrebbe apparire:

INSTALLED_APPS = [
    'feed',
]
Prima di dimenticare, testiamo che Django funziona. Utilizzando il comando Python Manage.py Runserver 0.0.0.0:8000, possiamo eseguire il server e quindi navigare in un browser Web sul computer eseguendo il codice su http: // localhost: 8000 e vedere una pagina web di esempio (funziona!) Emetti il ​​server con il controllo C, uguale a qualsiasi altro comando. Ora, scaviamo a scrivere del codice Python. Django ha tre componenti principali, tutti eseguiti dal codice interamente. I componenti sono chiamati modello, vista e modello e ognuno è rispettivamente a livello più alto e più basso prima che la pagina Web venga consegnata all'utente. Il modello è il codice che memorizza le informazioni nel database per il recupero, la selezione e il rendering. La vista decide come il modello viene reso, manipolato e modificato, quasi ogni vista utilizzerà direttamente un modello. Il modello è il codice HTML con alcune campane e fischi extra chiamati Lingua Template. Il modello è reso dalla vista in cui è pieno di codice Python econtesto come modelli e informazioni (stringhe e numeri interi usuall) dalla vista. Django ha anche altri componenti, tra cui ma non limitato a: Impostazioni, che configura l'app come abbiamo discusso. URL, che sono modelli che l'utente segue per ottenere l'accesso a parti specifiche dell'applicazione Web. Moduli, che definiscono il modo in cui le informazioni inviate al server vengono gestite e rese al database e all'utente. Queste sono le basi delle informazioni di elaborazione sul lato server e possono accettare qualsiasi tipo di informazione che il computer memorizza, in particolare stringhe di testo, numeri e booleani True/False (di solito caselle di controllo). I modelli, che sono il codice HTML e il linguaggio dei modelli e colpiscono il divario tra Python e HTML, il che significa che le informazioni di Python possono essere servite come codice HTML a cui chiunque può accedere e può proteggere un sito Web con accesso limitato, rendendo il codice Python accessibile al Web e utile per una varietà di scopi su un dispositivo remoto che non lo faEed per essere vicino al server. File statici, che di solito sono JavaScript e le sue librerie che il server serve e sono collegate al modello. I file multimediali, che il server serve o sono ospitati esternamente o appena scritti sul server prima di essere elaborati e pubblicati su un altro server (un bucket) per l'hosting. Middleware, che è pezzi di codice che vengono eseguiti contemporaneamente a ogni vista e sono considerati "inclusi" nella vista. Processori di contesto, che elaborano il contesto di ogni vista e vengono utilizzati per aggiungere un contesto extra. Test, che convalidano che l'utente o la richiesta superano determinati requisiti prima che venga resa. I consumatori, che determinano il modo in cui WebSockets gestisce e rispondono alla comunicazione. Amministratore, che viene utilizzato per registrare i modelli in modo che possano essere manipolati in dettaglio all'interno della pagina di amministrazione di Django, in cui il database può essere somministrato attraverso un'interfaccia grafica. Il sedano, che definisce compiti asincroni, possono iniziare parti del codice Djangoprima di procedere immediatamente all'attività successiva o alla riga di codice. Django può avere molti altri componenti, di cui discuteremo in dettaglio qui. Esistono molti modi per rendere il Django più funzionale, aggiungendo websocket, che sono canali di comunicazione rapidi e semplificati, sedano, che eseguono compiti asincroni e una moltitudine di altri software per estendere Django, specialmente nelle funzioni di vista, dove la maggior parte di Il codice viene eseguito. Le funzioni di visualizzazione sono fondamentali perché di solito dichiarano ogni pezzo di codice specifico per un modello URL specifico o una sezione del server. Innanzitutto, esploriamo le funzioni di visualizzazione. Le funzioni di visualizzazione iniziano con le importazioni che indicano il codice che verrà utilizzato nella vista e sono definite utilizzando le normali definizioni o classi di funzioni. Le viste più semplici sono definite dalla definizione della funzione DEF e restituiscono un HTTPresponse con un modello di base. Cominciamo definendo una vista di base per restituire il testo "Hello World". Ricorda che ogni volta che aggiungiFter un'affermazione come def, se, mentre, per, ecc., Dovrai aggiungere 4 spazi per ciascuna delle definizioni precedenti che desideri applicare alla tua funzione. Entreremo presto in ciò che ognuno di questi significa. Dalla directory del nostro sito, modifica il file feed/views.py utilizzando Nano e aggiungi le seguenti righe alla fine del

from django.http import HttpResponse

def hello(request):
    return HttpResponse('hello world')
HttPresponse di Django risponde con una stringa di testo, indicata con l'apertura e la chiusura '. Ogni volta che si passa informazioni a una funzione o classe, come richiesta o una stringa, dovrai utilizzare tra parentesi (, apertura e chiusura). Non è tutto ciò di cui abbiamo ancora bisogno per vedere la nostra opinione. Naturalmente, non abbiamo detto al server dove è esattamente la vista, dobbiamo ancora definire un percorso attraverso il quale dovrebbe essere resa la vista. Cominciamo definendo un percorso di base in app/urls.py e entreremo in gruppi di percorso in seguito. In app/urls.py, aggiungi una riga dopo le istruzioni di importazione dopo l'inizio dell'importazione della vista che abbiamo appena creato.

from feed import views as feed_views
Ora, definiamo il modello di vista. I modelli di visualizzazione hanno tre componenti, il componente del percorso, che indica al server in cui esiste la vista all'interno del server (il percorso URL che l'utente digita nella barra di navigazione per immettere la pagina web), il componente di visualizzazione in cui è specificata la vista e a Nome amichevole per la vista in modo che sia facile recuperare il suo modello quando si lavora con un modello, specialmente in modo che il nome possa essere modificato e aggiornato se necessario per fare spazio per un'altra vista o affrontare un nome più logico. Ha senso fare le cose in questo modo ed essere flessibili, perché la tua base di codice sarà un ambiente in continua evoluzione che necessita di flessibilità e improvvisazione per essere preziosa e facile da lavorare. Ecco come sarà la tua vista, puoi aggiungerlo a UrlPatterns = [Sezione di app/urls.py. Il modello di vista è definito con i tre componenti sopra descritti e una funzione chiamata percorso. I tuoi schemi URL sono un elenco, quindi assicurati di terminare sempre ogni elemento in essicon una virgola, perché questo separa ciascuno. Ogni articolo dovrebbe anche andare su una nuova riga, ancora una volta con quattro spazi prima, proprio come l'app in Impostazioni. Definiremo il primo componente della vista con una funzione di stringa vuota, al fine di creare una vista che viene eseguita nella directory principale del server Web. I tuoi urls.py ora dovrebbero apparire

from feed import views as feed_views

urlpatterns = [
    path('', feed_views.hello, name='hello'),
]
Questa è la base per la creazione di un sito Web con Django completamente statico. Al fine di creare un sito Web più dinamico in cui possiamo iniziare le informazioni sulla memorizzazione nella cache, come immagini, video, audio e altro ancora, dovremo usare i modelli, che esploreremo dopo. Per ora, controlliamo il nostro codice ed eseguiamo il server. Per controllare il codice per errori, eseguire:

python manage.py check
Se ci sono messaggi di errore, dovresti rivedere attentamente le modifiche apportate alla tua app e vedere se c'è qualcosa che deve essere risolto, come uno spazio estraneo o privo, un carattere extra, una stringa non chiusa, qualsiasi errore di battitura, qualsiasi accidentalmente carattere cancellato o qualsiasi altra cosa. Leggendo attraverso il messaggio di errore (se ne hai uno), dovresti essere in grado di vedere il percorso di un file creato o modificato insieme a un numero di riga, quindi guarda in quel file e una riga e vedi se riesci a riparare tutto ciò che è lì . Se hai risolto il problema, eseguire di nuovo il comando sopra. Quando il tuo software è pronto per essere eseguito e funziona, vedrai il "controllo del sistema non ha identificato alcun problema". Ora sei pronto per partire. Esegui il server con:

python manage.py runserver 0.0.0.0:8000
Ora apri un browser Web e vai su http: // localhost: 8000. Dovresti vedere il testo restituito nella parentesi e le citazioni della funzione HttPresponse nel tuo punto di vista. Questo è solo un esempio di base, ma se sei arrivato così lontano, capisci le basi di come funzionano Linux, Bash, Python e Django. Scaviamo più a fondo in alcuni modelli di database ed esploriamo il potere di una classe Python nella memorizzazione di informazioni. Quindi, inizieremo a prendere una presa su HTML e CSS prima di rendere il nostro sito completamente presente, flessibile e sicuro utilizzando JavaScript e Machine Learning. Le lezioni sono archiviate in models.py della tua app. Utilizzando Nano, modifica app/models.py e aggiungi una nuova classe. Una classe è definita con la definizione della classe e viene superata una superclasse da cui eredita, in questo caso modelli.model. Il nome della classe arriva dopo la definizione della classe e dopo la definizione della classe A: (colon), prima che gli attributi e le definizioni delle funzioni legate alla classe siano indicati di seguito. La nostra classeHa bisogno di un ID che possiamo usare per recuperarlo e mantenerlo unico, e ha anche bisogno di un campo di testo per archiviare alcune informazioni. Successivamente possiamo aggiungere un timestamp, file, booleani (definizioni vere o false che possono aiutare il nostro codice a prendere decisioni su cosa fare con il modello e possono essere utilizzati per ordinarlo), un'istanza per legare il modello a un utente registrato nel server e altro ancora. Disimballiamo il codice

from django.db import models # L'importazione che viene utilizzata per definire la nostra classe e i suoi attributi

class Post(models.Model): # La definizione della nostra classe stessa
    id = models.AutoField(primary_key=True) # L'ID del nostro modello, una chiave generata automaticamente che ci consentirà di interrogare il modello, lo manterrà unico ed è utile quando dobbiamo interagire con il modello una volta che è stato creato.
    text = models.TextField(default='') # L'attributo i nostri negozi di classe, in questo caso, un po 'di testo, inadempiente a una stringa vuota.
Chiudi e salva il file come facevamo prima per finire. Ci sono molti altri campi e opzioni che esploreremo quando aggiorneremo questa classe man mano che la nostra app si evolve, ma questa è le necessità di base della creazione di un'app per pubblicare un po 'di testo. Tuttavia, questo modello non funzionerà da solo. Come descritto in precedenza, avremo bisogno di una vista personalizzata e un modello URL personalizzato per far funzionare questo modello e avremo anche bisogno di una forma insieme a un modello. Esploriamo prima il modulo. Per definire un modulo, modifica app/forms.py con nano e aggiungi le seguenti righe. Avremo bisogno di due importazioni, della nostra classe di forme e del modello che abbiamo creato (feed.models.post), una definizione di classe simile al modello e un campo insieme a una sottoclasse chiamata meta che definirà il modello interagisce con. Il modulo può anche avere una funzione di inizializzazione che la imposta in base alle informazioni nella richiesta, nel modello o in altro modo, lo esploreremo in seguito. Le forme del modello sono così utili perché possono creare un modello o anche modificare un modello,Quindi li useremo per entrambi. Definiamo uno in forms.py

from django import forms
from feed.models import Post

class PostForm(forms.ModelForm):
    text = forms.CharField(widget=forms.Textarea)
    class Meta:
        model = Post
        fields = ('text',)
Questa è le basi di come sono una forma e un modello. Questo modulo del modello può essere utilizzato per istanziare o modificare un post, modificando il testo che contiene. Verreremo a integrare questo modulo in una vista dopo. Innanzitutto, facciamo le migrazioni e migriamo il database in modo che il nostro codice possa interagire con il modello quando viene eseguito. Per fare ciò, esegui i seguenti comandi:

python manage.py makemigrations
python manage.py migrate
Questo richiederà un minuto per essere eseguito, ma una volta che lo farà, ti permetterà di accedere al modello nelle viste, nel middleware o in qualsiasi altra parte del software. Continuiamo facendo una vista in cui possiamo vedere il nostro modello. Modifica feed/views.py e aggiungi il seguente codice, come notato. Non dovrai aggiungere nulla dopo il segno #, quel codice è commenti utilizzati per indicare informazioni sul codice. Inizieremo importando il nostro modello nelle viste e aggiungendolo a un contesto in cui possiamo renderlo in un modello come elenco per la visualizzazione. Successivamente, aggiungeremo un modello in cui possiamo rendere il modulo e il modello con un pulsante per creare un nuovo oggetto in base al modello e pubblicarlo sul server. Sembra complicato, quindi prendiamolo passo dopo passo. Prima di finire la vista, creiamo un modello che rende il modello e assicuramo di poterlo vedere creando un nuovo post nella shell. Ecco come dovrebbe apparire quella visione:

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

def feed(request):
    posts = Post.objects.all() # Interroga tutti i post nel database finora
    return render(request, 'feed/feed.html', {
        'posts': posts,
    })
Tutto questo sembra piuttosto semplice fino a quando non arriviamo in fondo. Render, il valore restituito dalla funzione anziché in una risposta HTTP come l'esempio precedente, prende sempre una richiesta come primo input, accetta un contesto (in questo caso i post nel database), che ora può essere reso nel modello e restituisce il modello definito nella funzione. Il modello sarà un documento HTML con un po 'di lingua chiamata Jinja2, che rende Python Informazioni nell'HTML. Per iniziare a creare modelli, fai due directory in feed.

mkdir feed/templates
mkdir feed/templates/feed
Quindi, modifica un modello nella directory sopra, feed/modelli/feed e aggiungi il codice per questo esempio. Diamo un'occhiata al modello per questo esempio.
 
<!doctype HTML>
<html>
<body>
<legend>Feed</legend>
<hr>
{% for post in posts %}
<p>{{ post.text }}</p>
{% endfor %}
</body>
</html>
 
Questo è un modello molto semplice. Definisce l'apertura e la chiusura dei tag HTML, un tag tipo di documento, un tag del corpo con un titolo di legenda, un tag di interruzione che aggiunge una piccola riga sullo schermo e un ciclo che rende ogni post nell'elenco dei post come paragrafo in il modello. Questo è tutto ciò che serve per rendere post, ma non ce ne sono ancora nel database. Creiamo un po 'con il guscio. Possiamo eseguire la shell con manage.py

python manage.py shell
Ora, importiamo il nostro modello post

from feed.models import Post
Successivamente, creeremo un semplice post con una stringa ed escimo nella shell. La stringa può essere qualsiasi cosa, finché è un testo valido.

Post.objects.create(text='hello world')
exit()
Infine, dovremo aggiungere un modello URL al nostro feed. Poiché la nostra app di feed utilizzerà più URL e vogliamo mantenere piccole dimensioni di file, creiamo un URLS.PY locale nella nostra app di feed che assomiglia a questo:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.feed, name='feed'),
]
Dovremo anche modificare l'URLS.PY nell'app di base, qualunque cosa abbiamo deciso di chiamarlo, questa è stata la prima directory che abbiamo creato. Modifica app/app.py e aggiungi quanto segue ai modelli URL

from django.urls import include # in alto

urlpatterns = [
    # ... codice precedente qui
    path('feed/', include(('feed.urls'), namespace='feed')),
]
Ora, quando eseguiamo il server con Python Manage.py Runserver, vedremo la pagina che abbiamo creato perché abbiamo il modello, la vista e il modello, nonché il modello URL, insieme agli elementi nel database. Successivamente, implementiamo il modulo che abbiamo creato e iniziamo a creare i nostri post. Ma prima di scrivere troppo codice, facciamo un backup usando lo script che abbiamo scritto in precedenza, backup. Esegui questo script nella shell, attendi alcuni momenti e tutto il codice sarà eseguito il backup del nostro repository Git.

backup
L'implementazione della forma è relativamente semplice. Importeremo il nostro modulo, aggiungiamo un gestore di richieste di post alla vista e salveremo il post nel database prima di reindirizzare alla stessa vista. Possiamo utilizzare la funzione di reindirizzamento che abbiamo già importato e un'altra funzione chiamata reverse per ottenere l'URL per il modello di vista. Lo interrogheremo con la stringa "feed: feed" perché lo spazio dei nomi del modello incluso è feed e la vista è anche chiamata feed.

from feed.forms import PostForm

def feed(request):
    posts = Post.objects.all() # Interroga tutti i post nel database finora
    if request.method == 'POST': # Gestire la richiesta post
        form = PostForm(request.POST) # Crea un'istanza del modulo e salva i dati su di esso
        if form.is_valid(): # Convalida la forma
            form.save() # Salva il nuovo oggetto
        return redirect(reverse('feed:feed')) # Reindirizza allo stesso URL con una richiesta GET
    return render(request, 'feed/feed.html', {
        'form': PostForm(), # Assicurati di passare la forma nel contesto in modo da poterlo renderlo.
        'posts': posts,
    })
Ora dovremo aggiornare il modello per tenere conto del nuovo modulo. Possiamo farlo usando il
Tag in HTML e rendendo il modulo nel modello HTML con un pulsante di invio. Avremo anche bisogno di un token CSRF, un token che impedisce ai siti esterni di pubblicare nel modulo senza prima caricare una pagina.
 
<!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>
 
Abbattiamo questo. C'è una nuova classe di moduli, un token, il modulo stesso e un pulsante di invio. Abbastanza semplice, ma quando lo diamo un'occhiata, potremmo volerlo far sembrare migliore. Funziona, possiamo pubblicare nuovi post con il modulo e ora vengono salvati nel database. Ci sono alcune cose in corso qui. Usiamo i tag HTML per dichiarare che il documento è un documento HTML, utilizziamo un tag modello ({ % ... %}) per rendere il token per il modulo e un altro, {{…}} per rendere il modulo. Abbiamo anche un ciclo per rendere il testo usando tag a blocchi e un tag modello. I tag a blocchi sono davvero importanti perché possiamo definire come vengono rese le sezioni del modello e i tag del modello sono la base di come inseriamo le variabili nel nostro codice. Ora dobbiamo rendere la nostra app migliore, perché per ora sembra davvero semplice. Possiamo farlo usando CSS, in linea o in classi legate a ciascun oggetto nel documento. CSS è davvero bello perché dice tutto sulla pagina come dovrebbe apparire,E può renderlo davvero bello. Ci sono alcune biblioteche che possono farlo, ma il mio personale va a Bootstrap. Bootstrap può essere scaricato dal loro sito Web,Getbootstrap.com/. Una volta lì, premere il pulsante per leggere i documenti di installazione e copiare il codice dalla sezione Includi tramite CDN. Avrai bisogno di questo codice nella parte superiore del tuo documento HTML, in un tag chiamato Head. Inoltre, andiamo avanti e creiamo un modello di base in modo da non dover ricreare questi collegamenti in ogni modello. Crea una nuova directory chiamata modelli con modelli MKDIR, quindi modifica modelli/base.html. Dovrebbe assomigliare a questo:
 
<!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>
 
Assicurati di copiare i file CSS e JavaScript, .css e .JS, perché avremo bisogno del JavaScript per rendere il nostro sito più funzionale in futuro. Ora torniamo alla shell bash ed eseguiamo un comando rapido. Ricorda, se hai mai bisogno di accedere all'ambiente virtuale, digita la sorgente VENV/Bin/Activate. Questo ti permetterà di installare pacchetti Python localmente in un modo che consente a Django di accedervi. Per dare le nostre forme generate dalle classi Django Bootstrap, useremo un pacchetto Python chiamato Crispy Forms. Possiamo scaricarlo con il seguente comando

pip install django-crispy-forms
Una volta installato, aggiungilo a impostazioni

INSTALLED_APPS = [
    # ... codice precedente qui
    'crispy_forms',
]
Ora, nel nostro modello di alimentazione, possiamo rimuovere alcune cose. Rimuoviamo l'inizio e la fine del documento e sostituiamolo con eredità dal nostro modello di base, utilizzando Extends e la definizione del blocco. Inoltre, aggiungeremo un'importazione di filtro modello con carico e filtro modello al modulo. Infine, aggiungiamo una classe bootstrap al pulsante sul modulo per renderlo più simile a un pulsante. Dovrebbe sembrare così:
 
{% 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 %}
 
Bellissimo! È già un po 'di codice. Successivamente, dovremmo testarlo e assicurarci di poter vedere che tutto sembra bello e anche assicurati che tutto funzioni correttamente. Esegui il server secondo le istruzioni precedenti e assicurati che il sito appaia e funzioni bene. Ottimo lavoro! Sei pronto per passare al passaggio successivo, in cui aggiungeremo funzionalità di accesso utente utilizzando URL, forme, viste e modelli simili. Il modello di base è importante e continueremo a modificarlo e apportare modifiche in base alle necessità, ma per ora concentriamoci sul rendere il nostro sito più sicuro, consentendo agli utenti di accedere con un nome utente e un passcode, e infine informazioni ancora più importanti che informazioni che Ti aiuterà a mantenere la tua app sicura e il tuo account accessibile solo da te. Per fare ciò, dovremo utilizzare il modello utente integrato in Django. Il modello utente è un modello di database, come il nostro post, che può essere reso per accedere a un utente nel sito Web. In futuro, prima di distribuire il sito su Internet, lo faremoEstendi questo modello con altri modelli attribuiti ad esso e crea ulteriori misure di sicurezza per il login resistenti al phishing. Inizieremo utilizzando alcuni moduli di accesso integrati che Django fornisce. Innanzitutto, creiamo una nuova app che useremo per rendere i modelli e le viste per la pagina di accesso di base. Creeremo anche altre app per rappresentare le continue sfide di accesso al fine di garantire l'app, tra cui un pincode, il riconoscimento facciale, la comunicazione vicino al campo, i dispositivi esterni, l'autenticazione multi -fattore e il riconoscimento delle impronte digitali. Abbiamo già parlato dell'avvio di un'app. Dalla nostra directory, all'interno dell'ambiente virtuale, passano gestite.py questi

python manage.py startapp users
Ora dovremmo avere una directory per la nuova app. Iniziamo creando una vista in quella directory che corrisponde al login dell'utente. Django ha visualizzazioni integrate per gli accessi degli utenti, ma questi non saranno adatti a noi perché abbiamo bisogno di una vista personalizzata, che è preferibilmente fatta con una definizione. In questa visione, inizieremo controllando una richiesta di post, pass richiesta.post a unaformio di login importato da Django, autenticare l'account utente e accedere all'utente prima di reindirizzarli alla nostra app di feed. In utenti/views.py, aggiungi il seguente codice

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'] # Ottieni il nome utente e la password dalla richiesta post
        password = request.POST['password'] # Autentica l'utente
        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()})
Questo è tutto ciò di cui hai bisogno per una vista di accesso di base. Ora, creiamo un modulo per la vista estendendo il modello di base. Inizieremo creando una nuova directory per i modelli nella cartella degli utenti.

mkdir users/templates
mkdir users/templates/users
Ora dovremmo essere in grado di modificare utenti/modelli/utenti/login.html. Mentre ci siamo, creeremo un modello per consentire anche all'utente di iscriversi.

nano users/templates/users/login.html
Ora, nel modello,
 
{% 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 %}
 
Questa è le basi di un modello di accesso. È davvero proprio come l'altro modello nella struttura, ma sembra un po 'diverso quando è reso. Possiamo copiare questo codice per creare un altro modello molto simile chiamato register.html, dove cambieremo la formulazione e useremo un nuovo modulo che costruiamo. Facciamo prima il modello. Modifica utenti/modelli/utenti/register.html e aggiungi il seguente codice:
 
{% 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 %}
 
Ora, costruiamo un modulo per la nostra registrazione degli utenti e torniamo alle viste prima di aggiornare i nostri accessi degli utenti con un modello. Faremo questo modulo di base per cominciare, ma incorporeremo maggiori dettagli e funzionalità di sicurezza come accordi e captcha in futuro. Modifica i moduli con nano utenti/forms.py e aggiungi il seguente codice.

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']
Quindi abbiamo un'altra forma qui, che funziona in modo abbastanza semplicemente. È un modulo di registro utente con nome utente, e -mail e password, nonché un campo di conferma della password. Si noti che questo modulo non estende i moduli moduli. Classe delle forme, è una forma modello, il che significa che ha un meta. Un campo è definito allo stesso modo e la meta di classe definisce il modello che il modulo corrisponde al resto delle informazioni che verranno scritte nel modulo. La maggior parte di questo esiste già nella formazione utente incorporata di Django, quindi lo useremo come base per la classe (passata nella parentesi). Successivamente, esamineremo la vista per registrare un utente, ora che abbiamo un modulo e un modello. Questo è un modelform, proprio come quello nella nuova visualizzazione dei post. Modifica utenti/views.py e aggiungi il seguente codice:

# ... importi
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})
Questo è tutto ciò di cui abbiamo bisogno per la registrazione di un utente, ma dovremmo avere maggiori informazioni. Vogliamo sapere il tempo che l'utente si è registrato, a che ora sono stati per l'ultimo sul sito, alcune informazioni su di loro, come una biografia, un fuso orario, ecc. Inoltre, dovremo aggiornare il nostro modello di feed, post, per tenere conto dell'utente Modelli e attributi post a ciascun utente. Per farlo, aggiorneremo i modelli.py in entrambe le app. Cominciamo modificando il modello di feed. Dovrebbe sembrare così ora:

from django.db import models # ... importi
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') # Aggiungi questa riga
    text = models.TextField(default='')
Presta attenzione alla seconda riga che è stata aggiunta al file. Questa è una chiave esterna, che attribuirà ogni post a un singolo utente per post, in modo da poter assicurarci di salvare i post su una base utente per utente e nessun post può essere fatto senza attribuirlo a un utente. Definiamo questa chiave esterna con la classe che rappresenta, un argomento di eliminazione per garantire che i post siano eliminati con utenti, argomenti null e vuoti per assicurarsi di poter rimuovere l'utente se necessario e di accogliere per la mancanza di un utente già Creato e un nome correlato, che possiamo utilizzare per fare riferimento agli oggetti post che l'utente crea. Questo nome correlato, a differenza di Post.Author, l'autore del post, ci dà l'utente che ha pubblicato il post stesso. Ora possiamo ottenere i post che un utente viene pubblicato mediante user.posts.all () o autore.posts.all (). Ora, rendiamo i nostri accessi più resilienti. Possiamo già rendere il nostro sito molto meno vulnerabile al phishing semplicemente limitando il numero di volte in cui consentiremo un accesso alSito, questo è abbastanza facile. Iniziamo anche a archiviare alcune informazioni su ciascun utente prima che continuiamo a sviluppare la nostra app. Modifica degli utenti/modelli.py, aggiungere quanto segue

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='')
Si noti che questo modello è abbastanza simile al modello post. Abbiamo un'importazione aggiuntiva, il fuso orario, che ci consentirà di impostare le impostazioni predefinite sui campi datetime e abbiamo anche un personaggio e un campo di testo come il post. L'uso di tutti questi timestamp ci aiuta a proteggere il sito e comprenderne l'uso e i campi di testo ci consentono di fornire informazioni su ciascun utente o autore, sul sito Web. L'ONETOOnefield dovrebbe essere l'unica considerazione minore, si comporta esattamente come un Foreginkey ma con solo uno per modello successivo. In questo modo, l'utente ha un solo profilo, mentre può avere molti post. Ora, miglioriamo le nostre visualizzazioni di accesso e registriamo per tenere conto del profilo. Innanzitutto, modifica utenti/views.py e concentrati sulla vista del registro:

# ... importi
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) # Assicurati di aggiungere questa riga, per creare un profilo per l'utente
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Questo crea semplicemente un profilo per l'utente, senza compilare nessuna delle informazioni. Ora, vogliamo assicurarci che l'account utente non possa essere effettuato troppo spesso, o almeno le password non possono essere provate troppo spesso, quindi aggiorniamo la vista di accesso.

# ... importi
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(): # Si noti che ora controlliamo se l'utente può accedere
            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: # Se l'accesso non ha avuto successo,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Questa è la parte in cui aggiorniamo il profilo degli utenti
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Quindi non possono accedere di nuovo per alcuni secondi
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Questo è il fondamentale di base per la sicurezza. Assicurati che il sito non sia vulnerabile a qualcuno che prova semplicemente ogni possibile combinazione di password, o anche alcune di esse contemporaneamente. Questo non sarà frustrante per l'utente normale che conosce il proprio passcode e accederà solo ad alcuni dispositivi, ma manterrà numerosi robot di phishing fuori dall'app. Si noti che abbiamo aggiunto un'istruzione IF con una variabile, CAN_LOGIN, che dovrebbe essere un tempo in passato e aggiornarla con ogni accesso senza successo usando lo stesso nome utente. In questo modo, un utente dannoso non sarà in grado di indovinare una password da nessuna parte vicino. Anche il numero di secondi in DateTime.timedelta () può essere aggiornato e il sito Web sarà più resiliente ma leggermente meno utilizzabile con più secondi. Consiglio 15 di cominciare. Ricorda, abbiamo costruito uno script di backup per salvare il nostro lavoro, quindi andiamo avanti e eseguiamo il backup di ciò che abbiamo finora per assicurarci di salvare tutto. Esegui il comando:

sudo backup
Ancora una volta, questo salverà il tuo lavoro finora. Consiglio di eseguire backup frequenti per salvare il tuo lavoro e potresti persino voler eseguire automaticamente un lavoro di backup. Puoi farlo usando un'utilità UNIX chiamata Cron. Per attivare questa utilità, eseguire il seguente comando e inserire la password:

sudo crontab -e
Se non hai già selezionato l'opzione 1 per Nano, l'editor di testo che dovresti già avere familiarità e scorrere fino alla parte inferiore del file usando i tasti freccia. Aggiungi la seguente riga:

0 * * * * sudo backup
Cron usa il minuto formato, ora, giorno del mese, mese, giorno della settimana, in cui un * o un numero rappresenta quando eseguire il comando. Usando uno 0 per il minuto e * per il resto delle opzioni, possiamo eseguire un comando al primo minuto di ogni ora all'inizio del minuto. Questo ci consente di eseguire il backup del codice automaticamente. Tutti i lavori di Cron se eseguiti con sudo esegui come root, quindi non dovremo digitare una password ogni ora. Per semplificare il backup del nostro codice senza utilizzare una password, disabilitiamo la password per il nostro comando di backup. Lo faremo eseguendo il seguente comando e inserendo una password:

sudo visudo
Ora, scorrere fino in fondo al file e aggiungere un'altra riga:

ALL ALL=NOPASSWD: /bin/backup
Questo ci consente di eseguire il comando "backup" come qualsiasi utente, senza una password. Il formato per questo è facile, basta prefissa la linea con "All = NOPASSWD:/bin/" e termina con il comando, ad esempio/bin/backup, che esiste in/usr/bin/. Ora, iniziamo a lavorare con e -mail. L'e -mail è davvero importante per i siti Web, perché è un modo per mantenere un sito Web più sicuro, verificare che gli utenti siano persone reali e persino prodotti o servizi di mercato ai clienti. Molte persone che frequentano Internet controllano quotidianamente la loro e -mail e ricevono tutti i tipi di e -mail di marketing su prodotti e servizi a cui sono interessati. Ci sono alcune opzioni quando si tratta di abilitare e -mail su un sito Web Django e sei il benvenuto a scegliere Qualunque cosa funzioni meglio per te. Innanzitutto, puoi pagare per un servizio di posta elettronica che ti consente di inviare e -mail dal tuo dominio e richiede un codice minimo. Ci sono molti servizi che offrono questo, come Google Workspace, SendinBlue, Mailgun e altro ancora. Altrimenti, sei ben edileIl tuo servizio di posta elettronica all'interno del tuo server da zero. Consiglio questa opzione, anche se è più codice e potrebbe richiedere un hosting speciale. Non sarai in grado di avviare un server di posta dal tuo computer di casa molto probabilmente, quindi andiamo avanti ed esaminiamo la configurazione e il codice per inviare e -mail prima di avviare un server nel cloud e creare il nostro server di posta all'interno. Innanzitutto, modifica impostazione.py con quanto segue

nano app/settings.py
Dove l'app è il nome dell'app creata con StartApp. Aggiungi le seguenti righe:

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)
Assicurati di modificarli quando sei pronto a distribuire la tua app, lo rivisiteremo in seguito. L'impostazione di email_address dovrebbe essere l'e -mail da cui si desidera inviare e la password (email_host_password) dovrebbe essere impostata sulla password che genera per il server. Carico la password da un file di configurazione per tenerla fuori dal codice utilizzando la seguente logica, al di sopra di queste righe in impostazione.py:

import os
import json
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Quindi, ho impostato un file JSON con la configurazione in /etc/config.json usando Nano come segue. Per modificare il file:

sudo nano /etc/config.json
Aggiungi le seguenti righe:

{
	“EMAIL_HOST_PASSWORD”: “<some password here>”
}
Continueremo a modificare il file di configurazione e aggiungere tutte le password e le chiavi che useremo nell'app. Per ora, esaminiamo rapidamente come inviare e -mail utilizzando Python. Innanzitutto, creiamo un modello per un'e -mail di verifica che possiamo inviare ai nostri utenti e inserirlo nella directory dei modelli utente. Questo modello sarà scritto in HTML.

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

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

<p>The link will expire in 30 minutes.</p>
<p>If you have not requested a verification email you can simply ignore this email.</p>
<p>See you there,</p>
<p>Daisy</p>
 
Questa e -mail è abbastanza semplice. Prende un contesto di un utente, l'URL di base per il sito e un ID utente e un token che vengono utilizzati per verificare l'e -mail dell'utente. Assicurati di definire l'URL di base in impostazioni.py prima di scrivere un codice Python per rendere il modello. Vai avanti e aggiungi le seguenti righe all'app/impostazione.py, vicino all'inizio.

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

BASE_URL = PROTOCOL + '://' + DOMAIN
Alla fine, quando il tuo sito è pronto per Internet e lo distribuisci, vorrai definire il tuo dominio come nome di dominio che acquisti per rappresentare il sito. Questo è il nome che digiterà nella barra navic per accedere al tuo sito. Per ora, puoi lasciare il dominio in bianco o utilizzare un segnaposto. Ti consigliamo inoltre di cambiare il SIT_NAME in un nome che desideri dare al tuo sito, di scelta. Prima di inviare e -mail, creiamo un generatore di token in modo da poter avere un token di attivazione dell'account che non scade mai. Possiamo farlo costruendo e importando un token di attivazione dell'account che assomiglia al seguente. Modifica il file:

nano users/tokens.py
Aggiungi il seguente codice:

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()
Questo generatore di token di base genera un token che possiamo inviare all'utente in un URL e l'utente può utilizzare per verificare la propria e -mail e attivare il proprio account. Quindi, vediamo come inviare un'e -mail. Utilizzando Nano, Modifica utenti/email.py.

nano users/email.py
L'invio dell'e -mail HTML di verifica sarà simile a questa:

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)
Questo è abbastanza semplice. Importiamo le funzioni di cui abbiamo bisogno per inviare l'e -mail, rendere l'e -mail con modelli e le nostre impostazioni, quindi definiamo l'e -mail con il nome del modello e la inviamo all'utente utilizzando una funzione. Noterai che non abbiamo definito la funzione per inviare la posta, send_html_email, quindi scriviamo questo sotto il codice che abbiamo già aggiunto agli utenti/email.py

def send_html_email(user, mail_subject, html_message):
    to_email = user.email
    username = user.username
    if to_email == '':
        return None
    unsub_link = settings.BASE_URL + user.profile.create_unsubscribe_link()
    html_message = html_message + "<p><a href=\"" + unsub_link +  "\" + title=\"Unsubscribe from " + settings.SITE_NAME + " emails\">Unsubscribe</a></p></body></html>"
    msg = EmailMultiAlternatives(mail_subject, strip_tags(html_message), settings.DEFAULT_FROM_EMAIL, [to_email], headers={'List-Unsubscribe' : '<' + unsub_link + '>'},)
    msg.attach_alternative(html_message, "text/html")
    profile = user.profile
    try:
        msg.send(fail_silently=False)
        if not profile.email_valid:
            profile.email_valid=True
            profile.save()
    except:
        profile.email_valid=False
        profile.save()
Questo è un po 'più complesso e non siamo ancora pronti a eseguire tutto questo codice. Si noti che stiamo definendo un Unsub_Link, il collegamento che l'utente può utilizzare per annullare l'iscrizione alle nostre e -mail. Questo è importante, perché gli utenti dovranno essere in grado di rinunciare alle nostre e -mail a meno che non possano vederle, in qualsiasi momento. Aggiungiamo anche un'alternativa di testo al nostro messaggio, che è il messaggio HTML spogliato dei tag HTML. Infine, controlliamo se l'e -mail inviata e, in caso contrario, segniamo il profilo dell'utente che la loro e -mail non è valida. Ritorniamo ai modelli utente in modo da poter farlo funzionare tutto. Dobbiamo definire una funzione per generare un collegamento a annullare l'iscrizione e definire un campo booleano per contrassegnare che l'e -mail dell'utente non è valida. Innanzitutto, aggiungi le seguenti importazioni nella parte superiore degli utenti/modelli.py

nano users/models.py

# ...
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
from django.urls import reverse
Successivamente, aggiungiamo funzioni al modello utente per creare il token e controllare il token utilizzato per attivare l'e -mail, nonché il campo per salvare se l'utente sta ricevendo correttamente la propria posta. In utenti/modelli.py di nuovo, aggiungi il seguente codice alla fine del modello (codice rientrato)

# ...
    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) # Valido per 30 giorni
        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,})
Questo è abbastanza semplice, utilizziamo un timestampsigner, che è uno strumento di crittografia di base, per creare un token che scadrà dopo un certo periodo di tempo e utilizziamo anche un'altra funzione per verificare se è valido. Usiamo questi token due volte, una volta per verificare l'e -mail e una volta per un link all'iscrizione. Ora che abbiamo questi, l'ultimo lavoro che dovremo fare è nelle opinioni. All'interno degli utenti/Views.py, aggiungiamo visualizzazioni per verificare l'indirizzo e -mail e annullare l'iscrizione.

nano users/views.py
Innanzitutto, aggiungi le seguenti importazioni. Ho lanciato qualche extra in modo da non dover importare più articoli più tardi.

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 # Assicurati di importare la funzione di invio dell'email di verifica
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
Potresti già avere alcune di queste importazioni, ma non fa male ripeterle. Avrai bisogno di importare la funzione di invio dell'email di verifica, nonché account_activation_token da utenti.tokens, tra le altre importazioni. Ora, in fondo al file, aggiungi il seguente codice:

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)):
        # annullare l'iscrizione
        profile = user.profile
        profile.subscribed = False
        profile.save()
        return render(request, 'users/unsubscribe.html')
    # Altrimenti reindirizza alla pagina di accesso
    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 (richiesta, utente)
        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})
Questo è un sacco di codice. Abbattiamolo. La prima funzione, pulita e semplice, annulla l'iscrizione all'utente dalla mailing list. La seconda funzione attiva la loro e -mail e noterai che ho aggiunto una funzione commentata, Sendwelcomemail. Sei il benvenuto a utilizzare un modello di posta elettronica e la definizione della funzione per inviare un'e -mail di benvenuto, non l'ho ancora fatto. L'ultima funzione che ho lanciato è importante, perché le e -mail di attivazione scadono. Pertanto, dovremo nuovamente nuovamente l'e -mail di attivazione. Possiamo utilizzare un modulo di base per questo e chiamare la funzione per inviare l'e -mail di verifica. Prima di farlo, assicuriamoci che venga inviato in primo luogo, aggiungendo una chiamata di funzione alla vista del registro. Aggiungi questa riga poco prima del reindirizzamento nella vista Register, DEF Register, in Users/Views.Py.

nano users/views.py

# ... (dopo) DEF Register (richiesta):
            send_verification_email(user)
# ... (prima) reindirizza (
Non è necessario aggiungere la prima e le ultime righe in quel frammento di codice, assicurati solo che la vista del registro invii l'e -mail di verifica all'utente. Dovrebbe assomigliare a questo:

# ... importi
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) # Assicurati di aggiungere questa riga!
            messages.success(request, 'Welcome to the app, {}.'.format(user.username))
    return render(request, 'users/register.html', {'form': UserRegisterForm})
Ora, dovremo aggiungere un modulo per nuovamente l'e -mail di attivazione. In utenti/forms.py, aggiungi il seguente modulo:

# ... (importi)
class ResendActivationEmailForm(forms.Form):
    email = forms.EmailField(required=True)
Avremo anche bisogno di un modello corrispondente a questo modulo di attivazione e -mail di Resend. Aggiungiamo questo modello in. Modifica il file:

nano users/templates/users/resend_activation.html
Quindi, aggiungi il seguente codice al file.

{% 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 %}
Accidenti, è molto! Ora, quando distribuiamo il codice sul nostro server, saremo in grado di inviare e -mail HTML e attivare gli account utente con un clic nell'e -mail. Potremmo anche voler inviare una semplice e -mail di benvenuto, quindi vediamo come farlo. Di nuovo in utenti/email.py, aggiungi il seguente codice:

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)
Inoltre, avremo bisogno di un modello per rendere tutte queste informazioni. Sul mio sito Web, il modello sembra sotto, ma sei invitato a formattarlo come preferisci.
 
<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>
 
Nota che non disponiamo di un corpo di chiusura o tag HTML, perché li aggiungiamo quando aggiungiamo il link all'iscrizione HTML. Questi sono importanti, ma non vogliamo definirli due volte. Allora cosa ci aspetta? Abbiamo fatto molta strada. Davvero, dovremmo essere pronti a distribuire il sito su un server. Possiamo aggiungere il decoratore @login_required e rendere sicure le nostre viste, prendere le iscrizioni utente, inviare e -mail conformi e informazioni sulla cache, che è la base di ciò che un sito Web deve fare per rimanere pertinente. Aggiungeremo alcune funzionalità utili e quindi creeremo una base per la distribuzione del nostro codice su un server remoto, la configurazione di un server di posta, la configurazione del dominio e i filtri per rendere il nostro sito sicuro e appropriato. Avremo anche bisogno di una visualizzazione reimpostazione della password, quindi aggiungiamola molto rapidamente. La visualizzazione reimpostazione della password integrata di Django è rotta in alcune funzioni, ma esamineremo come scrivere la nostra vista, il modello di posta elettronica, i moduli e i modelli URL. Ecco come appare la vista, in utenti/views.py

# ... importi
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)
Questo modulo è integrato su Django, ma avremo bisogno di un modello per confermare il reimpostazione della password, utenti/modelli/utenti/password_reset_confirm.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Reset Password</button>
            </div>
        </form>
{% endblock content %}
 
Abbiamo anche un modello per inviare un'e -mail di reimpostazione della password, con un modulo semplice, in utenti/modelli/utenti/password_reset.html
 
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
        <form method="POST">
            {% csrf_token %}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Reset Password</legend>
                {{ form|crispy }}
            </fieldset>
            <div class="form-group">
                <button class="btn btn-outline-info" type="submit">Request Password Reset</button>
            </div>
        </form>
{% endblock content %}
 
Il modello per l'e -mail stessa è semplice, è un file HTML di base che rende un link per reimpostare la password, in utenti/modelli/utenti/password_reset_email.html. Django interpreterà automaticamente questo file.
 
<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>
 
Avremo anche bisogno di altri due modelli. Il primo è confermare che l'e -mail è stata inviata. Le opinioni per questi sono già a Django, quindi dobbiamo solo affrontarle negli URLS.PY. Questo modello si trova su utenti/modelli/utenti/password_reset_done.html
 
{% extends 'base.html' %}
{% block content %}
  <div class="media-body">
    <div class="alert alert-info">
        An email has been sent with instructions to reset your password.
    </div>
  </div>
{% endblock content %}
 
E infine, per confermare che il reimpostazione della password è completato, utenti/modelli/utenti/password_reset_complete.html
 
{% extends 'base.html' %}
{% block content %}
 <div class="media-body">
    <div class="alert alert-info">
        Your password has been set.
    </div>
    <a href="{% url 'users:login' %}">Sign In Here</a>
  </div>
{% endblock content %}
 
Ora abbiamo bisogno di motivi URL per queste viste. In utenti/urls.py, aggiungi i seguenti schemi URL:

urlpatterns = [
    # ... URL precedenti qui
    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'),
]
Quattro modelli, è molto! Ma ora possiamo essere sicuri di essere in grado di ripristinare la password dell'utente ogni volta che è necessario, tutto dal browser Web. Capisco che questo è un sacco di codice. Se ti sembra un po 'sopra la testa, va bene. Migliorerai, la tua comprensione migliorerà e diventerai molto più competente con il codice molto presto. Se sei totalmente perso, ti consiglio di tornare su questo software in seguito dopo aver lavorato su un ritmo autonomo a codificare il corso online. Questi sono di solito liberi di iniziare e ti guideranno attraverso tutto ciò di cui hai bisogno per avere successo quando torni a questo progetto. Se ti senti come se fossi pronto per continuare, leggere, successivamente, copriremo la distribuzione del tuo codice su un server remoto e la configurazione di un server di posta, oltre ad automatizzare la distribuzione utilizzando Bash in modo da poter sempre impostare un nuovo progetto con Alcuni semplici comandi. L'ultima cosa che dobbiamo fare prima di distribuire su un server remoto è rendere il nostro sito un po 'più sicuro. TuSi noti che la vista di accesso prende solo un nome utente e una password e non esiste un'autenticazione multi -fattore o un codice temporale. Questa è una soluzione semplice e, con lo stesso codice, possiamo far inviare al nostro sito i messaggi di testo e persino essere sensibili ai messaggi di testo inviati al server. Per iniziare, torneremo nei modelli utente e aggiungeremo un firmatario del timestamp che rappresenterà ogni accesso. Aggiungeremo anche un identificatore univoco e rotante al modello utente che verrà utilizzato per aggiungere ulteriore sicurezza al nostro accesso. Modifica dei modelli utente, utenti/modelli.py, aggiungi quanto segue

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
# Assicurati di importare UUID, TIMESTAMP SIGNER e URL Generator (Reverse)
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='')
    # Aggiungi questo codice qui
    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)

    # E aggiungi questa funzione
    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) # Valido per 3 minuti
        except (BadSignature, SignatureExpired):
            return False
        return True
Assicurati che i tuoi utenti/models.py abbiano questo modo, oltre ai commenti (codice sulle righe con #). Abbattere questo, è semplice. Abbiamo alcune importazioni, un timestampsigner che è un'utilità crittografica che può generare un codice sicuro e verificarlo per assicurarsi che sia valido, sia stato utilizzato solo una volta e non più vecchio di un certo numero di secondi. Usiamo anche un UUID, che è un identificatore univoco che identifica il nostro utente nella firma del token e nell'URL in cui il token viene inviato all'utente. Useremo questa crittografia di base per costruire una vista di autenticazione a due fattori. Prima di fare qualsiasi altra cosa, eseguiamo le migrazioni in modo che i nostri modelli utente vengano aggiornati. Nella directory con manage.py, eseguire i seguenti comandi per realizzare e completare le migrazioni.

source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Questo è importante perché ogni volta che apportiamo modifiche ai modelli, dovremo creare le tabelle e aggiornare il database con le impostazioni predefinite prima di poter effettivamente utilizzare i modelli. Successivamente, improvvisiamo la nostra vista di accesso per reindirizzare a una vista di autenticazione secondaria. Negli utenti/Views.py, rimuovi la funzione di accesso e reindirizza all'URL che abbiamo appena generato nei modelli utente.

# ... importi

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(): # Si noti che ora controlliamo se l'utente può accedere
            # Rimuovi la funzione Auth_login che era qui
            messages.success(request, 'Your password was accepted. Please continue.')
            if user.profile.mfa_enabled:
                return redirect(user.profile.create_auth_url()) # Nota che reindirizziamo a un nuovo URL qui
            else: # Se l'utente non utilizza l'autenticazione a più fattori, accedili.
                auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend')
                return redirect('feed:feed')
        else: # Se l'accesso non ha avuto successo,
            messages.warning(request, 'Username or password incorrect. Please try again.')
            user = User.objects.filter(username=username).first() # Questa è la parte in cui aggiorniamo il profilo degli utenti
            if user: 
                profile = user.profile
                profile.can_login = timezone.now() + datetime.timedelta(seconds=15) # Quindi non possono accedere di nuovo per alcuni secondi
                profile.save()
    return render(request, 'users/login.html', {'form': AuthenticationForm()})
Quindi questo è piuttosto semplice, ora abbiamo un modo per reindirizzare alla vista di autenticazione a due fattori quando la creiamo. Abbiamo anche un fallback nel caso in cui l'utente non abbia aggiunto un numero di telefono. Aggiungeremo una vista di base per aggiungere presto un numero di telefono e accedere presto con un messaggio di testo. Innanzitutto, abbiamo bisogno di un modo semplice per inviare un messaggio di testo dal nostro codice. Per fare ciò, possiamo scegliere tra un numero di API, ma la più semplice secondo me è Twilio. Offrono anche buoni prezzi per progetti più piccoli e sconti in blocco. Crea un account su TWIIO.com, compila alcuni dettagli sul tuo progetto, acquista un numero di telefono e copia le chiavi API su Settings.Py. Quindi, aggiungi questo codice con un nuovo file, utenti/sms.py.

nano users/sms.py

# Importa tutti i pacchetti necessari
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

# Questo codice invia il testo con 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())

# Una funzione di supporto per ottenere un numero con così tante cifre
def get_num_length(num, length):
    n = ''
    for x in range(length):
        n = n + str(num)
    return int(n)

# Invia il testo per verificare l'utente
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)))

# Invia a un utente qualsiasi testo con questa funzione
def send_user_text(user, text):
    send_text(user.profile.phone_number, text)

# Convalida il codice con questa funzione
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

# Convalida il tempo
def check_verification_time(user):
    result = user.profile.mfa_code_expires > timezone.now()
    return result
Assicurati di modificare le tue impostazioni in modo appropriato, aggiungendo queste linee con le chiavi:

# Assicurati di copiarli dal tuo dashboard Twilio
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 # Il numero di minuti la pagina TFA è attivo una volta istanziato
Innanzitutto, avremo bisogno di forme per le nostre visualizzazioni di autenticazione a due fattori. Modifica degli utenti/forms.py, aggiungere il seguente codice.

# ... importi
from django import forms

# Un modulo per entrare nel nostro numero di telefono
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

# Una forma per autenticarsi
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.'
    }
Successivamente, creiamo le visualizzazioni in utenti/views.py

# ... importi
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})
Avremo anche bisogno di modelli per entrambe queste opinioni. Aggiungiamo prima il modello MFA.

nano users/templates/users/mfa.html
Aggiungi questo codice HTML al modello
 
{% 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 %}
 
Questo è piuttosto autoesplicativo. Il modulo invia un codice o un codice vuoto e noterai nella visualizzazione inviamo il codice se riceviamo un codice vuoto. Quindi abbiamo solo due pulsanti di invio e in questo modo possiamo inviare il codice con entrambi i pulsanti. Successivamente, aggiungeremo un modulo semplice per aggiungere un numero di telefono.

nano users/templates/users/mfa_onboarding.html
Aggiungi il seguente HTML:
 
{% 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 %}
 
Questo modulo è molto più semplice, rende solo il modulo del numero di telefono che abbiamo creato e consente all'utente di aggiungere un numero di telefono. Questo sembra davvero buono! Finché tutto è impostato correttamente, dovremmo essere in grado di inviare messaggi e accedere all'utente con il loro numero di telefono non appena aggiungiamo i modelli URL. L'ultima cosa che dobbiamo impostare è una visualizzazione del profilo in modo da poter assicurarci che l'utente possa cambiare il loro numero di telefono senza essere effettuato l'accesso. Inoltre, alla fine vorremo aggiungere un'opzione "Stop to shit", in modo che l'utente possa SMS "Stop" per rinunciare ai futuri messaggi di testo. Aggiungiamo una vista profilo agli utenti/views.py. Questa vista aggiornerà la bio, l'e -mail, il nome utente e il numero di telefono dell'utente, oltre a consentirci di abilitare l'autenticazione multi -fattore. Innanzitutto, avremo bisogno di altri due moduli in utenti/forms.py

# ... importi
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']
Successivamente, possiamo creare una vista per utilizzare entrambe queste forme. Modifica utenti/views.py e aggiungi la vista.

# Aggiungi queste importazioni
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)
Avremo anche bisogno di un modello per questa visione.

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 %}
 
Noterai che questo è un modulo abbastanza semplice, ma ha un po 'di JavaScript che pubblica automaticamente il contenuto del modulo mentre vengono aggiornati. Questo è utile avere, quindi sei in grado di apportare modifiche senza dover premere invio ogni volta. Successivamente, abbiamo bisogno di URL che rappresentano tutte queste opinioni negli utenti degli URL. Modifica utenti/urls.py e aggiungi questo codice:

# ... codice precedente, importazioni
from django.urls import path
from . import views

app_name='users'

urlpatterns = [
# … Schemi URL che abbiamo inserito in precedenza, aggiungi le tre righe successive
    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'),
]
Ora è un buon momento per testare il nostro progetto. Ma prima, eseguiamo un altro backup.

backup
Ed eseguire il server. Prima di distribuire su un server Linux, è una buona idea abilitare l'autenticazione a due fattori sull'account. Lo faremo andando al nostro profilo URL,/utenti/profilo/e controllando la casella per abilitare l'autenticazione dopo aver inserito il nostro numero di telefono e quindi inviare il modulo.

python manage.py runserver localhost:8000
Visita la pagina Web andando sul tuo browser Web, in questo esempio sto usando Google Chrome e inserendo l'URL https: // localhost: 8000/account/profilo/ Sarai in grado di accedere se necessario e abilitare l'autenticazione a due fattori. Questo progetto ha bisogno di un server su cui eseguire in modo che possa davvero inviare posta. Ma prima, abbiamo bisogno di un modo per vedere errori. Noterai che se esegui il server in modalità debug, con impostazioni.debug uguale a true, il server mostra gli errori automaticamente. Per mostrare errori senza utilizzare la modalità di debug, che non è sicuro su un server di produzione, dovremmo aggiungere una vista per questo. Gli errori più importanti che dobbiamo essere in grado di gestire sono: Errore 500 - Un problema con il nostro codice Errore 404 - Una pagina che non è stata trovata (URL rotto) Errore 403 - Un errore negato dell'autorizzazione Aggiungiamo una nuova app per gestire questi errori, chiamati errori.

python manage.py startapp errors
Aggiungi questo a impostazione.py come abbiamo fatto prima, nell'impostazione installata_apps e inizia aggiungendo riferimenti ad alcune visualizzazioni in app/urls.py, dove l'app è il nome del tuo progetto Django.

handler404 = 'errors.views.handler404'
handler500 = 'errors.views.handler500'
handler403 = 'errors.views.handler403'
Questo è tutto ciò di cui abbiamo bisogno oltre alle viste di errore, ai modelli e un po 'di middleware. Definiamo quelli così:

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

# Crea le tue opinioni qui.
@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.'})
Quindi, definiamo il middleware per gestire questi errori. Faremo questo aggiungendo prima a Middleware_classes in impostazioni.py, con il nome del nostro middleware.

MIDDLEWARE_CLASSES = [
    # ... Middleware precedente
    'errors.middleware.ExceptionVerboseMiddleware,
]
Quindi, aggiungiamo il middleware.

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

_error = local()

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

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

def set_current_exception(exception):
    try:
        _error.value = exception
    except AttributeError:
        print('Attribute error setting exception.')
Aggiungiamo una funzione per ottenere l'attuale eccezione utilizzando un locale di threading, che ci aiuta a tracciare eventuali errori nel nostro codice. In termini di modelli, ne abbiamo solo bisogno, perché definiamo dinamicamente il titolo nella vista. Il modello deve solo rendere il titolo e "Trace", il nostro traceback di errore dal contesto.

nano errors/templates/errors/error.html
 
{% extends 'base.html' %}
{% block content %}
<h1>{{ pagetitle }}</h1>
<p>{{ trace }}</p>
{% endblock %}
 
Questo è il nostro modello più semplice di sempre, ma è così facile vedere gli errori nel nostro progetto. Quindi, disabilitiamo il debug nelle impostazioni.

nano app/settings.py
Trova questa riga in cui è impostata su True e cambiala in Falso

DEBUG = False
Vai avanti e esegui il backup dell'app ora. Siamo pronti a distribuire su un server Linux remoto e continuiamo ad aggiungere funzionalità da lì.

sudo backup
Prima di pubblicare questo codice su un server, dovremmo considerare che potrebbero esserci alcuni problemi con il codice. A seconda del caso, i siti che accettano le informazioni pubblicati avranno problemi con lo spam che viene pubblicato e difficoltà a rimuovere lo spam. Ciò non dovrebbe accadere immediatamente, ma se sta accadendo, esamineremo in seguito come moderare automaticamente lo spam sul sito e rendere più difficile per i robot accedere al sito, insieme a come disattivare gli account utente e verificare l'identità di un utente Una scansione del loro ID o una scansione biometrica, come un'impronta digitale o un riconoscimento facciale. Guardando l'esempio di autenticazione multi -fattore che abbiamo esaminato, in produzione, le cose possono essere diverse. Notare come stiamo limitando gli accessi e i token in scadenza. Se i robot accedono a un sito, l'autenticazione a due fattori può essere più difficile in quanto possono inserire codici contemporaneamente l'utente. Per combattere questo, usiamo un modello nei modelli utente, dichiarando come interagiamo con il sito quando lo siamoAutenticazione utilizzando l'autenticazione multi -fattore con un numero di telefono. Aggiungeremo anche un'opzione per l'autenticazione con e -mail. Inizia modificando i modelli utente con

nano users/models.py
Questo è l'aspetto del modello che stiamo aggiungendo. Non abbiamo bisogno di metodi, solo variabili per archiviare un ID, l'utente, il timestamp, la scadenza, la lunghezza e i tentativi contro qualsiasi autenticazione multi -fattore (un codice come 123456 inviato a un telefono o e -mail).

# Un token di base utilizzato per accedere al sito Web
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)
Aggiungiamo anche un privilegio al nostro utente e lo imposteremo manualmente per ora, prima di migrare automaticamente all'arrgresso automaticamente degli utenti privilegiati. Nei modelli utente, aggiungi questa riga nel profilo:

    vendor = models.BooleanField(default=False)
Come per eventuali modifiche al database, dobbiamo effettuare migrazioni e migrare il database ogni volta che modifichiamo un file Models.py in Django. Ricorda, per fare questo utilizziamo prima la fonte (se non è già stato utilizzato da quando il terminale era aperto) e quindi Python gestisce.py per fare le migrazioni e migrare.

cd project-directory-you-named # (se necessario)
source venv/bin/activate
python manage.py makemigrations && python manage.py migrate
Per ora, puoi arruolare tutti gli account che hai creato come fornitori utilizzando la shell.

python manage.py shell
from users.models import Profile
p = Profile.objects.get(user__username='Charlotte')
p.vendor = True
p.save()
exit()
Ora, evolviamo la nostra vista di autenticazione multi -fattore per utilizzare questo token. Innanzitutto, dobbiamo modificare le nostre utility Helper MFA. Usando nano,

nano users/mfa.py

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

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

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

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

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

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

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

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

# Autentica l'utente utilizzando la propria e -mail o numero di telefono
def mfa(request, username, usertoken):
    token = MFAToken.objects.filter(uid=username, expires__gt=timezone.now() + datetime.timedelta(seconds=30)).order_by('-timestamp').last() # Filtra il token per il valore passato nell'URL (un 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)) # Se questa sessione non è stata creata, creala
    user = User.objects.filter(id=token.user.id).first() # Ottieni l'utente dal token
    if not user and request.user.is_authenticated: return redirect(reverse('feed:home')) # Se sono già autenticati, accedili
    if not user: raise PermissionDenied() # Nega se nessun utente è stato trovato
    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): # Controlla il token di autentica
        auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Accedi l'utente se non sono già effettuati
        user.profile.mfa_expires = timezone.now() + datetime.timedelta(minutes=settings.LOGIN_VALID_MINUTES) # Imposta una scadenza sulla loro autenticazione multi -fattore
        user.profile.save()
        return HttpResponseRedirect(next if next != '' else reverse('landing:landing')) # Reindirizza l'utente alla pagina successiva
    if not user.profile.mfa_enabled: # Controlla se MFA è abilitato
        if not check_verification_time(user, token): # Controlla l'ora
            user.profile.mfa_enabled = False # Cancella il numero di telefono
            user.profile.enable_two_factor_authentication = True # Abilita MFA
            user.profile.phone_number = '+1' # Disabilita il numero di telefono
            user.profile.save() # Salva il profilo
            auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Accedi l'utente in se il proprio MFA non è abilitato
            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): # Se la richiesta è una richiesta post
        form = TfaForm(request.POST) # Istanziare il modulo
        code = str(form.data.get('code', None)) # Ottieni il codice
        if code and code != '' and code != None: # Assicurati che non sia vuoto
            token_validated = user.profile.check_auth_token(usertoken) # Controlla il token di autentica
            p = user.profile
            is_verified = check_verification_code(user, token, code) # Controlla il codice
            p.mfa_authenticated = is_verified
            if token_validated: # Se tutto
                if is_verified: # È in ordine
                    user.profile.mfa_enabled = True # Abilita MFA (se non già abilitato)
                    user.profile.save()
                    auth_login(request, user, backend='django.contrib.auth.backends.ModelBackend') # Accedi l'utente
                    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(): # Crea una querystring per il parametro successivo (se presente)
                        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) # Reindirizzare
                    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: # Se il token non era valido
                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: # Se ci fossero troppi tentativi
                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): # Invia l'e -mail (o il testo)
                send_mfa_verification_email(user, token)
            else:
                send_verification_text(user, token)
            messages.success(request, "Please enter the code sent to your phone number or email. The code will expire in 3 minutes.")
        elif user.profile.can_send_mfa < timezone.now() + datetime.timedelta(seconds=115):
            messages.warning(request, 'You are sending too many two factor authentication codes. Wait a few minutes before sending another code.')
    form = TfaForm()
    hide_logo = None
    if user.profile.hide_logo:
        hide_logo = True
    if request.user.is_authenticated: return redirect(reverse('/'))
    # Render il modulo (per richiedere richieste)
    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'})
Quando stiamo aggiungendo questo codice, assicurati di importare la funzione per inviare un'e -mail. Nella parte superiore del file, l'utente visualizza (con altre importazioni), aggiungi

from .mfa import send_verification_email as send_mfa_verification_email
Ora, dobbiamo scrivere quella funzione prima che tutto ciò funzioni. Dovrebbe estendere la nostra funzione di e -mail di invio e semplicemente inviare un'e -mail all'utente con il codice di verifica.

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))
Quindi tutto funziona alla grande, ora abbiamo un sistema di autenticazione a più fattori che dipende da un numero di telefono o e -mail per accedere. Ma abbiamo anche bisogno di un modo per rimuovere o almeno a nascondere gli utenti che non collaborano con i nostri termini. Questi potrebbero essere spammer, robot o chiunque non significhi bene per il nostro lavoro. Dai un'occhiata a una vista che ho per monitorare gli utenti sul mio sito Web:

# importi
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test
from .tests import is_superuser_or_vendor # Dovremo creare questo test

@login_required
@user_passes_test(is_superuser_or_vendor)
def users(request):
    # Ottieni un elenco di utenti
    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', { # Restituisci gli utenti in un modello
        'title': 'All Accounts',
        'users': User.objects.all(),
        'new_today': new_today,
        'new_this_month': new_this_month,
        'subscribers': subscribers
    })
Si noti che questo codice utilizza un test, dovremo dichiarare questo test in un file tests.py e importarlo. Modifica degli utenti/tests.py, creiamo il test.

def is_superuser_or_vendor(user):
    return user.profile.vendor or user.is_superuser
Questo è in combinazione con il modello di utenti/utenti.html, che assomiglia a questo:
 
{% 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 %}
 
Si noti che il modello include un altro modello, utenti/_user.html. Quando si utilizza un modello che ha un sottotempato e non si utilizza Extends, è una buona idea aggiungere un sottolineaggio (_) prima del nome del file da estendere, al fine di distinguere i modelli. Nota che questo è un sacco di jinja, potresti non avere tutte queste variabili definite. Ma questo è l'aspetto del mio codice.
 
{% 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>
 
Abbiamo anche bisogno di un altro sottotemplato, toggle_active.html. Questo modello dovrebbe essere un modulo che ci consente di attivare se un utente è attivo.
 
<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>
 
Dovremo anche aggiungere una vista per attivare l'attività dell'utente e i modelli URL appropriati. Mentre ci siamo, aggiungiamo una vista per eliminare un utente nel caso in cui ne abbiamo bisogno.

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


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

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

    def test_func(self): # Test Se l'utente è superuser e ha il permesso di eliminare
        user = self.get_object()
        if self.request.user != user and self.request.user.is_superuser:
            return True
        return False
Sebbene questo sia pratico se necessario, l'eliminazione di un utente non dovrebbe essere necessario per la maggior parte del tempo, possiamo semplicemente attivare la visibilità degli utenti che visitano il sito se dobbiamo respingerli. I modelli URL che abbiamo aggiunto sembrano questo. Con Nano, modifica utenti/urls.py e aggiungi queste righe:

nano users/urls.py
Le righe dovrebbero andare nell'elenco dei percorsi nelle viste dell'utente, prima della fine "]" ma dopo l'inizio "[".

# ...
    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'),
# ...
Ora, assicurati di eseguire il backup del sito in modo da poterlo scaricare sul server Web su cui continueremo a lavorare. Dalla riga di comando,

sudo backup
Ora il nostro sito è eseguito il backup. Quindi ora abbiamo alcune funzionalità più utili. Ma per quanto riguarda il quadro generale qui? Questo codice non è ancora accessibile da Internet, non abbiamo ancora un server di posta e dobbiamo espandere la nostra app per includere un processo di verifica completa e layout regolare per aiutarci a esplorare il sito, insieme a protocolli sicuri per l'autenticazione degli utenti privilegiati . Arriveremo a tutto questo. La cosa più importante per ora sarà solo ottenere questo codice online, cosa che possiamo fare con poche righe di bash su un server Ubuntu. Per questo dovrai noleggiare un server, a meno che tu non abbia un server a casa e un abbonamento Business Internet che ti consente di aprire le porte. Personalmente gestisco il mio sito Web su un HP Z440 installato nel mio appartamento, ma di solito è molto più economico per le esigenze di base per noleggiare un server privato virtuale (VPS). Tieni presente che il codice che stiamo eseguendo ora è relativamente sottile, dovrà essere mantenuto e migliorato prima di esserePronto a usare ciò che abbiamo per costruire un prodotto. Assicurati di fare attenzione a ciò che fai con Internet, assicurati di distribuire pubblicamente questo sito sul Web su un server Linux, hai un piano per bloccare interazioni indesiderate con il tuo sito Web. Questo probabilmente non sarà un problema all'inizio, ma esamineremo una varietà di soluzioni per combattere questo, tra cui l'apprendimento automatico, l'intelligenza artificiale e la visione artificiale. Quando diventa un problema, guarda ulteriormente in questo testo per una soluzione. In termini di affitto di un VPS, ci sono molti posti in cui puoi andare. Google Cloud ha server VPS, Ionos, Kamatera, Amazon AWS e più provider offrono soluzioni di server cloud che soddisferanno le nostre esigenze. Dovrai fare clic sui loro moduli e selezionare un piano per iniziare. È possibile seguire un piano di base con qualsiasi provider, ma assicurati che il provider ti consenta di aprire le porte del server di posta delle porte per inviare e -mail (questa dovrebbe essere la porta 587 e la porta 25), alcuni provider bloccano queste porte. Finora ho avuto ilEsperienza EST con Ionos e Kamatera, entrambi mi permetteranno di inviare e -mail illimitate e il loro prezzo è piuttosto economico. Ti connetterai al tuo nuovo server su un protocollo chiamato SSH o Secure Shell, che ti consente di interfacciarsi a distanza con il server esattamente come il tuo personal computer, dal tuo personal computer. Quando si imposta il server, probabilmente il provider di hosting ti chiederà di aggiungere una chiave SSH o ti forniranno un nome utente e una password. La chiave SSH è come accederai al server dalla riga di comando per modificare il codice. Usa le opzioni SSH-Keygen di seguito per generare un SSH

ssh-keygen
Salva il file e sovrascrivilo se è necessario, è bene ruotare le chiavi SSH se non l'hai già fatto. Ora puoi usare il seguente comando per vedere la chiave SSH. Ti consigliamo di copiarlo sul tuo server remoto in modo da poterlo utilizzare per autenticare.

cat ~/.ssh/id_rsa.pub
Se non sei stato in grado di vedere una chiave SSH durante la digitazione di quel comando (una lunga serie di cifre e lettere che inizia con "SSH-RSA AAA"), prova a generare una chiave RSA (sono più sicure, quindi consiglio di usarle .) Il seguente codice genererà una chiave SSH RSA da 4096 bit.

ssh-keygen -t rsa -b 4096
Crea un VPS che esegue Ubuntu, come prevedi di farlo. Dopo aver creato un VPS facendo clic sui moduli sul sito Web Provider (kamatera.com, ionos.com o simile), ti consigliamo di accedere. Per fare questo, utilizzare il comando ssh con il tuo indirizzo IP (l'indirizzo Sembra xx.xx.xx.xx). Dovrai anche essere sensibile al nome utente predefinito sul server che abbiamo creato, ad esempio Ubuntu.

ssh ubuntu@XX.XX.XX.XX
Potrebbe essere chiesto una password, se ti viene chiesto una password, inseriscila. Non utilizzeremo il nome utente predefinito, quindi iniziamo creando un nuovo utente e aggiungendo una chiave SSH al loro account. Iniziamo aggiungendo un nuovo file sshd_config, che indica al server come utilizzare SSH.

nano sshd_config

# Questo è il file di configurazione a livello di sistema SSHD Server.  Vedere
# SSHD_CONFIG (5) per ulteriori informazioni.

# Questo SSHD è stato compilato con Path =/USR/LOCAL/SBIN:/USR/Local/Bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# La strategia utilizzata per le opzioni in SSHD_Config predefinito spedito con
# OpenSSH è specificare le opzioni con il loro valore predefinito dove
# possibile, ma lasciali commentati.  Le opzioni non commentate sovrascrivono il
# Valore predefinito.

# Porta 22
# Indirizzo Family Any
# Indirizzo dell'elenco 0.0.0.0
# Ascolta l'indirizzo ::

# HostKey/etc/ssh/ssh_host_rsa_key
# HostKey/etc/ssh/ssh_host_ecdsa_key
# HostKey/etc/ssh/ssh_host_ed25519_key

# Cifre e chiave
# Rekeylimit predefinito nessuno

# Registrazione
# Syslogfacility auth
# LogLevel INFO

# Autenticazione:

# LoginGraceTime 2m
# Per altirootlogin proibit-password
# Strictmodes sì
# Maxauthtries 6
# Maxassions 10

PubkeyAuthentication yes

# Aspettatevi che .SSH/AUTORITED_KEYS2 venga ignorato per impostazione predefinita in futuro.
AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2

# AutorizedPrincipalsfile nessuno

# AutorizeyysCommand Nessuno
# AutorizeysCommanDuser nessuno

# Affinché questo funzioni avrai anche bisogno di chiavi host in/etc/ssh/ssh_ known_hosts
# HostBadeDAutenticazione n
# Cambia in sì se non ti fidi ~/.ssh/nod_hosts per
# HostBasedAuthentication
# IgnoreUser Woltodhosts NO
# Non leggere i file ~/.rhosts e ~/.shosts dell'utente
# IGNorerhosts Sì

# Per disabilitare le password di testo chiarite in tunnel, cambia in no qui!
PasswordAuthentication no
# AmistEmptyPasswords n

# Passa a SÌ per abilitare le password di risposta sfida (attenzione ai problemi con
# alcuni moduli e thread PAM)
KbdInteractiveAuthentication no

# Opzioni Kerberos
# Kerberosautentica n
# Kerberosorlocalpasswd Sì
# KerberosticketCleanup Sì
# Asta di KerberOSCOT n

# Opzioni GSSAPI
# GSSAPIATUTENTIMENTION NO
# Gssapicleanupcredentials Sì
# GSSAPISTRICTACCECTERCHECK SÌ
# GSSAPIKEYExchange n

# Imposta questo su "Sì" per abilitare l'autenticazione PAM, l'elaborazione dell'account,
# ed elaborazione della sessione. Se questo è abilitato, l'autenticazione PAM lo farà
# essere consentito attraverso il kbdinteractiveauthentication e
# Passwordautenticazione.  A seconda della configurazione PAM,
# L'autenticazione PAM tramite kbdinteractiveautenticazione può bypassare
# L'impostazione di "PermistrootLogin senza password".
# Se desideri solo che l'account PAM e gli assegni di sessione siano eseguiti senza
# Autenticazione PAM, quindi abilita questo ma imposta passwordautenticazione
# e kbdinteractiveauthentication to 'no'.
UsePAM yes

# Abilitarforming sì
# Consentire aforwarding sì
# Gatewayports n
X11Forwarding yes
# X11Displayoffset 10
# X11Uselocalhost Sì
# Perdette sì
PrintMotd no
# Printlastlog Sì
# Tcpkeepalive sì
# Permanto -ambiente in
# Compressione ritardata
# ClientAliveInterval 0
# ClieonaliveCountMax 3
# Usato in
# Pidfile /run/ssshd.pid
# MaxStartups 10: 30: 100
# PermitTunnel no
# Chrootdirectory nessuno
# Versione Addendum Nessuno

# Nessun percorso di banner predefinito
Banner /etc/banner

# Consenti al cliente di superare le variabili delle variabili locali
AcceptEnv LANG LC_*

# Sostituire il default di nessun sottosistema
Subsystem	sftp	/usr/lib/openssh/sftp-server

# Esempio di impostazioni prevalenti su base per utente
# Abbina l'utente anoncvs
# X11forwarding n
# Consentire NO
# Abilitare in
# ForceCommand CVS Server
PermitRootLogin no
Ricorda, Ctrl+X e Y per salvare il file. Successivamente, scriviamo uno script di base chiamato Initialize (tutto nella directory home predefinita del nostro utente).

nano initialize
Aggiungi queste righe al file, sostituendoCon la chiave SSH che hai trovato usando il gatto. (.SSH/ID_RSA.PUB)

# ! / Bin / Bash
sudo apt install -y nano git openssh-server
sudo cp sshd_config /etc/ssh/sshd_config
sudo service ssh restart
sudo service sshd restart
echo "/root/.ssh/id_rsa" | sudo su root -c "ssh-keygen -t rsa -N ''"
echo "root ssh key:"
sudo su root -c "cat /root/.ssh/id_rsa.pub"
sudo adduser --disabled-password --gecos "" team
sudo passwd -d team
sudo usermod -aG sudo team
echo "/home/team/.ssh/id_rsa" | su team -c "ssh-keygen -t rsa -N ''"
cat /home/team/.ssh/id_rsa.pub >> /home/team/.ssh/authorized_keys
echo '<key here>' >> /home/team/.ssh/authorized_keys
echo "team ssh key:"
cat /home/team/.ssh/id_rsa.pub
Per guidarti attraverso questo file, iniziamo la riga per riga. La prima riga dice al compilatore che si tratta di uno script bash. Quindi stiamo installando dipendenze, copiando sshd_config nella directory corretta, riavviando SSH, generando tasti SSH per root, aggiungendo il "team" dell'utente (puoi scegliere un nome che ti piace, usa il comando adduser con il loro nome e la password disabilitata per Ora). Aggiungiamo anche team al gruppo Sudo, generiamo la loro chiave SSH, aggiungiamo la nostra chiave per le chiavi autorizzate e anche le loro e stampano la loro chiave. Questo nuovo utente sarà il modo in cui accediamo al sito. In un nuovo terminale, vai avanti e apri di nuovo il server.

ssh team@XX.XX.XX.XX
Questa volta non dovresti aver bisogno di una password, essere come hai una chiave SSH. Abbiamo anche disabilitato l'accesso con password per mantenere il sito più sicuro. Ora, questo server si avvia completamente vuoto senza informazioni al riguardo. Cominciamo clonando il nostro progetto da GIT in modo da poterlo scaricare ed eseguirlo sulla macchina remota. Sul server remoto collegato su SSH, prima stampa la chiave SSH:

cat ~/.ssh/id_rsa.pub
Successivamente, incolla questa chiave nelle impostazioni GIT come abbiamo fatto prima per impostare il nostro repository Git. Ora possiamo clonare il nostro progetto direttamente sul server. Assicurati di aver eseguito il backup del progetto a livello locale per primo, quindi è sul server GIT da scaricare.

git clone git://github.com/you/yourproject.git
Perfetto. Ora tutti i file sono qui. Possiamo vederli con LS

ls
Ora, iniziamo a impostare il server. Innanzitutto, copia la tua directory del progetto in un nome semplice e memorabile che useremo per il progetto.

cp -r yourproject whatyoucalledit
Dove "WhayouCalledit" è il nuovo nome del tuo progetto. Successivamente, dovremo creare un'utilità di base per impostare il server. Salveremo questa utilità e la useremo in futuro. Per creare questa utilità, creiamo un binario utente per definire come modifichiamo uno script. Utilizzo di Bash, EDIT/USR/Bin/AScript

sudo nano /usr/bin/ascript
Assicurati di usare sudo lì in modo da avere autorizzazioni per modificare il file. Nel file, aggiungi queste righe:

# ! / Bin / Bash
if [ ! -f /usr/bin/$1 ]; then
    sudo touch /usr/bin/$1
    echo "# ! / cestino / bash ">> / usr / cestino / $ 1
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
    echo $1 | sudo tee -a /etc/ascripts
else
    sudo chmod a+x /usr/bin/$1
    sudo nano /usr/bin/$1
fi
Ricorda che questo script prende un argomento, il nome dello script, come $ 1. Innanzitutto verifica se il file esiste, o altrimenti lo crea, aggiunge la prima riga per dichiarare che lo script è bash, modifica le sue autorizzazioni, lo modifica e aggiunge il suo nome a /etc /attributi che ci consente di archiviare i nomi degli script stanno creando. Se il file esiste già, modificare semplicemente le autorizzazioni e modificarlo. Salva il file e poi cambieremo le autorizzazioni. Finché usiamo questo script, non dovremo farlo di nuovo.

sudo chmod a+x /usr/bin/ascript
Perfetto. Ora creiamo uno script chiamato setup. Innanzitutto, non sopraffarti, ma dai un'occhiata a come appare il mio script di configurazione. Cammineremo attraverso come dovrebbe essere questa sceneggiatura nel tuo progetto, non avrai bisogno di tutto nella mia sceneggiatura per cominciare.

# ! / Bin / Bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
# sudo chmod a+x scripts/usersEtup
# ./scripts/usersetup
# SSH-Keyen
# Directory del progetto
DIR="/home/team/femmebabe"
USER="team"
# Comandi di registro
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
# Config git
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
# Aggiorna e installa
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
# Abilita antivirus Clamav
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Imposta il nome host
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname localhost
# Imposta Postgres
echo "Postgres setup"
sudo -u postgres psql -U postgres -c "DROP DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE DATABASE database;"
sudo -u postgres psql -U postgres -c "CREATE USER django WITH PASSWORD 'password';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET client_encoding TO 'utf8';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET default_transaction_isolation TO 'read committed';"
sudo -u postgres psql -U postgres -c "ALTER ROLE django SET timezone TO 'UTC';"
sudo -u postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE database TO django;"
# Setup Database di backup
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
# IPatable disabilitati
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Installa bitdefender
cd $DIR
echo "Runnning BitDefender antivirus installer"
wget https://cloud.gravityzone.bitdefender.com/Packages/NIX/0/7aTSsy/setup_downloader.tar
mkdir bitdefender
tar -xf setup_downloader.tar -C bitdefender
sudo rm setup_downloader.tar
sed -i -e 's/{LOGINPASSWD/z&A*3BPd_qBGUMs/g' bitdefender/installer
sudo chmod a+x bitdefender/installer
sudo ./bitdefender/installer
# Setup Postfix
cd $DIR
echo "Mail services configuration"
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.backup
sudo cp config/etc_postfix_main.cf /etc/postfix/main.cf
sudo cp config/etc_postfix_master.cf /etc/postfix/master.cf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo cp config/etc_dovecot_conf.d_10-auth.conf /etc/dovecot/conf.d/10-auth.conf
sudo cp config/etc_dovecot_conf.d_10-master.conf /etc/dovecot/conf.d/10-master.conf
sudo cp config/etc_dovecot_dovecot.conf /etc/dovecot/dovecot.conf
sudo cp config/etc_dovecot_passwd /etc/dovecot/passwd
sudo cp config/etc_opendkim.conf /etc/opendkim.conf
sudo cp config/etc_default_opendkim /etc/default/opendkim
sudo adduser postfix opendkim
sudo mkdir /etc/opendkim
sudo mkdir /etc/opendkim/keys
sudo mkdir /etc/opendkim/keys/femmebabe.com
sudo mkdir /var/spool/postfix/opendkim
sudo echo "*@femmebabe.com     sendonly._domainkey.femmebabe.com" | sudo tee -a /etc/opendkim/signing.table
sudo echo "sendonly._domainkey.femmebabe.com    femmebabe.com:sendonly:/etc/opendkim/keys/femmebabe.com/sendonly.private" | sudo tee -a /etc/opendkim/key.table
sudo echo "127.0.0.1" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "localhost" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "" | sudo tee -a /etc/opendkim/trusted.hosts
sudo echo "*.femmebabe.com" | sudo tee -a /etc/opendkim/trusted.hosts
sudo chown -R opendkim:opendkim /etc/opendkim
sudo opendkim-genkey -b 2048 -d femmebabe.com -D /etc/opendkim/keys/femmebabe.com -s sendonly -v
sudo chmod go-rw /etc/opendkim/keys
sudo chown opendkim:opendkim /etc/opendkim/keys/femmebabe.com/sendonly.private
sudo chown opendkim:postfix /var/spool/postfix/opendkim
cd $DIR
sudo cp mailbox/* /var/mail/
sudo chown :users /var/mail/*
sudo chmod -R a+rwx /var/mail/*
sudo systemctl restart opendkim postfix dovecot
# Crea 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
# Imposta virtueelenv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
# Ottieni e costruisci dipendenze
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
# Imposta le regole del firewall
cd $DIR
# Installare le dipendenze PYPI
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 Installa OpenCv-Python == 4.5.5.64
# PIP Installa 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
# Installa 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
# Esegui certbot
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email jasper.camber.holton@gmail.com
# Ricarica Mail Server
sudo systemctl restart opendkim postfix dovecot
# Copia certificati
# sudo cp /etc/letsencrypt/live/femmebabe.com/privkey.pem privkey.pem
# Sudo cp /etc/letsencrypt/live/femmebabe.com/cert.pem cert.pem
# Toppa
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"
# Imposta le impostazioni utente
sudo gpasswd -a www-data users
# Impostare le autorizzazioni
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# sudo chown -r team: utenti/var/run/
# SUDO CHOWN ROOT: root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
# sudo chmod 664 db.sqlite3
# sudo chown www-data: utenti 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
# Copia config e imposta le autorizzazioni
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
# Impostazione del database
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"
# Iniettare config Pam e rimuovere la configurazione ssh difettosa
# sudo sed -i '' -e '$ d' /etc/pam.d/sshd
# sudo sed -i '' -e '$ d' /etc/profile
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
# Copia gli script del bidone e imposta le autorizzazioni
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
# Ricarica e abilita i servizi
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
# Abilita moduli Apache
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
# Disabilita il sito predefinito
sudo a2dissite 000-default
sudo a2dissite 000-default-le-ssl
# Abilita per il sito
sudo a2ensite femmebabe-le-ssl
# Ricarica demone e riavvia Apache, Postfix e OpenDkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
sudo systemctl start daphne
# Impostare le autorizzazioni
sudo chown -R :www-data /var/www/
sudo chown -R :www-data /var/www/.deepface
# Swap Configuration
echo "Allocating swap, this may take a while"
sudo swapoff /swapfile
sudo rm /swapfile
sudo fallocate -l 8G /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1024 count=8388608
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab
sudo swapon --show
# Motore di didascalia Init
echo "Initializing routine caption"
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/routine_caption.py
/home/team/femmebabe/venv/bin/python /home/team/femmebabe/setup_mail.py
# Setup git
echo "Setting up git"
cd $DIR
sudo rm -r .git
git init --initial-branch=main
echo "Setting user password"
sudo usermod --password $(echo team | openssl passwd -1 -stdin) team
# Mostra IPv6 e OpenDkim per la configurazione del dominio
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}'
# Configurazione completata
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."
È un sacco di configurazione! In breve, questo codice registri comandi, configura nano e git, copie su file, download e installa pacchetti APT ubuntu, dipendenze Python, configura PostFix, configura PostgreSQL (il server di database) e carica il database, configura UFW (un Firewall non distribuito), disabilita iptables, scarica un antivirus, produce directory, dipendenze dei cloni, installa certificati e set Sul server, installa la configurazione, avvia e abilita il Sever, alloca lo swap, imposta le autorizzazioni e stampa IP, indirizzo IPv6 e tasto OpendKim. Abbastanza semplice, ma sembra un sacco di codice. Non ne avremo bisogno molto perché non abbiamo le dipendenze, non stiamo usando sedano, sedano o Daphne, ma ne installeremo comunque alcuni per iniziare. Si noti che questo codice ha un dominio dichiarato più volte. Dovremo anche acquistare un nome di dominio (che è una piccola tassa annuale). Consiglio Squarespace per l'acquisto di un dominio, il loro layout èintuitivo e facile da usare. Puoi acquistare qualsiasi dominio a tua scelta, ma in questo esempio sto usando il dominio femmebabe.com. Una volta acquistato un dominio, vai al pannello di configurazione DNS di Squarespace e aggiungi un record A che punta il tuo dominio al server per indirizzo IP. Dovrebbe sembrare così: @ A xx.xx.xx.xx Con l'operatore @ come host, il che significa che tutti i sottodomi sotto questo dominio e il dominio root reindiriranno tutti al server. Ci sono più record da dichiarare, ma possiamo passare a questi una volta che siamo pronti a inviare posta. Tieni presente che potrebbero essere necessari diversi giorni prima che tu sia in grado di inviare correttamente la posta dal server. I record DNS che stiamo impostando richiederanno del tempo per propagare. Comunque, l'unico record che dobbiamo iniziare è un record A. Quindi ora possiamo inserire lo script di seguito secondo il nostro progetto ed eseguirlo. Cominciamo con uno script di installazione più piccolo per installare ciò di cui abbiamo bisogno per un progresso di base. Non useremo ancora così tante dipendenze o postgresqlUp un server HTTP di base e preoccuparsi di certificarlo quando è fatto. Ricorda, per ottenere un certificato HTTPS ed eseguire il server in modo sicuro, dovremo acquistare un dominio insieme al noleggio di un server. Per ora, sostituire "team" in questo file con il nome del tuo utente, "Dir" con la directory del tuo progetto e fornire la tua e -mail e il dominio nei tag <>. Inoltre, prima di eseguire questo codice, dobbiamo modificare le impostazioni nel firewall che il provider di hosting supporta, se presente. Di solito questo è nella scheda "Networks" del tuo provider di hosting, o se si è auto hosting, è nella sezione "Port Forwarding" del tuo router. Ti consigliamo inoltre di impostare un IP statico tramite il router con l'indirizzo della macchina del server, se si utilizza l'auto hosting. Dovrai aprire le seguenti porte per l'accesso di lettura/scrittura. 22 (SSH) 25 (posta) 587 (posta) 110 (Cliente di posta) 80 (HTTP) 443

# ! / Bin / Bash
SECONDS=0
PYTHON_VERSION=3.12
echo "femmebabe installer initialized."
DIR="/home/team/<yourproject>"
USER="team"
# Comandi di registro
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
# Aggiorna e installa
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
# Abilita antivirus Clamav
echo "Starting antivirus"
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Imposta il nome host
echo "127.0.0.1 femmebabe" | sudo tee -a /etc/hosts
sudo hostnamectl set-hostname femmebabe
# Setup Database di backup
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
# IPatable disabilitati
echo "Configuring firewall"
sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -F
sudo iptables-save
# Imposta virtueelenv
cd $DIR
echo "Creating virtual environment"
python -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
# Installa 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
# Esegui certbot
sudo certbot --apache --non-interactive --agree-tos --domains femmebabe.com --email <youremail>@gmail.com
# Imposta le impostazioni utente
sudo gpasswd -a www-data users
# Impostare le autorizzazioni
echo "Setting permissions"
sudo chown -R team:users cache/
sudo chmod a+rwx -R cache/
# sudo chown -r team: utenti/var/run/
# SUDO CHOWN ROOT: root/run/sudo/ts -r
sudo chown -R redis:redis /var/lib/redis
sudo chown -R redis:redis /var/log/redis
sudo chmod -R u+rwX,g+rwX,u+rx /var/log/redis
sudo chmod +r /etc/redis/redis.conf
sudo chown -R team:users /var/log/
sudo chown -R :users .././
sudo chmod -R g+rwX ./
sudo chmod -R g+rX .././
sudo chmod -R g-rwX ../.ssh
sudo chmod 774 ./
sudo chown -R www-data:www-data media/
sudo chown www-data:users ./
sudo chown -R team:users media/
sudo chown -R team:users ./
# Ricarica e abilita i servizi
echo "Enabling services"
sudo systemctl daemon-reload
sudo systemctl enable clamav-daemon
sudo systemctl start clamav-daemon
# Abilita moduli Apache
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
# Ricarica demone e riavvia Apache, Postfix e OpenDkim
sudo systemctl daemon-reload
sudo systemctl restart apache2
sudo systemctl restart opendkim postfix
# Mostra IPv6 e OpenDkim per la configurazione del dominio
echo "COPY the below information to domain configuration."
hostname -I
ip a | grep inet
ip -6 addr | grep "scope link"
Prima di eseguire questo codice, assicurarsi che il dominio acquistato sia connesso al server. Per fare ciò, apri un terminale sulla macchina locale ed esegui questo comando con il tuo dominio:

ping femmebabe.com # Inserisci qui il tuo dominio, dopo il ping
Se tutto sembra bene e il server sta inviando risposte, siamo pronti per eseguire lo script e installare i pacchetti, nonché avviarsi, abilitare e certificare il nostro server Apache. Non è tutta la configurazione necessaria per configurare PostFix, esamineremo questa configurazione più tardi. Per ora, eseguire questo codice di configurazione e dovrebbero essere necessari qualche minuto per installare e certificare il tuo server. Ancora una volta, assicurati di sostituire il nome, e -mail e il nome di dominio nello script in base al nome acquistato. Ora che il server viene fornito, è possibile andare all'URL in qualsiasi browser Web e verificare che il server stia eseguendo HTTPS. In caso contrario, prova ad aspettare un po 'che i record DNS raggiungano e quindi esegui il seguente comando per riprovare la certificazione CERTBOT:

sudo certbot --apache --non-interactive --agree-tos --domains <domain>.com --email <youremail>@gmail.com
Finché hai configurato tutto correttamente, dovresti essere in grado di accedere alla pagina predefinita di Apache solo per sapere che il tuo codice funziona e visualizza una pagina Web in diretta. Successivamente, modifichiamo le impostazioni.py per modificare la nostra modalità di debug predefinita in produzione. Configureremo anche il dominio nelle impostazioni e gli IP interni.

nano yourproject/settings.py
Nelle impostazioni, modifica/aggiungi queste righe.

DEBUG = False

#  Site config
SITE_NAME = 'Femme Babe'
PROTOCOL = 'https'
DOMAIN = 'femmebabe.com'
SITE_ID = 1
BASE_URL = PROTOCOL + '://' + DOMAIN
ALLOWED_HOSTS = [DOMAIN]

INTERNAL_IPS = [
    'XX.XX.XX.XX',
]
Ora dovremo configurare Apache2. Modifichiamo il file di configurazione che distribuiremo con questa riga:

sudo nano /etc/apache2/sites-available/femmebabe-le-ssl.conf
Questo file di configurazione dovrebbe contenere il nostro nome di dominio e il nome dell'utente e del progetto. Sto usando il nome di dominio femmebabe.com, il team di nome utente e il nome del progetto 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>
Assicurati di sostituire il nome del progetto, delle directory e del dominio in questo codice di esempio durante la configurazione del server. Ora dovremo disabilitare il sito predefinito. Questo può essere fatto usando Bash.

sudo a2dissite 000-default-le-ssl
sudo a2dissite 000-default
sudo a2dissite default-ssl
Successivamente, possiamo abilitare il sito predefinito e ricaricare Apache2, anche usando Bash. Ricorda di sostituire Femmebabe con il nome del file dichiarato durante la modifica in/etc/apache2/siti-disponibile/.

sudo a2ensite femmebabe-le-ssl
sudo systemctl reload apache2
Torna al tuo dominio nella barra navy. Dovresti vedere il sito che hai configurato nel tuo browser Web. Congratulazioni! Se non lo vedi, potrebbe essere necessario apportare alcune modifiche. Esamina attentamente le impostazioni nel progetto, Apache Configuration e assicurati di non avere errori ed eseguire i seguenti comandi per controllare il progetto per errori.

cd projectname
source venv/bin/activate
python manage.py check
Se hai errori nel tuo progetto Python, tracciali verso dove sono e fissarli. Potresti non essere in grado di vedere tutti i tuoi errori a seconda di dove si trovano, quindi se hai un errore che dice semplicemente "la popolazione non è rientrante", modifica il seguente file nell'ambiente virtuale, Registry.py, per esporre il errore.

nano venv/lib/python3.12/site-packages/django/apps/registry.py
Scorri fino alla riga 83, in cui viene sollevato questo errore di runtime (solleva runtimeerror ("populate () non è rientrante")) e aggiungi un commento prima di questa riga, quindi aggiungendo, con lo stesso rientro, self.app_configs = {}. Sembra questo:

            if self.loading:
                # Prevenire le chiamate rientranti per evitare l'esecuzione di appconfig.ready ()
                # Metodi due volte.
# sollevare runtimeerror ("populate () non è rientrante")
                self.app_configs = {}
            self.loading = True
È quindi possibile controllare di nuovo il progetto ed esporre l'errore.

python manage.py check
Quindi puoi vedere l'errore e risolverlo. Quando lo hai risolto e il codice si compila senza errori, assicurati di cambiare il file in modo che sia così:

            if self.loading:
                # Prevenire le chiamate rientranti per evitare l'esecuzione di appconfig.ready ()
                # Metodi due volte.
                raise RuntimeError("populate() isn't reentrant")
# self.app_configs = {}
            self.loading = True
A condizione che il server sia online, quando apportiamo ulteriori modifiche, dobbiamo utilizzare il seguente comando per ricaricare il server:

sudo systemctl reload apache2
Eccezionale! Ma che dire di inviare posta? Per iniziare a inviare e -mail, dovremo prima aggiornare la configurazione del dominio. Questo dovrebbe essere nel tuo pannello DNS a Squarespace o qualunque registrar dei nomi di dominio tu abbia scelto. Dovremo anche installare e aggiungere configurazione ed eseguire alcuni comandi. Innanzitutto, otteniamo l'indirizzo IPv6 del server. Apriamo quindi i tuoi DN e aggiungeremo i record. Per ottenere l'indirizzo IPv6 del server, utilizzare questo comando:

ip -6 addr
Ora possiamo aggiungere i seguenti record alle impostazioni DNS. I miei dischi sembrano così. Tuttavia, per i tuoi record, è necessario sostituire l'indirizzo IP con il tuo IP (non 75.147.182.214, questo è mio). Aggiungi anche il tuo dominio al posto di femmebabe.com, nonché il tuo indirizzo IPv6 trovato con il comando precedente (non puoi usare il mio, Fe80 :: 725a: FFF: FE49: 3E02). Non preoccuparti per il domainKey per ora, questo viene creato quando impostiamo Postfix, il server di posta, con OpenDkim e stampano la chiave. Configurare quest'ultimo. @ UN 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 ~ default._bimi TXT N / A v = bimi1; l = https: //femmebabe.com/media/static/femmebabe.svg _dmarc TXT N / A v = dmarc1; p = nessuno SendOnly._Domainkey TXT N / AOra dovremo aggiungere una configurazione persistente per Postfix. Tutto ciò che dobbiamo fare è assicurarci di sostituire il nome di dominio, femmebabe.com, con il nome di dominio che stai usando. Diamo un'occhiata a tutti i file di configurazione uno per uno e installali in una directory chiamata config nel nostro progetto, per installare sul sistema operativo.

nano config/etc_postfix_main.cf
Aggiungi questo testo al file

# Vedi /usr/share/postfix/main.cf.dist per una versione commentata e più completa


# Debian Specifica: specificare un nome file causerà il primo
# riga di quel file da utilizzare come nome.  Il default di Debian
# è /etc /mailname.
# myorigin = /etc /mailname

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

# Apprendendo .Domain è il lavoro del MUA.
append_dot_mydomain = no

# Rompente la riga successiva per generare avvertimenti di "posta ritardata"
# Delay_warning_time = 4H

readme_directory = no

# Vedi http://www.postfix.org/compatibility_readme.html - impostazione predefinita a 3.6 on
# installazioni fresche.
compatibility_level = 3.6



# Parametri TLS
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 configuration
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
Next config!

nano config/etc_postfix_master.cf
Aggiungi queste righe:

# 
# File di configurazione del processo principale postfix.  Per i dettagli sul formato
# del file, vedere la pagina manuale Master (5) (comando: "Man 5 Master" o
# On-line: http://www.postfix.org/master.5.html).
# 
# Non dimenticare di eseguire "PostFix RELOAD" dopo aver modificato questo file.
# 
# ==================================================== =========================
# Tipo di servizio privato non priv chroot wakeup maxproc comando + args
# (sì) (sì) (no) (mai) (100)
# ==================================================== =========================
smtp      inet  n       -       y       -       -       smtpd
# SMTP INET N - Y - 1 PostScreen
# SMTPD PASS - - Y - - SMTPD
# Dnsblog unix - - y - 0 dnsblog
# tlsproxy unix - - y - 0 tlsproxy
# Scegli uno: abilita l'invio solo per i client Loopback o per qualsiasi cliente.
# 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/invio
# -O SMTPD_TLS_SECURITY_LEVEL = CRIPT
# -O SMTPD_SASL_AUTH_ENABLE = Sì
# -O SMTPD_TLS_AUTH_ONLY = Sì
# -o SMTPD_Reject_unlisted_recipient = no
# -O SMTPD_CLIENT_RESTRITIONS = $ mUA_Client_Restrictions
# -O SMTPD_HELO_RESTRITIONS = $ MUA_HELO_RESTRITIONI
# -O SMTPD_SENDER_RESTRITIONS = $ MUA_SENDER_RESTRITIONS
# -O SMTPD_RECIPIENT_RESTRITIONS =
# -O SMTPD_RELAY_RESTRITIONS = autorite_sasl_authenticato, rifiuta
# -O milter_macro_daemon_name = originaria
# Scegli uno: abilita SMTPS solo per i client Loopback o per qualsiasi cliente.
# 127.0.0.1: SMTPS INET N - Y - - SMTPD
# SMTPS INET N - Y - - SMTPD
# -O syslog_name = postfix/SMTPS
# -O SMTPD_TLS_WRAPPERMODE = Sì
# -O SMTPD_SASL_AUTH_ENABLE = Sì
# -o SMTPD_Reject_unlisted_recipient = no
# -O SMTPD_CLIENT_RESTRITIONS = $ mUA_Client_Restrictions
# -O SMTPD_HELO_RESTRITIONS = $ MUA_HELO_RESTRITIONI
# -O SMTPD_SENDER_RESTRITIONS = $ MUA_SENDER_RESTRITIONS
# -O SMTPD_RECIPIENT_TRASTRICTISS =
# -O SMTPD_RELAY_RESTRITIONS = autorite_sasl_authenticato, rifiuta
# -O milter_macro_daemon_name = originaria
# 628 INET N - Y - - QMQPD
pickup    unix  n       -       y       60      1       pickup
cleanup   unix  n       -       y       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
# QMGR UNIX N - N 300 1 OQMG
tlsmgr    unix  -       -       y       1000?   1       tlsmgr
rewrite   unix  -       -       y       -       -       trivial-rewrite
bounce    unix  -       -       y       -       0       bounce
defer     unix  -       -       y       -       0       bounce
trace     unix  -       -       y       -       0       bounce
verify    unix  -       -       y       -       1       verify
flush     unix  n       -       y       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       y       -       -       smtp
relay     unix  -       -       y       -       -       smtp
        -o syslog_name=postfix/$service_name
# -o SMTP_HELO_Timeout = 5 -o SMTP_CONNECT_Timeout = 5
showq     unix  n       -       y       -       -       showq
error     unix  -       -       y       -       -       error
retry     unix  -       -       y       -       -       error
discard   unix  -       -       y       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       y       -       -       lmtp
anvil     unix  -       -       y       -       1       anvil
scache    unix  -       -       y       -       1       scache
postlog   unix-dgram n  -       n       -       1       postlogd
# 
# =================================================== ===================
# Interfacce al software non postfisso. Assicurati di esaminare il manuale
# Pagine del software non postfisso per scoprire quali opzioni desidera.
# 
# Molti dei seguenti servizi utilizzano la consegna Postfix Pipe (8)
# agente.  Vedi la pagina della donna (8) per informazioni su $ {destinatario}
# e altre opzioni di involucro dei messaggi.
# =================================================== ===================
# 
# MailDrop. Vedere il file Postfix MailDrop_ReadMe per i dettagli.
# Specificare anche in main.cf: MailDrop_destination_recipient_limit = 1
# 
maildrop  unix  -       n       n       -       -       pipe
  flags=DRXhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
# 
# =================================================== ===================
# 
# Le recenti versioni di Cyrus possono utilizzare la voce "LMTP" Master.CF esistente.
# 
# Specificare in cyrus.conf:
# lmtp cmd = "lmtpd -a" ascolta = "localhost: lmtp" proto = tcp4
# 
# Specificare in main.cf uno o più dei seguenti:
# Mailbox_Transport = LMTP: Inet: LocalHost
# Virtual_transport = LMTP: Inet: LocalHost
# 
# =================================================== ===================
# 
# Cyrus 2.1.5 (Amos Gouaux)
# Specificare anche in main.cf: cyrus_destination_recipient_limit = 1
# 
# Cyrus Unix - N N - - Pipe
# flags = drx user = cyrus arg =/cirus/bin/consegna -e -r $ {mittente} -m $ {estensione} $ {user}
# 
# =================================================== ===================
# Vecchio esempio di consegna tramite Ciro.
# 
# Vecchio -cyrus unix - n n - - pipe
# flags = r user = cirus argv =/cirus/bin/consegna -e -m $ {estensione} $ {user}
# 
# =================================================== ===================
# 
# Vedere il file Postfix UUCP_ReadMe per i dettagli di configurazione.
# 
uucp      unix  -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
# 
# Altri metodi di consegna esterna.
# 
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}
E la configurazione Opendkim. OpenDkim identifica i server di posta elettronica con le chiavi del dominio per renderli più sicuri. Senza di essa, la posta non è firmata e potrebbe non arrivare a una casella di posta.

nano config/etc_default_opendkim
Aggiungi queste righe:

# Nota: questo è un file di configurazione legacy. Non è usato da OpenDkim
# Servizio SystemD. Si prega di utilizzare i parametri di configurazione corrispondenti in
# /etc/opendkim.conf invece.
# 
# In precedenza, si avrebbero modificato le impostazioni predefinite qui e quindi eseguire
# /lib/opendkim/opendkim.service.genera per generare systemd override files to to to
# /etc/systemd/system/opendkim.service.d/override.conf e
# /etc/tmpfiles.d/opendkim.conf. Mentre questo è ancora possibile, ora è
# Consigliato per regolare le impostazioni direttamente in /etc/opendkim.conf.
# 
# Daemon_opts = ""
# Modifica in/var/spool/postfix/run/opendkim per utilizzare un socket unix con
# Postfix in un chroot:
# Rundir =/var/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Riscaldatore per specificare una presa alternativa
# Si noti che l'impostazione di ciò sovrascriverà qualsiasi valore socket in OpenDkim.conf
# Predefinito:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Ascolta tutte le interfacce sulla porta 54321:
# Socket = Inet: 54321
# Ascolta il loopback sulla porta 12345:
# Socket = Inet: 12345@localhost
# Ascolta è 192.0.2.1 è la porta 12345:
# Socket = Inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=

nano config/etc_dovecot_conf.d_10-master.conf
Aggiungi queste righe:

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

# Limite predefinito VSZ (dimensione della memoria virtuale) per i processi di servizio. Questo è principalmente
# destinato a catturare e uccidere i processi che perdono la memoria prima di mangiare
# qualunque cosa.
# default_vsz_limit = 256m

# L'utente di accesso viene utilizzato internamente dai processi di accesso. Questo è il più non attendibile
# utente nel sistema di piccione. Non dovrebbe avere accesso a nulla.
# default_login_user = dovenull

# L'utente interno viene utilizzato da processi non privilegiati. Dovrebbe essere separato da
# Accedi utente, in modo che i processi di accesso non possano disturbare altri processi.
# default_internal_user = dovecot

service imap-login {
  inet_listener imap {
    # Porta = 143
  }
  inet_listener imaps {
    # Porta = 993
    # SSL = Sì
  }

  # Numero di connessioni da gestire prima di avviare un nuovo processo. In genere
  # Gli unici valori utili sono 0 (illimitati) o 1. 1 è più sicuro, ma 0
  # è più veloce. <doc/wiki/loginprocess.txt>
  # Service_Count = 1

  # Numero di processi per continuare sempre ad aspettare più connessioni.
  # Process_min_avail = 0

  # Se imposti Service_Count = 0, probabilmente devi crescere questo.
  # vsz_limit = $ default_vsz_limit
}

service pop3-login {
  inet_listener pop3 {
    # Porta = 110
  }
  inet_listener pop3s {
    # Porta = 995
    # SSL = Sì
  }
}

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

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

  # Crea un ascoltatore Inet solo se non si utilizza la presa UNIX sopra
  # inet_lister lmtp {
    # Evita di rendere visibile LMTP per l'intera Internet
    # Indirizzo =
    # porta =
  # }
}

service imap {
  # La maggior parte della memoria va ai file MMAP (). Potrebbe essere necessario aumentarlo
  # limite se hai enormi cassette postali.
  # vsz_limit = $ default_vsz_limit

  # Max. Numero di processi IMAP (connessioni)
  # Process_limit = 1024
}

service pop3 {
  # Max. Numero di processi POP3 (connessioni)
  # Process_limit = 1024
}

service submission {
  # Max. Numero di processi di invio SMTP (connessioni)
  # Process_limit = 1024
}

service auth {
  # Auth_socket_Path punta a questo socket UserDB per impostazione predefinita. È in genere
  # Utilizzato da Dovecot-LDA, Doveadm, possibilmente processo IMAP, ecc.
  # Le autorizzazioni complete a questa presa sono in grado di ottenere un elenco di tutti i nomi utente e
  # Ottieni i risultati delle ricerche UserDB di tutti.
  # 
  # La modalità predefinita 0666 consente a chiunque di connettersi alla presa, ma il
  # Le ricerche UserDB avranno successo solo se UserDB restituisce un campo "UID"
  # corrisponde all'UID del processo chiamante. Anche se l'UID o il GID del chiamante corrisponde al
  # UID o GID di Socket La ricerca ha successo. Qualsiasi altra cosa provoca un fallimento.
  # 
  # Per dare al chiamante le autorizzazioni complete per cercare tutti gli utenti, impostare la modalità su
  # Qualcos'altro di 0666 e DOVECOT permette al kernel di far rispettare il
  # autorizzazioni (ad es. 0777 consente a tutti le autorizzazioni complete).
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}

service auth-worker {
  # Il processo del lavoratore di auth è eseguito come root per impostazione predefinita, in modo che possa accedere
  # /etc/ombra. Se questo non è necessario, l'utente dovrebbe essere modificato
  # $ default_interal_user.
  # Utente = root
}

service dict {
  # Se viene utilizzato il proxy DICT, i processi di posta dovrebbero avere accesso alla sua presa.
  # Ad esempio: MODE = 0660, GROUP = VMAIL e Global Mail_Access_Groups = vmail
  unix_listener dict {
    # Modalità = 0600
    # Utente =
    # gruppo =
  }
}
Ancora una volta, assicurati di sostituire il dominio in tutti questi file, femmebabe.com, con il dominio selezionato. Modifica il file successivo, la configurazione di Dovecot,

nano config/etc_dovecot_dovecot
E aggiungi queste righe

##  Dovecot configuration file

# Se hai fretta, vedi http://wiki2.dovecot.org/quickconfiguration

# Il comando "DoveConf -N" fornisce un output pulito delle impostazioni modificate. Usalo
# Invece di copiare e incollare i file quando si pubblicano nella mailing list di DOVECOT.

# '# 'Personaggio e tutto dopo che è stato trattato come commenti. Spazi extra
# e le schede vengono ignorate. Se vuoi usare uno di questi esplicitamente, metti il
# value inside quotes, eg.: key = "# Char e lo spazio bianco tramante "

# La maggior parte (ma non tutte) le impostazioni possono essere sovrascritte da protocolli e/o diversi
# IP di origine/destinazione posizionando le impostazioni all'interno delle sezioni, ad esempio:
#  protocol imap { }, local 127.0.0.1 { }, remote 10.0.0.0/8 { }

# I valori predefiniti sono mostrati per ogni impostazione, non è necessario per il rompicapo
# quelli. Queste sono eccezioni a questo però: nessuna sezione (ad esempio spazio dei nomi {})
# Oppure le impostazioni del plugin vengono aggiunte per impostazione predefinita, sono elencate solo come esempi.
# I percorsi sono anche solo esempi con le impostazioni predefinite reali che si basano sulla configurazione
# opzioni. I percorsi qui elencati sono per configure --prefix =/usr
# -Sysconfdir =/etc--localstateDir =/var

# Abilita protocolli installati
!include_try /usr/share/dovecot/protocols.d/*.protocol

# Una virgola separata da IP o host dove ascoltare per le connessioni.
# "*" Ascolta in tutte le interfacce IPv4 "::" Ascolta in tutte le interfacce IPv6.
# Se si desidera specificare porte non default o qualcosa di più complesso,
# Modifica conf.d/master.conf.
# Ascolta = *, ::

# Directory di base dove archiviare i dati di runtime.
# base_dir =/var/run/dovecot/

# Nome di questo istanza. In Multi-Intence Setup Doveadm e altri comandi
# può usare -i <stance_name> per selezionare quale istanza viene utilizzata (un'alternativa
# a -c <config_path>). Il nome dell'istanza viene inoltre aggiunto ai processi DOVECOT
# nell'output PS.
# Instance_name = dovecot

# Messaggio di saluto per i clienti.
# login_greeting = dovecot pronto.

# Elenco separato dello spazio di intervalli di rete affidati. Connessioni da questi
# Gli IP sono autorizzati a sovrascrivere i loro indirizzi e porte IP (per la registrazione e
# Per controlli di autenticazione). disable_plaintext_auth è anche ignorato per
# queste reti. In genere specificheresti i tuoi server proxy IMAP qui.
# login_trusted_networks =

# Elenco separato dello spazio di accesso di accesso di accesso Controllo (ad es. TCPWRAP)
# login_access_sockets =

# Con proxy_maybe = sì se la destinazione proxy corrisponde a uno di questi IP, non farlo
# proxy. Questo non è necessario normalmente, ma può essere utile se la destinazione
# IP è ad es. Un IP di un bilanciamento del carico.
# auth_proxy_self =

# Mostra più titoli di processo verbosio (in PS). Attualmente mostra il nome utente e
# Indirizzo IP. Utile per vedere chi sta effettivamente usando i processi IMAP
# (ad es. Cassette di posta condivisa o se lo stesso UID viene utilizzato per più account).
# verbose_proctitle = no

# Dovrebbero essere uccisi tutti i processi quando il processo master Dovecot si spegne.
# Impostarlo su "no" significa che il dovecot può essere aggiornato senza
# costringendo a chiudere le connessioni client esistenti (anche se questo potrebbe essere
# Un problema se l'aggiornamento è ad es. a causa di una soluzione di sicurezza).
# Shutdown_Client = Sì

# Se diverso da zero, eseguire i comandi di posta tramite così tante connessioni al server Doveadm,
# Invece di eseguirli direttamente nello stesso processo.
# doveadm_worker_count = 0
# Società o host UNIX: porta utilizzata per la connessione al server Doveadm
# DoveADM_Socket_path = DoveADM-Server

# Elenco separati di spazio di variabili di ambiente che sono conservate su Dovecot
# startup e tramandata a tutti i processi dei figli. Puoi anche dare
# Tasto = coppie di valori per impostare sempre impostazioni specifiche.
# Import_environment = tz

## 
## Impostazioni del server del dizionario
## 

# Il dizionario può essere utilizzato per archiviare la chiave = elenchi di valori. Questo è usato da diversi
# plugin. È possibile accedere al dizionario direttamente o sebbene a
# Dizionario Server. I seguenti nomi di dizionario di blocchi di blocco di DtCt a Uris
# Quando viene utilizzato il server. Questi possono quindi essere referenziati usando URI in formato
# "Proxy :: <nome>".

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

# La maggior parte della configurazione effettiva viene inclusa di seguito. I filenati sono
# Sorto per la prima volta per il loro valore ASCII e analizzato in quell'ordine. 00 prefissi
# Nei filamenti hanno lo scopo di rendere più facile capire l'ordinamento.
!include conf.d/*.conf

# Un file di configurazione può anche provare ad essere incluso senza dare un errore se
# Non è trovato:
!include_try local.conf

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

protocols = imap pop3

# Consente a DoveCot di ascoltare tutte le connessioni di input (IPv4 / IPv6)

listen = *, ::
Aggiungi una password per l'utente di Dovecot:

nano config/etc_dovecot_passwd
La prima parte del file, prima del colon, è il nome utente. L'ultima parte, "YourPassword", indica la password che desideri dare al tuo server di posta.

team:{plain}yourpassword
Successivamente, la configurazione Opendkim

nano config/etc_opendkim.conf
E aggiungi queste righe:

# Questa è una configurazione di base per la firma e la verifica. Può essere facilmente
# Adattato per soddisfare un'installazione di base. Vedi OpenDkim.conf (5) e
# /usr/share/doc/opendkim/examples/opendkim.conf.sample per completare
# Documentazione dei parametri di configurazione disponibili.

Syslog			yes
SyslogSuccess		yes
# Log perché no

# Parametri di firma e verifica comuni. In Debian, l'intestazione "da" è
# sovradimso, perché spesso è la chiave di identità utilizzata dai sistemi di reputazione
# e quindi un po 'sensibile alla sicurezza.
Canonicalization	relaxed/simple
Mode			s
SubDomains		no
OversignHeaders		From

# Dominio di firma, selettore e chiave (richiesto). Ad esempio, eseguire la firma
# Per il dominio "Esempio.com" con selettore "2020" (2020._Domainkey.example.com),
# Utilizzando la chiave privata memorizzata in /etc/dkimkeys/example.private. Più granulare
# Le opzioni di configurazione sono disponibili in /usr/share/doc/opendkim/readme.opendkim.
# Dominio Esempio.com
# Selettore 2020
# Keyfile /etc/dkimkeys/example.private

# In Debian, Opendkim funziona come utente "Opendkim". È richiesto un Umask di 007 quando
# Utilizzo di una presa locale con MTA che accedono alla presa come non privilegiato
# utente (ad esempio, postfix). Potrebbe essere necessario aggiungere un "postfix" dell'utente al gruppo
# "Opendkim" in quel caso.
UserID			opendkim
UMask			007

# Socket per la connessione MTA (richiesta). Se l'MTA è all'interno di una prigione di Chroot,
# deve essere assicurato che la presa sia accessibile. In Debian, Postfix è in corso
# Un chroot in/var/spool/postfix, quindi dovrebbe essere una presa unix
# configurato come mostrato nell'ultima riga seguente.
# Socket Local: /run/opendkim/opendkim.sock
# Socket Inet: 8891@localhost
# Socket Inet: 8891
Socket			local:/var/spool/postfix/opendkim/opendkim.sock

PidFile			/run/opendkim/opendkim.pid

# Host per i quali firmare anziché verificare, il valore predefinito è 127.0.0.1. Vedere il
# Sezione operativa di Opendkim (8) per ulteriori informazioni.
# InternalHosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12

# L'ancoraggio di fiducia consente DNSSEC. In Debian, viene fornito il file di ancoraggio di fiducia
# dal pacchetto DNS-Root-Data.
TrustAnchorFile		/usr/share/dns/root.key
# Nameservers 127.0.0.1

# Mappa i domini da tra gli indirizzi ai tasti utilizzati per firmare i messaggi
KeyTable           refile:/etc/opendkim/key.table
SigningTable       refile:/etc/opendkim/signing.table

# Un insieme di host interni la cui posta dovrebbe essere firmata
InternalHosts       /etc/opendkim/trusted.hosts

nano config/etc_default_opendkim
E aggiungi queste righe

# Nota: questo è un file di configurazione legacy. Non è usato da OpenDkim
# Servizio SystemD. Si prega di utilizzare i parametri di configurazione corrispondenti in
# /etc/opendkim.conf invece.
# 
# In precedenza, si avrebbero modificato le impostazioni predefinite qui e quindi eseguire
# /lib/opendkim/opendkim.service.genera per generare systemd override files to to to
# /etc/systemd/system/opendkim.service.d/override.conf e
# /etc/tmpfiles.d/opendkim.conf. Mentre questo è ancora possibile, ora è
# Consigliato per regolare le impostazioni direttamente in /etc/opendkim.conf.
# 
# Daemon_opts = ""
# Modifica in/var/spool/postfix/run/opendkim per utilizzare un socket unix con
# Postfix in un chroot:
# Rundir =/was/spool/postfix/run/opendkim
RUNDIR=/run/opendkim
# 
# Riscaldatore per specificare una presa alternativa
# Si noti che l'impostazione di ciò sovrascriverà qualsiasi valore socket in OpenDkim.conf
# predefinito:
SOCKET="local:/var/spool/postfix/opendkim/opendkim.sock"
# Ascolta tutte le interfacce sulla porta 54321:
# Socket = Inet: 54321
# Ascolta il loopback sulla porta 12345:
# Socket = Inet: 12345@localhost
# Ascolta è 192.0.2.1 è la porta 12345:
# Socket = Inet: 12345@192.0.2.1
USER=opendkim
GROUP=opendkim
PIDFILE=$RUNDIR/$NAME.pid
EXTRAAFTER=
Quando siamo pronti per impostare il nostro server postfix, eseguiremo il codice seguente, con il nome di dominio appropriato incorporato. Inizia creando uno script

touch scripts/postfixsetup
sudo chmod a+x scripts/postfixsetup
nano scripts/postfixsetup
Ora, in Nano, l'editor di testo, modifica questo file in modo che includa il tuo nome di dominio invece di femmebabe.com.

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

./scripts/postfixsetup
Una volta eseguito questo script, copiare l'ultima riga, lo stampa e lo incolla nella configurazione DNS come valore per SendOnly._Domainkey. Questa è la chiave Opendkim utilizzata per identificare il tuo dominio quando si inviano posta sicura. Eccezionale! Entro pochi giorni, dovresti essere in grado di inviare posta dal server a condizione che tutto sia configurato correttamente. Se hai appena configurato il DNS per il tuo server di posta, dovrebbero essere necessarie meno di 72 ore per l'aggiornamento dei record. Di solito è molto più veloce. Puoi verificare se il tuo server funziona utilizzando questo comando, fornito la tua e -mail:

echo “test” | mail -s “Test Email” youremail@gmail.com
Se tutto sembra funzionare correttamente, dovresti essere in grado di inviare e -mail con il tuo server. Se non funziona, prova a guardare i registri per vedere quale potrebbe essere l'errore.

tail –lines 150 /var/log/mail.log
Ciò offrirà informazioni verbose sulla posta inviata dal server e se funziona correttamente. Dovresti essere in grado di vedere l'email anche nella tua casella di posta, se non è lì, controlla la cartella spam. Dovrai anche configurare le tue impostazioni in Impostazioni.py in modo che il tuo server di posta elettronica possa parlare con la tua app Django, il progetto. Aggiungi o sostituisci queste righe nelle impostazioni

EMAIL_HOST = DOMAIN
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_ADDRESS = 'team@femmebabe.com'
EMAIL_HOST_USER = 'team' # 'Love@mamasheen.com'
EMAIL_HOST_PASSWORD = config['EMAIL_HOST_PASSWORD']
DEFAULT_FROM_EMAIL = '{} <{}>'.format(SITE_NAME, EMAIL_HOST_USER)
Si noti che stiamo utilizzando un file di configurazione per ottenere la password. Cariciamo questo file nelle impostazioni come così, all'inizio del file.:

import os
import json

# Apri e caricano configurazione
with open('/etc/config.json') as config_file:
    config = json.load(config_file)
Crea questo file e aggiungiamo una chiave segreta ad esso, nonché la password della posta. Per generare una chiave segreta, usa questo comando, con qualsiasi lunghezza che ti piace alla fine:

openssl rand -base64 64
Ora, copia il testo che OpenSSL ha generato e modifica /etc/config.json

sudo nano /etc/config.json
Aggiungi le seguenti righe al tuo file, con la chiave che OpenSSL generata come chiave segreta.

{
	"SECRET_KEY": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX-generated-using-openssl)",
	"EMAIL_HOST_PASSWORD": "yourpassword"
}
Il formato JSON è semplice e facile da usare, possiamo dichiarare anche altre chiavi che vogliamo usare nel nostro progetto in questo modo e tenerle separate dalla nostra directory del progetto in modo che altri utenti non possano scriverli e quindi non possono essere letti Solo dalla nostra directory del progetto. Questa è una pratica consigliata per le chiavi API, di cui useremo più di alcuni qui. Ti consigliamo anche di eseguire il backup del tuo progetto per assicurarti che tutto sia salvato e sarai in grado di recuperare il tuo lavoro in seguito anche se non desideri più noleggiare un server.

sudo backup
Ora, prova a inviare un'e -mail HTML dal server Web, a condizione che l'invio della riga di comando è funzionante. Interroga l'istanza dell'utente nella shell e invia un'e -mail HTML a quell'utente tramite Django. Cambia il mio nome nel codice, Charlotte, nel tuo nome utente.

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()
Se il primo comando non funziona, assicurati di utilizzare

source venv/bin/activate
A condizione che tutto sia impostato correttamente, ora riceverai un'e -mail di benvenuto nella tua casella di posta inviata dalla tua app web. Buon lavoro! Hai fatto molta strada. Volevo aggiungere, se stai lottando con qualsiasi errore mentre lavori su un progetto come questo, non esitare a cercare risposte e chiedere aiuto. Google, tra gli altri motori di ricerca, sono grandi risorse per cercare aiuto per la programmazione. Basta cercare l'errore che stai ricevendo e sarai in grado di vedere come le altre persone risolvono il problema. Inoltre, sei il benvenuto a contattarmi, i tuoi educatori (insegnanti, professori, tutor), tutti i coetanei su Internet che sono disponibili per l'aiuto di programmazione o consultare questo libro o altre risorse per trovare soluzioni ai problemi che stai riscontrando. Capisco che non è facile, ma anche se hai letto così lontano e non stai scrivendo alcun codice, stai imparando molto sulla costruzione di un'app Web da zero. Passati sulla schiena, stai andando alla grandelavoro. Grazie per aver dedicato del tempo a leggere questa guida Web di terza edizione. Nelle edizioni future, includerò più degli esempi importanti discussi all'inizio del documento e ci immergeremo molto più a fondo nel mondo dello sviluppo di software e hardware. Resta sintonizzato per quello che verrà e non vedo l'ora di insegnarti come costruire software incredibile. Ci vediamo al prossimo






Vicino
Pagina 1
Salto
Vedi l'articolo completo
Continua a leggere

Acquistare | Acquista con criptovalute



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


(Fare clic o toccare per scaricare l'immagine)
Intrattenimento professionale, foto, video, audio, live streaming e gameplay casual, nonché scansione di documenti d'identità, sviluppo web e servizi di maternità surrogata.

Lasciami una mancia in Bitcoin utilizzando questo indirizzo: 3KhDWoSve2N627RiW8grj6XrsoPT7d6qyE

© Glam Girl X 2025

Termini di servizio