-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixed #20916 -- Added Client.force_login() to bypass authentication during a test login. #4865
Conversation
I'm not completely convinced by implementing a new auth backend and patching the settings with it. I guess things break if there is no authentication backend set. Perhaps pseudocode like this:
|
I agree with Marc. I think the patch is too complicated/complex for what you want to achieve. There should be an easier way to do that. |
@mjtamlyn Thanks for the feedback. I like you're suggestion and approach better. I have incorporated it into the latest version. |
Implementation looks good to me, needs docs and release notes |
|
||
# Create a fake request to store login details. | ||
request = HttpRequest() | ||
def force_login(self, user, backend=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we call it "login_user"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a bad plan at all. I originally suggested force_login
on the ticket to make it clear that it bypasses the authentication systems completely. Everything here is pretty clearly a testing utility mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd actually prefer something like force_login
for exactly that reason. login_user
suggests something more generic than shortcircuting the is_active
flag.
On June 16, 2015 10:10:32 PM GMT+02:00, Marc Tamlyn notifications@github.com wrote:
# Create a fake request to store login details.
request = HttpRequest()
- def force_login(self, user, backend=None):
Not a bad plan at all. I originally suggested
force_login
on the
ticket to make it clear that it bypasses the authentication systems
completely. Everything here is pretty clearly a testing utility mind.
Reply to this email directly or view it on GitHub:
https://github.com/django/django/pull/4865/files#r32564941
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is more generic than shortcircuting the is_active
flag, isn't it? It logs in the given user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, but from a user's perspective I don't see the difference between login()
and login_user()
. I could even think that the latter would prevent staff/superusers to login.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I agree with @MarkusH. I feel the word force helps emphasize that this mechanism is bypassing authentication.
But ultimately, I don't mind either and will adopt whatever the consensus is.
I have updated the commit with more tests and documentation. All comments welcome. If a decision is made on Thanks for all feedback. |
The docs currently don't give much rationale as to why you would use this instead of If we have this we can add a section like "This makes the tests requiring a logged in user simpler to write and quicker to run. You should ensure you have some tests which check the authentication systems properly." |
Good point. I have tried to address your concern in the latest version. Let me know if this is what you had in mind. Let me know if I should expand or reword anything. |
Ran some simple benchmarks. Basically, I added a "test" that calls either
Test code executed to produce results (quick and dirty): def test_perf(self):
import time
hashers = [
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
'django.contrib.auth.hashers.MD5PasswordHasher',
'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher',
'django.contrib.auth.hashers.CryptPasswordHasher',
]
n = 100
print("\n\n")
User.objects.all().delete()
u = User(
last_login=datetime.datetime(2006, 12, 17, 7, 3, 31), is_superuser=False, username='testclient',
first_name='Test', last_name='Client', email='testclient@example.com', is_staff=False, is_active=True,
date_joined=datetime.datetime(2006, 12, 17, 7, 3, 31)
)
u.set_password('password')
u.save()
t0 = time.time()
for i in range(n):
self.client.force_login(u)
dt = time.time() - t0
print("force_login: %fs" % dt)
for hasher in hashers:
with self.settings(PASSWORD_HASHERS=[hasher]):
User.objects.all().delete()
u = User(
last_login=datetime.datetime(2006, 12, 17, 7, 3, 31), is_superuser=False, username='testclient',
first_name='Test', last_name='Client', email='testclient@example.com', is_staff=False, is_active=True,
date_joined=datetime.datetime(2006, 12, 17, 7, 3, 31)
)
u.set_password('password')
u.save()
t0 = time.time()
for i in range(n):
self.client.login(username='testclient', password='password')
dt = time.time() - t0
print("%s: %fs" % (hasher, dt))
print() Edit @MarkusH: Turned on syntax highlighting for the test function. |
Looks good to me, and thanks for the benchmarks. There's a bit of wording style which will need amending in the docs I think but I'm rubbish at identifying that so I'll summon @timgraham instead ;) |
to combat brute force attacks. Using this method instead of ``login()`` | ||
may make your tests quicker to run by skipping these algorithms. | ||
|
||
Please note, testing and verifying the authentication system of your |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what tests this paragraph is implying need to be written. Using Client.login()
in a few tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess in particular it's that if you're not using Django's built in auth system then you should test your code? I wouldn't mind if this note went away though.
Minor edits: http://dpaste.com/3HABAVP |
Thanks Tim. I have applied this patch to the latest version of the PR. |
…uring a test login.
Could I get a review of this additional paragraph to the docs? If it looks good, I'll add it and merge this.
|
Removes a few too many |
merged in b44dee1, thanks! |
…on when logging in during tests.