Desidero poter impostare un'opzione nelle impostazioni dell'utente che impone loro di cambiare la password al successivo accesso all'interfaccia di amministrazione. È possibile? Come dovrebbe essere implementato? Sto usando il modello di autenticazione predefinito in questo momento, ma non contrario a modificarlo o modificarlo. Grazie per qualsiasi aiuto.È possibile implementare una funzionalità di tipo "modifica password all'accesso successivo" nell'amministratore di django?
risposta
Da un thread sul Django Users mailing list:
Questo non è l'ideale, ma dovrebbe funzionare (o prompt di qualcuno a proporre qualcosa di meglio).
aggiungere una tabella one-to-one per l'utente, con un campo che contiene la password iniziale (criptato, ovviamente, in modo che sembra la password nella tabella
auth_user
).Quando l'utente esegue il login, verifica la pagina di accesso per verificare se le password corrispondono a . In tal caso, reindirizzare alla pagina di modifica della password anziché alla pagina di reindirizzamento normale .
Sono in procinto di farlo da solo. Sono necessari tre componenti: un profilo utente (se non già in uso sul tuo sito), un componente middleware e un segnale pre_save.
Il mio codice per questo è in un'app denominata "account".
# myproject/accounts/models.py
from django.db import models
from django.db.models import signals
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
force_password_change = models.BooleanField(default=False)
def create_user_profile_signal(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
def password_change_signal(sender, instance, **kwargs):
try:
user = User.objects.get(username=instance.username)
if not user.password == instance.password:
profile = user.get_profile()
profile.force_password_change = False
profile.save()
except User.DoesNotExist:
pass
signals.pre_save.connect(password_change_signal, sender=User, dispatch_uid='accounts.models')
signals.post_save.connect(create_user_profile_signal, sender=User, dispatch_uid='accounts.models')
Innanzitutto, creiamo un profilo utente con una chiave esterna per l'utente. Il valore booleano force_password_change
, come viene descritto nel nome, verrà impostato su true per un utente ogni volta che si desidera forzare la modifica della password. Potresti fare qualsiasi cosa qui però. Nella mia organizzazione, abbiamo anche scelto di implementare una modifica obbligatoria ogni 90 giorni, quindi ho anche un DateTimeField che memorizza l'ultima volta che un utente ha cambiato la password. Quindi lo hai impostato nel segnale pre_save, password_changed_signal
.
In secondo luogo, abbiamo il create_user_profile_signal
. Questo è per lo più aggiunto solo per completezza. Se stai solo aggiungendo i profili utente al tuo progetto, avrai bisogno di un segnale post_save che crei un profilo utente ogni volta che viene creato un utente. Questo ha portato a termine questo compito.
In terzo luogo, abbiamo il password_changed_signal
. Questo è un segnale pre_save perché a questo punto del processo la riga effettiva nella tabella Utente non è stata aggiornata. Pertanto, possiamo accedere sia alla password precedente che alla nuova password che sta per essere salvata. Se i due non corrispondono, significa che l'utente ha cambiato la propria password e possiamo quindi ripristinare il valore booleano force_password_change. Questo sarebbe il punto, anche dove ti occuperesti di tutte le altre cose che hai aggiunto come l'impostazione di DateTimeField precedentemente menzionate.
Le ultime due righe collegano le due funzioni ai segnali appropriati.
Se non l'hai già, si dovrà anche aggiungere la seguente riga a del progetto settings.py
(cambiando l'etichetta app e il nome del modello per abbinare il vostro setup):
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
che copre le nozioni di base. Ora abbiamo bisogno di un componente middleware per verificare lo stato del nostro flag force_password_change
(e qualsiasi altro controllo necessario).
# myproject/accounts/middleware.py
from django.http import HttpResponseRedirect
import re
class PasswordChangeMiddleware:
def process_request(self, request):
if request.user.is_authenticated() and \
re.match(r'^/admin/?', request.path) and \
not re.match(r'^/admin/password_change/?', request.path):
profile = request.user.get_profile()
if profile.force_password_change:
return HttpResponseRedirect('/admin/password_change/')
This molto semplici ganci middleware nella process_request
fase del processo di caricamento della pagina. Controlla che 1) l'utente abbia già effettuato l'accesso, 2) stiano tentando di accedere ad alcune pagine nell'amministratore e 3) la pagina a cui stanno accedendo non sia la stessa pagina di modifica della password (altrimenti si otterrebbe un ciclo infinito di reindirizzamenti). Se tutti questi sono veri e il flag force_password_change
è stato impostato su True
, l'utente viene reindirizzato alla pagina di modifica della password. Non saranno in grado di navigare da nessun'altra parte finché non cambiano la loro password (attivando il segnale pre_save discusso in precedenza).
Infine, non vi resta che aggiungere questo middleware del progetto settings.py
(ancora una volta, la modifica del percorso di importazione, se necessario):
MIDDLEWARE_CLASSES = (
# Other middleware here
'myproject.accounts.middleware.PasswordChangeMiddleware',
)
In realtà, il mio unico problema al momento è modificare la pagina della password di modifica dell'amministratore in modo da poter visualizzare un messaggio all'utente spiegando perché sono finiti qui. Il semplice inserimento di un modello di sostituzione nella directory dei modelli del progetto non funziona (apparentemente è completamente ignorato). E l'impostazione di 'admin.site.password_change_template' (nuova in 1.2) sul percorso del tuo modello di override funziona solo in parte. Il modello è stato modificato abbastanza bene, ma sembra perdere il contesto della vista (mancano tutti i campi modulo, ecc.). Se qualcuno può aiutare con questo, per favore chime. –
Sembra una soluzione piuttosto completa – cerberos
Ho usato la soluzione di Chris Pratt, con un piccolo cambiamento: invece di utilizzare un middleware, che sarebbe stato eseguito per ogni pagina con il conseguente utilizzo delle risorse, ho pensato che avrei solo intercettato la vista di login.
Nel mio urls.py Ho aggiunto questo ai miei urlpatterns:
url(r'^accounts/login/$', 'userbase.views.force_pwd_login'),
poi ho aggiunto il testo seguente userbase.views:
def force_pwd_login(request, *args, **kwargs):
response = auth_views.login(request, *args, **kwargs)
if response.status_code == 302:
#We have a user
try:
if request.user.get_profile().force_password_change:
return redirect('django.contrib.auth.views.password_change')
except AttributeError: #No profile?
pass
return response
Sembra funzionare senza problemi su Django 1.2, ma non ho motivo di credere che 1.3+ dovrebbe avere problemi con esso.
Controlla questo semplice pacchetto basato sulla sessione (Testato con django 1.8). https://github.com/abdullatheef/django_force_reset_password
Crea visualizzazione personalizzata in myapp.views.py
class PassWordReset(admin.AdminSite):
def login(self, request, extra_context=None):
if request.method == 'POST':
response = super(PassWordReset, self).login(request, extra_context=extra_context)
if response.status_code == 302 and request.user.is_authenticated():
if not "fpr" in request.session or request.session['fpr']:
request.session['fpr'] = True
return HttpResponseRedirect("/admin/password_change/")
return response
return super(PassWordReset, self).login(request, extra_context=extra_context)
def password_change(self, request, extra_context=None):
if request.method == 'POST':
response = super(PassWordReset, self).password_change(request, extra_context=extra_context)
if response.status_code == 302 and request.user.is_authenticated():
request.session['fpr'] = False
return response
return super(PassWordReset, self).password_change(request, extra_context=extra_context)
pfr_login = PassWordReset().login
pfr_password_change = PassWordReset().admin_view(PassWordReset().password_change, cacheable=True)
Poi nel progetto/urls.py
from myapp.views import pfr_password_change, pfr_login
urlpatterns = [
......
url(r'^admin/login/$', pfr_login),
url(r'^admin/password_change/$', pfr_password_change),
url(r'^admin/', admin.site.urls),
....
]
Quindi aggiungere questo middleware frontend/middleware.py
class FPRCheck(object):
def process_request(self, request):
if request.user.is_authenticated() \
and re.match(r'^/admin/?', request.path) \
and (not "fpr" in request.session or ("fpr" in request.session and request.session['fpr'])) \
and not re.match(r"/admin/password_change|/admin/logout", request.path):
return HttpResponseRedirect("/admin/password_change/")
Ordine di middleware
MIDDLEWARE_CLASSES = [
....
'myapp.middleware.FPRCheck'
]
Nota
- Questo non avrà bisogno di alcun modello extra.
- Funziona anche con qualsiasi motore di sessione.
- Nessuna query DB all'interno del middleware.
@ EBH ha aggiornato la risposta – itzMEonTV
Questo è il middleware che uso con Django 1.11:
# myproject/accounts/middleware.py
from django.http import HttpResponseRedirect
from django.urls import reverse
class PasswordChangeMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
next = reverse('client:password-update')
if request.user.is_authenticated() and request.path != next:
if request.user.account.force_password_change:
return HttpResponseRedirect(next)
return response
Ancora aggiungendolo alla lista impostazioni middleware:
MIDDLEWARE_CLASSES = (
# Other middleware here
'myproject.accounts.middleware.PasswordChangeMiddleware',
)
- 1. Implementare la password di modifica con Loopback
- 2. È possibile implementare la funzionalità SystemTrayIcon nell'applicazione Qt Quick
- 3. Password dimenticata: qual è il metodo migliore per implementare una funzione di password dimenticata?
- 4. È possibile implementare la funzionalità di rendimento di Python nella C libera?
- 5. Cambio di password Django modulo di visualizzazione
- 6. Il test successivo è attivato con modifica?
- 7. L'API di iscrizione ASP.NET modifica la password della password
- 8. Django problemi di password
- 9. Come implementare la funzionalità di annullamento?
- 10. Come posso implementare funzionalità di Single Sign-On con Check_MK?
- 11. Override Iscrizione di Django allauth URL "successivo" di reindirizzamento
- 12. Problema di modifica della password di Django, super (type, obj): obj deve essere un'istanza o sottotipo di tipo
- 13. utente django disconnesso dopo la modifica della password
- 14. Meteor: modifica una password utente SENZA uscire?
- 15. È possibile limitare la funzionalità della DLL?
- 16. Liferay - personalizzare la password di modifica
- 17. È possibile implementare manualmente le associazioni Cocoa?
- 18. Implementazione della funzionalità di password dimenticata in Java
- 19. Django force password expiration
- 20. Hadoop e Django, è possibile?
- 21. Qual è il gateway di pagamento possibile più semplice da implementare? (usando Django)
- 22. cercando di implementare un pulsante 'successivo' usando twitter bootstrap-tabs.js
- 23. Modifica password Derby DB
- 24. funzionalità di ricerca sul sito django multilingue
- 25. Come implementare la funzionalità di Excel Solver in C#?
- 26. È possibile configurare le funzionalità di Linux per utente?
- 27. integrare validatori di password django con framework django validate_password
- 28. Imposizione di una lunghezza minima nella password Django
- 29. Django modello di modifica Disegno
- 30. Rimuovere la funzionalità "Aggiungi" nell'amministratore di Django
Volesse che impedisce agli utenti di navigare semplicemente uscire dalla pagina di modifica della password e andare da qualche altra parte? (senza mai cambiare la password) – bparker