68 votes

Vérifier que l'utilisateur s'est bien connecté

Comment puis-je tester qu'un utilisateur est connecté après avoir soumis le formulaire d'inscription ?

J'ai essayé ce qui suit mais cela renvoie True avant même d'avoir ajouté la logique de connexion à ma vue d'enregistrement.

def test_that_user_gets_logged_in(self):
    response = self.client.post(reverse('auth-registration'), 
                                { 'username':'foo', 
                                  'password1':'bar', 
                                  'password2':'bar' } )

    user = User.objects.get(username='foo')
    assert user.is_authenticated()

Le code qui est testé :

class RegistrationView(CreateView):
    template_name = 'auth/registration.html'
    form_class = UserCreationForm
    success_url = '/'

    def auth_login(self, request, username, password):
        '''
        Authenticate always needs to be called before login because it
        adds which backend did the authentication which is required by login.
        '''

        user = authenticate(username=username, password=password)
        login(request, user)

    def form_valid(self, form):
        '''
        Overwrite form_valid to login.
        '''

        #save the user
        response = super(RegistrationView, self).form_valid(form)

        #Get the user creditials
        username = form.cleaned_data['username']
        password = form.cleaned_data['password1']

        #authenticate and login
        self.auth_login(self.request, username, password)

        return response

0 votes

Avez-vous essayé response.request.user.is_authenticated() ?

1 votes

Je l'ai fait mais l'objet de la demande n'a pas d'objet utilisateur.

103voto

Chronial Points 15402

Vous pouvez utiliser le get_user de la méthode auth module. Il dit qu'il veut une requête comme paramètre, mais il n'utilise jamais que le module session de la demande. Et il se trouve que notre Client a cet attribut.

from django.contrib import auth
user = auth.get_user(self.client)
assert user.is_authenticated

0 votes

+1 c'est une excellente réponse et cela ferait une affirmation utile : gist.github.com/bengolder/c9dc7006f9d6b4d17d5af5465115df73

4 votes

Cela ne fonctionne pas à partir de la version 2.0.5 de Django. Premièrement is_authenticated est maintenant une propriété et non un appelant. Il ne renvoie pas true même en cas de connexion réussie.

1 votes

self.client.session['_auth_user_id'] (comme discuté dans cette réponse ) fonctionne avec Django >=2.0.

83voto

emyller Points 829

Ce n'est pas la meilleure réponse . Voir https://stackoverflow.com/a/35871564/307511

Chronial a donné un excellent exemple sur la façon de faire cette affirmation ci-dessous. Sa réponse meilleure que la mienne pour le code actuel.


La méthode la plus simple pour tester si un utilisateur est connecté est de tester l'objet Client :

self.assertIn('_auth_user_id', self.client.session)

Vous pouvez également vérifier si un utilisateur spécifique est connecté :

self.assertEqual(int(self.client.session['_auth_user_id']), user.pk)

À titre d'information supplémentaire, le response.request n'est pas un HttpRequest Il s'agit plutôt d'un dict ordinaire contenant des informations sur la requête en cours, de sorte qu'il n'aura pas l'attribut user de toute façon.

De même, le fait de tester le response.context n'est pas sûr parce que vous n'avez pas toujours un contexte.

12 votes

En guise d'assurance supplémentaire, vous pouvez effectuer le même test mais en utilisant la valeur de la variable SESSION_KEY variable. Comme ceci : from django.contrib.auth import SESSION_KEY self.assertTrue(SESSION_KEY in self.client.session) Vous pouvez voir que cela est utilisé dans l'application d'authentification dans le cadre de Django : github...test/views.py Ils disposent également d'une fonction pratique permettant de vérifier qu'un utilisateur s'est déconnecté : github...test/views.py

0 votes

Merci pour le complément, je n'étais pas au courant. :)

2 votes

Le lien vers le premier commentaire est cassé - c'est ici qu'il est hébergé maintenant. github.com/django/django-old/blob/master/django/contrib/auth/

11voto

Jonatan Littke Points 2733

Le TestClient de Django possède un méthode de connexion qui renvoie Vrai si l'utilisateur s'est connecté avec succès.

5 votes

Sauf que ce n'est pas le test qui fait l'appel à login().

0 votes

@Manur que voulez-vous dire ? Est-ce que cela change l'utilité de self.assertTrue(self.client.login(credentials)) ?

9voto

Bernhard Vallant Points 18035

La méthode is_authenticated() sur le User modèle retourne toujours True . False est retourné pour request.user.is_authenticated() dans le cas où request.user est une instance de AnonymousUser qui is_authenticated() retourne toujours False . Pendant le test, vous pouvez jeter un coup d'œil à response.context['request'].user.is_authenticated() .

Vous pouvez également essayer d'accéder à une autre page dans le test qui nécessite d'être connecté, et voir si response.status renvoie à 200 ou 302 (redirect from login_required ).

0 votes

Quelle pourrait être la raison pour laquelle je n'ai pas d'objet response.request.user ? Voici à quoi ressemble la requête dictée {'CONTENT_LENGTH' : 244, 'wsgi.input' : <django.test.client.FakePayload object at 0x31e9950>, 'REQUEST_METHOD' : 'POST', 'PATH_INFO' : '/register/', 'CONTENT_TYPE' : 'multipart/form-data ; boundary=BoUnDaRyStRiNg', 'QUERY_STRING' : ''}

0 votes

Utilisez-vous django.contrib.auth.middleware.AuthenticationMiddleware ?

0 votes

Oui, en utilisant le middleware par défaut.

2voto

Thierry Lam Points 7888

Où est-ce que vous initialisez votre self.client ? Qu'y a-t-il d'autre dans votre setUp méthode ? J'ai un test similaire et votre code devrait fonctionner correctement. Voici comment je procède :

from django.contrib.auth.models import User
from django.test import TestCase
from django.test.client import Client

class UserTestCase(TestCase):

    def setUp(self):
        self.client = Client()

    def testLogin(self):
        print User.objects.all() # returns []
        response = self.client.post(reverse('auth-registration'), 
                            { 'username':'foo', 
                              'password1':'bar', 
                              'password2':'bar' } )
        print User.objects.all() # returns one user
        print User.objects.all()[0].is_authenticated() # returns True

EDIT

Si je commente ma logique de connexion, je n'obtiens aucun utilisateur après self.client.post( . Si vous voulez vraiment vérifier si l'utilisateur a été authentifié, utilisez la fonction self.client pour accéder à une autre url qui nécessite une authentification de l'utilisateur. Dans la continuité de ce qui précède, accédez à une autre page :

response = self.client.get(reverse('another-page-which-requires-authentication'))
print response.status_code

Le code ci-dessus doit renvoyer 200 pour confirmer que l'utilisateur s'est authentifié. Dans le cas contraire, il sera redirigé vers la page de connexion avec un code 302.

2 votes

Print User.objects.all()[0].is_authenticated() avez-vous essayé de tester cela avant d'implémenter votre logique de connexion ? Parce que ce que je comprends de ce que les autres ont dit, c'est que cela retournera toujours vrai. Vous avez besoin de request.user.is_authenticated. De plus, le TestCase de django est fourni avec un objet Client déjà initialisé, donc pas besoin de le faire deux fois.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X