ソースを参照

Refs #17209 -- Fixed token verification for PasswordResetConfirmView POST requests.

Florian Apolloner 8 年 前
コミット
51eaff6d35
2 ファイル変更28 行追加3 行削除
  1. 11 3
      django/contrib/auth/views.py
  2. 17 0
      tests/auth_tests/test_views.py

+ 11 - 3
django/contrib/auth/views.py

@@ -441,6 +441,15 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView):
     @method_decorator(never_cache)
     def dispatch(self, *args, **kwargs):
         assert 'uidb64' in kwargs and 'token' in kwargs
+
+        self.validlink = False
+        self.user = self.get_user(kwargs['uidb64'])
+
+        if self.user is not None and self.token_generator.check_token(self.user, kwargs['token']):
+            self.validlink = True
+        else:
+            return self.render_to_response(self.get_context_data())
+
         return super(PasswordResetConfirmView, self).dispatch(*args, **kwargs)
 
     def get_user(self, uidb64):
@@ -455,7 +464,7 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView):
 
     def get_form_kwargs(self):
         kwargs = super(PasswordResetConfirmView, self).get_form_kwargs()
-        kwargs['user'] = self.get_user(self.kwargs['uidb64'])
+        kwargs['user'] = self.user
         return kwargs
 
     def form_valid(self, form):
@@ -466,8 +475,7 @@ class PasswordResetConfirmView(PasswordContextMixin, FormView):
 
     def get_context_data(self, **kwargs):
         context = super(PasswordResetConfirmView, self).get_context_data(**kwargs)
-        user = context['form'].user
-        if user is not None and self.token_generator.check_token(user, self.kwargs['token']):
+        if self.validlink:
             context['validlink'] = True
         else:
             context.update({

+ 17 - 0
tests/auth_tests/test_views.py

@@ -255,6 +255,23 @@ class PasswordResetTest(AuthViewsTestCase):
         u = User.objects.get(email='staffmember@example.com')
         self.assertTrue(not u.check_password("anewpassword"))
 
+    def test_confirm_invalid_hash(self):
+        """A POST with an invalid token is rejected."""
+        u = User.objects.get(email='staffmember@example.com')
+        original_password = u.password
+        url, path = self._test_confirm_start()
+        path_parts = path.split('-')
+        path_parts[-1] = ("0") * 20 + '/'
+        path = '-'.join(path_parts)
+
+        response = self.client.post(path, {
+            'new_password1': 'anewpassword',
+            'new_password2': 'anewpassword',
+        })
+        self.assertIs(response.context['validlink'], False)
+        u.refresh_from_db()
+        self.assertEqual(original_password, u.password)  # password hasn't changed
+
     def test_confirm_complete(self):
         url, path = self._test_confirm_start()
         response = self.client.post(path, {'new_password1': 'anewpassword', 'new_password2': 'anewpassword'})