Punti salienti di Django: modelli utente e autenticazione (parte 1)

Pubblicato: 2022-03-10
Riepilogo rapido ↬ Uno dei motivi principali per sviluppare un sito dinamico è autenticare gli utenti e limitare i contenuti. Django fornisce un potente modello utente pronto all'uso e in questo articolo illustreremo il modo migliore per fornire flussi di autenticazione utente sicuri e intuitivi.

Esistono due tipi di siti Web: statici e dinamici. Django è un framework per lo sviluppo di siti web dinamici. Sebbene un sito Web statico sia uno che presenta esclusivamente informazioni, non vi è alcuna interazione (a parte le semplici richieste di pagina) che viene registrata su un server. In un sito Web statico, il server invia HTML, CSS e JavaScript a un client e il gioco è fatto. Più funzionalità richiedono un sito Web dinamico, in cui il server archivia le informazioni e risponde all'interazione dell'utente oltre alla semplice pubblicazione delle pagine. Uno dei motivi principali per sviluppare un sito dinamico è autenticare gli utenti e limitare i contenuti.

Scrivere, distribuire e amministrare un sito Web statico è un ordine di grandezza più facile, più economico e più sicuro di un sito dinamico. Pertanto, dovresti creare un sito Web dinamico solo se le capacità aggiuntive del paradigma dinamico sono necessarie per il tuo progetto. Django semplifica e snellisce il processo di creazione di un sito dinamico con i suoi componenti integrati. Essendo uno dei componenti primari di un'applicazione Web dinamica, l'oggetto "account utente", come la ruota, è tentato di reinventare, ma la forma standard è appropriata per la maggior parte degli usi. Django fornisce un potente modello utente pronto all'uso e in questo articolo illustreremo il modo migliore per fornire flussi di autenticazione utente sicuri e intuitivi.

Ulteriori parti della serie:

  • Punti salienti di Django: la creazione di modelli salva le linee (parte 2)
  • Punti salienti di Django: modelli, amministrazione e sfruttamento del database relazionale (parte 3)
  • Punti salienti di Django: gestione di risorse statiche e file multimediali (parte 4)

Prepararsi

Se desideri creare la tua applicazione Django per sperimentare i concetti di questo articolo, puoi creare una directory (e preferibilmente un ambiente virtuale) e quindi eseguire i seguenti comandi:

 pip install django django-admin startproject PROJECTNAME cd PROJECTNAME python manage.py startapp APPNAME python manage.py migrate python manage.py runserver

Se stai cercando una procedura dettagliata per creare il tuo primo progetto Django, il sito Web di Django ne offre uno fantastico. In questo articolo, non utilizziamo un progetto di esempio, ma i concetti discussi si applicheranno a quasi tutte le applicazioni Django.

Altro dopo il salto! Continua a leggere sotto ↓

Modello utente standard

Fondamentalmente, il concetto di account utente esiste per due motivi: controllo degli accessi e stato dell'applicazione personalizzato. Il controllo di accesso è l'idea che le risorse su un sistema siano disponibili solo per alcuni utenti. Lo stato personalizzato dipende fortemente dallo scopo dell'applicazione, ma può includere impostazioni, dati o qualsiasi altro record specifico di un singolo utente. Il modello User stock di Django fornisce approcci sensati a entrambi i casi d'uso.

Inizialmente, ci sono due tipi di utenti in un'applicazione Django: account superutente e utenti regolari. I superutenti hanno tutti gli attributi e i privilegi degli account regolari, ma hanno anche accesso al pannello di amministrazione di Django, una potente applicazione che esploreremo in dettaglio in un prossimo articolo. In sostanza, i superutenti possono creare, modificare o eliminare qualsiasi dato nell'applicazione, inclusi altri account utente.

Fondamentalmente, il concetto di account utente esiste per due motivi: controllo degli accessi e stato dell'applicazione personalizzato.

Per creare un superutente sulla tua applicazione Django, esegui:

 python manage.py createsuperuser

L'altro vantaggio di un account utente è la memorizzazione di dati personalizzati nel database. Per impostazione predefinita, Django richiede solo un nome utente e una password, ma fornisce campi opzionali per consentire agli utenti di inserire nome, cognome e indirizzo e-mail. Puoi leggere un riferimento completo del modello sul sito Web di Django. Discuteremo di estendere questo modello di seguito.

Sicurezza e affidabilità

Django include un sostanziale middleware di gestione delle password con il modello utente. Le password utente devono contenere almeno 8 caratteri, non interamente numeri, non corrispondere troppo al nome utente e non essere in un elenco delle 20.000 password più comuni. I moduli delle azioni Django convalidano questi requisiti. Quando una password viene inviata al server, viene crittografata prima di essere archiviata, per impostazione predefinita utilizzando l'algoritmo PBKDF2 con un hash SHA256. Nel complesso, il sistema di password predefinito fornisce una solida sicurezza senza alcuno sforzo da parte dello sviluppatore. A meno che tu non abbia competenze specifiche e un motivo convincente per modificare il modo in cui le password vengono gestite nella tua applicazione, non modificare questo comportamento.

Un altro comodo integrato è il requisito che i nomi utente siano univoci. Se ci pensi, se ci fossero due utenti con il nome utente "djangofan1" e il server ricevesse una richiesta di accesso per quel nome utente, non saprebbe quale utente stava tentando di accedere all'applicazione. Sfortunatamente per loro, il secondo utente che proverà a registrarsi con “djangofan1” dovrà scegliere un nome diverso, forse “djangofan2”. Questo vincolo di unicità viene applicato a livello di database ma viene nuovamente verificato dai moduli forniti da Django.

Infine, una nota sull'eliminazione degli utenti. Sebbene l'eliminazione degli utenti sia una possibilità, le applicazioni più complesse avranno un numero di risorse legate a ciascun account utente. Se desideri eliminare in modo efficace un utente senza rimuovere gli oggetti allegati, imposta invece il campo is_active dell'utente su false. Quindi, quelle altre risorse rimangono associate all'account anziché essere eliminate e l'account utente può essere riattivato in qualsiasi momento da un superutente. Tieni presente che ciò non libera il nome utente, ma l'impostazione dell'account come inattivo insieme alla modifica del nome utente su un valore casuale e univoco potrebbe ottenere lo stesso effetto. Infine, se le politiche del tuo sito o le leggi locali applicabili richiedono che gli account utente siano completamente eliminati, l'approccio is_active non sarà sufficiente.

A meno che tu non abbia competenze specifiche e un motivo convincente per modificare il modo in cui le password vengono gestite nella tua applicazione, non modificare questo comportamento.

Uso standard

Quando si desidera registrare un nuovo account utente, la vista per farlo sarà probabilmente simile alla seguente in views.py :

 from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login from django.contrib.auth.forms import UserCreationForm def signup(request): if request.user.is_authenticated: return redirect('/') if request.method == 'POST': form = UserCreationForm(request.POST) if form.is_valid(): form.save() username = form.cleaned_data.get('username') password = form.cleaned_data.get('password1') user = authenticate(username=username, password=password) login(request, user) return redirect('/') else: return render(request, 'signup.html', {'form': form}) else: form = UserCreationForm() return render(request, 'signup.html', {'form': form})

Analizziamolo:

  • Se l'utente ha già effettuato l'accesso, lo reindirizzeremo lontano dalla pagina di registrazione.
  • Se il metodo di richiesta è POST, significa che il modulo per la creazione di un utente è già stato compilato ed è ora di creare un utente.
    • Innanzitutto, costruisci l'oggetto modulo sul back-end con i dati forniti dall'utente.
    • Se il modulo è valido, crea l'utente ed effettua il login, quindi invialo alla pagina principale.
    • Altrimenti, scaricali nuovamente nella pagina di creazione dell'utente con informazioni su quali dati non erano validi (ad esempio, hanno richiesto un nome utente già in uso).
  • In caso contrario, l'utente accede alla pagina per la prima volta e deve essere visualizzato con il modulo per la creazione di un nuovo account.

Ora esaminando l'accesso all'account:

 from django.shortcuts import render, redirect from django.contrib.auth import authenticate, login from django.contrib.auth.forms import AuthenticationForm def signin(request): if request.user.is_authenticated: return render(request, 'homepage.html') if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] user = authenticate(request, username=username, password=password) if user is not None: login(request, user) return redirect('/') else: form = AuthenticationForm(request.POST) return render(request, 'signin.html', {'form': form}) else: form = AuthenticationForm() return render(request, 'signin.html', {'form': form})

Un'altra rottura:

  • Se l'utente ha già effettuato l'accesso, lo reindirizzeremo lontano dalla pagina di accesso.
  • Se il metodo di richiesta è POST, significa che il modulo per l'accesso è stato compilato ed è ora di autenticare l'utente su un account.
    • Innanzitutto, autenticare l'utente con i dati forniti dall'utente
    • Se il nome utente e la password corrispondono a un account, accedi all'utente
    • In caso contrario, riportali alla pagina di accesso con le informazioni del modulo precompilate
  • In caso contrario, l'utente accede alla pagina per la prima volta e deve essere soddisfatto del modulo per l'accesso.

Infine, i tuoi utenti potrebbero voler disconnettersi. Il codice base per questa richiesta è semplice:

 from django.shortcuts import render, redirect from django.contrib.auth import logout def signout(request): logout(request) return redirect('/')

Una volta che l'utente ha effettuato l'accesso al proprio account e fino a quando non si è disconnesso da quel dispositivo, sta effettuando una "sessione". Durante questo periodo, le successive richieste dal proprio browser potranno accedere alle pagine di solo account. Un utente può avere più sessioni attive contemporaneamente. Per impostazione predefinita, le sessioni non scadono.

Mentre un utente ha una sessione attiva sul proprio dispositivo, si registrerà come True per il controllo request.user.is_authenticated . Un altro modo per limitare le pagine ai soli utenti che hanno effettuato l'accesso è il decoratore @login_required sopra una funzione. Ci sono molti altri modi per ottenere lo stesso, dettagliati qui.

Se questo livello di configurazione è superiore a quello che si desidera eseguire, esiste un approccio ancora più immediato alla gestione degli utenti. Queste viste di autenticazione stock forniscono percorsi, viste e moduli standard per la gestione degli utenti e possono essere modificate assegnandole a URL personalizzati, passando modelli personalizzati o persino suddividendo le viste in sottoclassi per un maggiore controllo.

Estendere il modello utente

In genere, è necessario espandere il modello utente per fornire controlli di accesso più dettagliati o archiviare più dati utente per account. Esploreremo diversi casi comuni di seguito.

Eliminazione di campi dal modello utente

Contrariamente all'intestazione di questa sezione, in realtà non consiglio di apportare modifiche direttamente al modello utente o allo schema del database associato! Il modello utente generico viene stabilito nel database per impostazione predefinita durante l'installazione di un nuovo progetto Django. Tanto è legato al modello utente predefinito che modificarlo potrebbe avere effetti imprevisti nella tua applicazione (soprattutto se stai utilizzando librerie di terze parti), di conseguenza, l'aggiunta o la rimozione di campi non è consigliata e non è facilitata dal framework.

Per impostazione predefinita, gli unici due campi richiesti per un utente sono nome utente e password. Se non desideri utilizzare nessuno degli altri campi, ignora semplicemente la loro esistenza, poiché un utente può essere creato senza nome, cognome o indirizzo e-mail. C'è una raccolta di campi predefiniti come last_login e date_joined che possono anche essere ignorati se non li vuoi. Se avessi un vincolo tecnico effettivo che richiedeva l'eliminazione di campi facoltativi dal modello utente, lo sapresti già e non avresti bisogno di questo articolo.

Un motivo comune per cui potresti voler eliminare un campo nel modello utente è eliminare il nome utente a favore dell'e-mail come identificatore univoco. In tal caso, durante la creazione dell'utente dai dati del modulo o l'autenticazione di una richiesta, è sufficiente inserire l'indirizzo e-mail come nome utente oltre al suo utilizzo nel campo e-mail. Il campo nome utente applicherà comunque il vincolo di unicità quando i nomi utente vengono formattati come indirizzi e-mail. Le stringhe sono stringhe, saranno trattate allo stesso modo.

Tanto è legato al modello utente predefinito che modificarlo potrebbe avere effetti imprevisti nella tua applicazione, soprattutto se stai utilizzando librerie di terze parti.

Aggiunta di campi con un profilo

Allo stesso modo, se desideri memorizzare informazioni aggiuntive sui tuoi utenti, non dovresti tentare di modificare il modello utente predefinito. Anche per un singolo campo, definisci il tuo oggetto con una relazione uno-a-uno con gli utenti esistenti. Questo modello extra è spesso chiamato Profile . Supponi di voler memorizzare un secondo nome e una data di nascita (dob) per ciascun utente. Il Profile sarebbe definito come segue in models.py :

 from django.db import models from django.contrib.auth.models import User class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) middle_name = models.CharField(max_length=30, blank=True) dob = models.DateField(null=True, blank=True)

Controllo accessi personalizzato

L'applicazione potrebbe aver richiesto una distinzione tra diversi tipi di utenti per l'accesso a informazioni e funzioni. Django fornisce un sistema per creare un controllo degli accessi personalizzato a grana fine: permessi e gruppi.

Le autorizzazioni sono oggetti che determinano l'accesso alle risorse. Un utente può avere una o più autorizzazioni. Ad esempio, potrebbero avere accesso in lettura a una tabella di prodotti e accesso in scrittura a una tabella di clienti. L'esatta implementazione delle autorizzazioni varia sostanzialmente in base all'applicazione, ma l'approccio di Django rende intuitivo definire le autorizzazioni per i dati e assegnarle agli utenti.

Le applicazioni per aziende e altre grandi organizzazioni spesso implementano il controllo degli accessi basato sui ruoli. In sostanza, un utente può avere vari ruoli, ognuno dei quali dispone di determinate autorizzazioni. Lo strumento di Django per implementare questo modello è il Gruppo. Un gruppo può avere un numero qualsiasi di autorizzazioni, ognuna delle quali può essere assegnata a un numero qualsiasi di gruppi. Un utente ottiene quindi le autorizzazioni non direttamente ma tramite l'appartenenza a gruppi, semplificando l'amministrazione dell'applicazione.

Panoramica: integrazione di un fornitore di servizi di pagamento

Il processo preciso di integrazione di un elaboratore di pagamento varia sostanzialmente in base all'applicazione e al fornitore. Tuttavia, tratterò il processo in termini generali.

Uno dei principali vantaggi dell'esternalizzazione dei pagamenti è che il fornitore è responsabile dell'archiviazione e della convalida di dati altamente regolamentati come le informazioni sulla carta di credito. Il servizio condivide quindi alcuni token utente univoci con la tua applicazione insieme ai dati sulla cronologia dei pagamenti. Come per aggiungere il profilo, puoi creare un modello associato User principale e archiviare i dati in quel modello. Come per le password, è importante seguire l'integrazione fornita con il provider per evitare di archiviare informazioni sensibili in modo improprio.

Panoramica: accesso social

L'altro campo ampio e complesso su cui voglio soffermarmi brevemente è il social sign-in. Grandi piattaforme come Facebook e Google, così come siti più piccoli come GitHub, forniscono API per l'utilizzo dei loro servizi per autenticare gli utenti. Simile a un fornitore di servizi di pagamento, questo crea un record nel tuo database che collega un account a un account nel loro database.

Potresti voler includere l'autenticazione sociale nel tuo sito per facilitare la registrazione degli utenti senza creare un nuovo set di credenziali di accesso. Se la tua applicazione si rivolge esclusivamente ai clienti che già utilizzano un sito specifico che fornisce un'opzione di autenticazione sociale, potrebbe aiutarti ad attirare utenti da quel mercato abbassando la barriera di accesso. Inoltre, se la tua applicazione intende accedere ai dati dell'utente da un servizio di terze parti, il collegamento degli account durante l'autenticazione semplifica il processo di concessione delle autorizzazioni.

Tuttavia, ci sono aspetti negativi nell'utilizzo dell'autenticazione sociale. Le modifiche o le interruzioni dell'API da parte del fornitore di terze parti potrebbero interrompere i tempi di attività dell'applicazione o le attività di sviluppo. In generale, le dipendenze esterne aggiungono complessità all'applicazione. Infine, vale la pena considerare le politiche di raccolta e utilizzo dei dati di terze parti con cui ti stai integrando e assicurarti che siano in linea con le tue aspettative e quelle dei tuoi utenti.

Se decidi che l'autenticazione sociale è giusta per la tua applicazione, fortunatamente c'è una libreria per questo. Python Social Auth per Django è un pacchetto per abilitare le funzionalità dell'ecosistema di autenticazione sociale di Python nei progetti Django.

Avvolgendo

Per quanto universale sia l'account utente, il suo uso diffuso può portare a risolvere gli stessi problemi inutilmente. Si spera che questo articolo ti abbia mostrato la gamma di potenti funzionalità disponibili in Django e ti abbia dato una comprensione delle responsabilità di base di un'applicazione durante la creazione di account utente.

Django Highlights è una serie che introduce importanti concetti di sviluppo web in Django. Ogni articolo è scritto come una guida autonoma a un aspetto dello sviluppo di Django inteso ad aiutare gli sviluppatori e i designer front-end a raggiungere una comprensione più profonda dell '"altra metà" della base di codice. Questi articoli sono costruiti principalmente per aiutarti a comprendere la teoria e le convenzioni, ma contengono alcuni esempi di codice, che sono scritti in Django 3.0. Diversi concetti che abbiamo toccato in questo articolo, inclusi modelli, utenti amministratori, modelli e moduli, verranno esplorati individualmente in dettaglio nei futuri articoli di questa serie.

Ulteriori parti della serie:

  • Punti salienti di Django: la creazione di modelli salva le linee (parte 2)
  • Punti salienti di Django: modelli, amministrazione e sfruttamento del database relazionale (parte 3)
  • Punti salienti di Django: gestione di risorse statiche e file multimediali (parte 4)