Code

Opened 2 years ago

Closed 23 months ago

Last modified 22 months ago

#18157 closed New feature (fixed)

Document that setting PASSWORD_HASHERS for tests can make them much faster

Reported by: carljm Owned by: nobody
Component: Documentation Version: 1.4
Severity: Normal Keywords:
Cc: kmike84@…, dan.fairs@…, dev@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

As discussed in this thread, the new default PBKDF2 password hasher in Django 1.4 is significantly slower by design than the previous MD5 hasher (so that cracking of passwords in an exposed password database is more time-consuming). It seems that for some test suites that authenticate a lot of users, this can slow down the overall test suite run-time by as much as a factor of two.

The workaround is simple: you can override the PASSWORD_HASHERS setting to something like PASSWORD_HASHERS = ['django.contrib.auth.hashers.MD5PasswordHasher'], just for tests. Given the speed difference, this workaround is probably worth documenting in the testing docs (with the caveat that of course your test suite then won't reveal any bugs in your real PASSWORD_HASHERS setting).

Attachments (0)

Change History (12)

comment:1 Changed 2 years ago by kmike

  • Cc kmike84@… added

To make it clear: in my case the cause of 2x slowdown seems to be user creation, not user authentication.

comment:2 Changed 2 years ago by airstrike

Considering this workaround won't really test any password hashes, I wonder if having a dummy hasher would further improve test speeds.

Cheers,
AT

comment:3 Changed 2 years ago by akaariai

  • Triage Stage changed from Unreviewed to Accepted

I believe md5 is really "fast enough" unless you are doing nothing else than hashing alone (haven't benchmarked). There is certain point of not having a dummy-hasher at all in Django.

comment:4 Changed 2 years ago by carljm

As akaariai noted in the mailing list thread, it may also make sense to make this change in the test_sqlite settings file for running Django's own test suite.

comment:5 Changed 2 years ago by akaariai

I moved the test_sqlite settings file issue to another ticket (#18163) to avoid complicating this ticket with the design decision needed there.

I wonder if it would be a good idea to have "TEST_PASSWORD_HASHER" setting. This setting would move one of the existing PASSWORD_HASHERS to the top of the PASSWORD_HASHERS list.

comment:6 Changed 2 years ago by danfairs

  • Cc dan.fairs@… added

comment:7 Changed 2 years ago by ryankask

  • Cc dev@… added

comment:8 Changed 2 years ago by aaugustin

I wonder if having a dummy hasher would further improve test speeds.

I don't expect the time taken by the MD5 hasher to be significant. PBKDF2 is slow because it hashes the password thousands of times. MD5 hashes it only once.


I wonder if it would be a good idea to have "TEST_PASSWORD_HASHER" setting.

Not another setting please :)

comment:9 Changed 23 months ago by Claude Paroz <claude@…>

  • Resolution set to fixed
  • Status changed from new to closed

In [17d6cd90299e39823e80a005e7a04bc24ee8af4c]:

Fixed #18157 -- Documented that setting PASSWORD_HASHERS can speed up tests

comment:10 Changed 23 months ago by mjtamlyn

Big +1 on this, but it may be worth mentioning that if you have fixtures generated with a different password hasher you'll get errors if you don't include that hasher. Same speed up can be gained just by putting the MD5 hasher at the top of your existing setting. Obviously we shouldn't be using fixtures but...

comment:11 Changed 23 months ago by Claude Paroz <claude@…>

In [b0d8085c67884f36c8fb4af5f1fdae844e4700f7]:

Added note about including fixtures hashing algorithm

Refs #18157.

comment:12 Changed 22 months ago by jodym@…

Note that you CAN'T do this for just one test using @override_settings, because PREFERRED_HASHER is initialized once the first time get_hasher() is called. Ugh.

Workaround:

@override_settings(PASSWORD_HASHERS=(
    'django.contrib.auth.hashers.SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
))
def test_whatever(self):
    import django.contrib.auth.hashers
    django.contrib.auth.hashers.PREFERRED_HASHER = None
        
    ...

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.