This backend will allow you to have users login using either their username or the email address as it is in the User model. In addition, it will allow anyone with the staff priveleges to login as another user. The method is to user the user you wish to masquerade as (either email/username) as the username and then a string of the format username/password as the password, where username is the username of the staff member, and password is their password.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User from django.forms.fields import email_re class EmailBackend(ModelBackend): """Allows a user to login using their email address, and not just their username. This is a lot more common than a new username. Some things that it takes care of for you are: - Allow _either_ username or email to be used - Allow anyone marked as staff in the database to mascquerade as another user by using the user they want to masquerade as as the username and using <username>/<password> in the password field, where <username> is _their_ username.""" def _lookup_user(self, username): try: if email_re.search(username): # Looks like an email. Since emails are not case sensitive # and many users have a habit of typing them in mixed # cases, we will normalize them to lower case. This assumes # that the database has done the same thing. user = User.objects.get(email=username.lower()) else: user = User.objects.get(username=username) except User.DoesNotExist: return None return user def authenticate(self, username=None, password=None): user = self._lookup_user(username) if user: if user.check_password(password): return user elif '/' in password: proposed_user = user # Who we want to be (username, password) = password.split('/', 1) user = self._lookup_user(username) if user and user.is_staff: if user.check_password(password): return proposed_user return None
More like this
- Stuff by NixonDash 1 month ago
- Add custom fields to the built-in Group model by jmoppel 3 months, 1 week ago
- Month / Year SelectDateWidget based on django SelectDateWidget by pierreben 6 months, 3 weeks ago
- Python Django CRUD Example Tutorial by tuts_station 7 months, 1 week ago
- Browser-native date input field by kytta 8 months, 3 weeks ago
Good snippet. One issue, however; line 39 should use
in case there is a / in the password.
email_reis unnecessary here. If you just check whether the username matches an email, the validation on the email database field will take care of it:
Thanks for the changes. I'm not sure about the expense of hitting the database v. the regex, since it's compiled. I'll do some little micro-benchmarks. I'm not sure it matters, in the end since it's only done on log-in. You're right about the password bit, though.
Can't you just do a
User.objects.get(email__iexact=username)on line 23?
Also, nowadays the correct import for email_re is
from django.core.validators import email_re.
Please login first before commenting.