Я хочу, чтобы django аутентифицировал пользователей по электронной почте, а не по именам пользователей. Один из способов - указать адрес электронной почты в качестве значения имени пользователя, но я этого не хочу. Причина в том, что у меня есть URL-адрес /profile/<username>/
, поэтому у меня не может быть URL-адреса /profile/abcd@gmail.com/
.
Другая причина в том, что все электронные письма уникальны, но иногда бывает, что имя пользователя уже используется. Следовательно, я автоматически создаю имя пользователя как fullName_ID
.
Как я могу просто изменить, чтобы Django аутентифицировался по электронной почте?
Вот как я создаю пользователя.
username = `abcd28`
user_email = `abcd@gmail.com`
user = User.objects.create_user(username, user_email, user_pass)
Вот как я вхожу в систему.
email = request.POST['email']
password = request.POST['password']
username = User.objects.get(email=email.lower()).username
user = authenticate(username=username, password=password)
login(request, user)
Есть ли какой-либо другой способ входа в систему, кроме получения имени пользователя?
if user.check_password(password):
вы , вероятно , хотите , чтобы включить то , что Django делает по умолчанию черезModelBackend
:if user.check_password(password) and self.user_can_authenticate(user):
для того , чтобы убедиться , что пользователь имеетis_active=True
.Если вы начинаете новый проект, django настоятельно рекомендует вам настроить пользовательскую модель. (см. https://docs.djangoproject.com/en/dev/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project )
и если вы это сделали, добавьте в свою модель пользователя три строки:
class MyUser(AbstractUser): USERNAME_FIELD = 'email' email = models.EmailField(_('email address'), unique=True) # changes email to unique and blank to false REQUIRED_FIELDS = [] # removes email from REQUIRED_FIELDS
Потом
authenticate(email=email, password=password)
работает, покаauthenticate(username=username, password=password)
перестает работать.источник
class MyUserManager(BaseUserManager): def create_superuser(self, email, password, **kwargs): user = self.model(email=email, is_staff=True, is_superuser=True, **kwargs) user.set_password(password) user.save() return user
Аутентификация электронной почты для Django 3.x
Для использования электронной почты / имени пользователя и пароля для аутентификации вместо аутентификации по умолчанию и пароля нам необходимо переопределить два метода класса ModelBackend: authentication () и get_user ():
Метод get_user принимает user_id - который может быть именем пользователя, идентификатором базы данных или чем-то еще, но должен быть уникальным для вашего пользовательского объекта - и возвращает пользовательский объект или None. Если вы не сохранили электронную почту в качестве уникального ключа, вам придется позаботиться о нескольких результатах, возвращаемых для query_set. В приведенном ниже коде об этом позаботились, вернув первого пользователя из возвращенного списка.
from django.contrib.auth.backends import ModelBackend, UserModel from django.db.models import Q class EmailBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): try: #to allow authentication through phone number or any other field, modify the below statement user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username)) except UserModel.DoesNotExist: UserModel().set_password(password) except MultipleObjectsReturned: return User.objects.filter(email=username).order_by('id').first() else: if user.check_password(password) and self.user_can_authenticate(user): return user def get_user(self, user_id): try: user = UserModel.objects.get(pk=user_id) except UserModel.DoesNotExist: return None return user if self.user_can_authenticate(user) else None
По умолчанию для AUTHENTICATION_BACKENDS установлено значение:
['django.contrib.auth.backends.ModelBackend']
В файле settings.py добавьте следующее внизу, чтобы переопределить значение по умолчанию:
AUTHENTICATION_BACKENDS = ('appname.filename.EmailBackend',)
источник
У меня было аналогичное требование, когда любое имя пользователя / адрес электронной почты должны работать для поля имени пользователя. Если кто-то ищет способ аутентификации на бэкэнд для этого, ознакомьтесь со следующим рабочим кодом. Вы можете изменить набор запросов, если вам нужен только адрес электронной почты.
from django.contrib.auth import get_user_model # gets the user_model django default or your own custom from django.contrib.auth.backends import ModelBackend from django.db.models import Q # Class to permit the athentication using email or username class CustomBackend(ModelBackend): # requires to define two functions authenticate and get_user def authenticate(self, username=None, password=None, **kwargs): UserModel = get_user_model() try: # below line gives query set,you can change the queryset as per your requirement user = UserModel.objects.filter( Q(username__iexact=username) | Q(email__iexact=username) ).distinct() except UserModel.DoesNotExist: return None if user.exists(): ''' get the user object from the underlying query set, there will only be one object since username and email should be unique fields in your models.''' user_obj = user.first() if user_obj.check_password(password): return user_obj return None else: return None def get_user(self, user_id): UserModel = get_user_model() try: return UserModel.objects.get(pk=user_id) except UserModel.DoesNotExist: return None
Также добавьте AUTHENTICATION_BACKENDS = ('path.to.CustomBackend',) в settings.py
источник
Django 2.x
Как упоминал Ганеш выше для django 2.x, для метода аутентификации теперь требуется параметр запроса.
# backends.py from django.contrib.auth import backends, get_user_model from django.db.models import Q UserModel = get_user_model() class ModelBackend(backends.ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): if username is None: username = kwargs.get(UserModel.USERNAME_FIELD) try: # user = UserModel._default_manager.get_by_natural_key(username) # You can customise what the given username is checked against, here I compare to both username and email fields of the User model user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username)) except UserModel.DoesNotExist: # Run the default password hasher once to reduce the timing # difference between an existing and a nonexistent user (#20760). UserModel().set_password(password) else: if user.check_password(password) and self.user_can_authenticate(user): return user return super().authenticate(request, username, password, **kwargs)
добавьте свой бэкэнд в настройки вашего проекта
# settings.py AUTHENTICATION_BACKENDS = ['path.to.ModelBackend']
Ваша пользовательская модель пользователя должна будет сделать электронные письма уникальными для активных и проверенных пользователей, вы можете сделать это просто с помощью чего-то вроде этого:
from django.contrib.auth.models import AbstractUser class User(AbstractUser): objects = UserManager() email = models.EmailField(_('email address'), unique=True) class Meta: verbose_name = _('user') verbose_name_plural = _('users') db_table = 'auth_user' swappable = 'AUTH_USER_MODEL'
Но для предотвращения того, чтобы кто-то блокировал использование своей электронной почты кем-то другим, вы должны вместо этого добавить проверку электронной почты и принять во внимание процесс регистрации и входа в систему, что электронные письма могут не быть уникальными (и, вероятно, помешать новым пользователям использовать существующий и проверенный адрес электронной почты).
источник
Электронная почта и аутентификация имени пользователя для Django 2.X
Имея в виду, что это частый вопрос, вот пользовательская реализация, имитирующая исходный код Django, но которая аутентифицирует пользователя либо по имени пользователя, либо по электронной почте без учета регистра, сохраняя защиту от временных атак и не аутентифицируя неактивных пользователей .
from django.contrib.auth.backends import ModelBackend, UserModel from django.db.models import Q class CustomBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): try: user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username)) except UserModel.DoesNotExist: UserModel().set_password(password) else: if user.check_password(password) and self.user_can_authenticate(user): return user def get_user(self, user_id): try: user = UserModel.objects.get(pk=user_id) except UserModel.DoesNotExist: return None return user if self.user_can_authenticate(user) else None
Всегда не забывайте добавлять в свой settings.py правильный бэкэнд аутентификации .
источник
UserModel().set_password(password)
существует возможность помешать злоумышленникам определить, существует ли пользователь или нет, независимо от выполнения примерно того же объема криптографической работы (я предполагаю, что это временная атака, которую вы имели в виду)?Вам следует настроить класс ModelBackend. Мой простой код:
from django.contrib.auth.backends import ModelBackend from django.contrib.auth import get_user_model class YourBackend(ModelBackend): def authenticate(self, username=None, password=None, **kwargs): UserModel = get_user_model() if username is None: username = kwargs.get(UserModel.USERNAME_FIELD) try: if '@' in username: UserModel.USERNAME_FIELD = 'email' else: UserModel.USERNAME_FIELD = 'username' user = UserModel._default_manager.get_by_natural_key(username) except UserModel.DoesNotExist: UserModel().set_password(password) else: if user.check_password(password) and self.user_can_authenticate(user): return user
И в файле settings.py добавьте:
AUTHENTICATION_BACKENDS = ['path.to.class.YourBackend']
источник
request
параметр вauthenticate
метод для django 2.1.1Аутентификация по электронной почте и имени пользователя для Django 2.x
from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend from django.db.models import Q class EmailorUsernameModelBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): UserModel = get_user_model() try: user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username)) except UserModel.DoesNotExist: return None else: if user.check_password(password): return user return None
В settings.py добавьте следующую строку,
AUTHENTICATION_BACKENDS = ['appname.filename.EmailorUsernameModelBackend']
источник
from django.contrib.auth.models import User from django.db import Q class EmailAuthenticate(object): def authenticate(self, username=None, password=None, **kwargs): try: user = User.objects.get(Q(email=username) | Q(username=username)) except User.DoesNotExist: return None except MultipleObjectsReturned: return User.objects.filter(email=username).order_by('id').first() if user.check_password(password): return user return None def get_user(self,user_id): try: return User.objects.get(pk=user_id) except User.DoesNotExist: return None
А потом в
settings.py
:где статьи - это мое приложение django,
backends.py
это файл python внутри моего приложения иEmailAuthenticate
класс бэкэнда аутентификации внутри моегоbackends.py
файлаисточник
Довольно просто. В дополнительных занятиях нет необходимости.
Когда вы создаете и обновляете пользователя с помощью электронной почты, просто укажите в поле имени пользователя адрес электронной почты.
Таким образом, при аутентификации поле имени пользователя будет иметь то же значение, что и электронное письмо.
Код:
# Create User.objects.create_user(username=post_data['email'] etc...) # Update user.username = post_data['email'] user.save() # When you authenticate user = authenticate(username=post_data['email'], password=password)
источник
Для Django 2
username = get_object_or_404(User, email=data["email"]).username user = authenticate( request, username = username, password = data["password"] ) login(request, user)
источник
Аутентификация по электронной почте для Django 2.x
def admin_login(request): if request.method == "POST": email = request.POST.get('email', None) password = request.POST.get('password', None) try: get_user_name = CustomUser.objects.get(email=email) user_logged_in =authenticate(username=get_user_name,password=password) if user_logged_in is not None: login(request, user_logged_in) messages.success(request, f"WelcomeBack{user_logged_in.username}") return HttpResponseRedirect(reverse('backend')) else: messages.error(request, 'Invalid Credentials') return HttpResponseRedirect(reverse('admin_login')) except: messages.warning(request, 'Wrong Email') return HttpResponseRedirect(reverse('admin_login')) else: if request.user.is_authenticated: return HttpResponseRedirect(reverse('backend')) return render(request, 'login_panel/login.html')
источник
Если вы создали настраиваемую базу данных, оттуда, если вы хотите проверить свой электронный идентификатор и пароль.
models.objects.value_list('db_columnname').filter(db_emailname=textbox email)
2. назначить в полученном списке
object_query_list
3. преобразовать список в строку
Пример:
Возьмите HTML
Email_id
иPassword
значения вViews.py
u_email = request.POST.get('uemail')
u_pass = request.POST.get('upass')
Получить идентификатор электронной почты и пароль из базы данных
Email = B_Reg.objects.values_list('B_Email',flat=True).filter(B_Email=u_email)
Password = B_Reg.objects.values_list('Password',flat=True).filter(B_Email=u_email)
Возьмите значения идентификатора электронной почты и пароля в списке из
Query
набора значенийEmail_Value = Email[0]
Password_Value=Password[0]
Преобразовать список в строку
string_email = ''.join(map(str, Email_Value))
string_password = ''.join(map(str, Password_Value))
Наконец, ваше условие входа в систему
if (string_email==u_email and string_password ==u_pass)
источник
Я создал для этого помощника: функцию
authenticate_user(email, password)
.from django.contrib.auth.models import User def authenticate_user(email, password): try: user = User.objects.get(email=email) except User.DoesNotExist: return None else: if user.check_password(password): return user return None class LoginView(View): template_name = 'myapp/login.html' def get(self, request): return render(request, self.template_name) def post(self, request): email = request.POST['email'] password = request.POST['password'] user = authenticate_user(email, password) context = {} if user is not None: if user.is_active: login(request, user) return redirect(self.request.GET.get('next', '/')) else: context['error_message'] = "user is not active" else: context['error_message'] = "email or password not correct" return render(request, self.template_name, context)
источник
Похоже, что этот метод был обновлен в Django 3.0.
Для меня метод работы был:
authentication.py # <- я поместил это в приложение (не работает в папке проекта вместе с settings.py
from django.contrib.auth import get_user_model from django.contrib.auth.backends import BaseBackend from django.contrib.auth.hashers import check_password from django.contrib.auth.models import User class EmailBackend(BaseBackend): def authenticate(self, request, username=None, password=None, **kwargs): UserModel = get_user_model() try: user = UserModel.objects.get(email=username) except UserModel.DoesNotExist: return None else: if user.check_password(password): return user return None def get_user(self, user_id): UserModel = get_user_model() try: return UserModel.objects.get(pk=user_id) except UserModel.DoesNotExist: return None
Затем добавил это в файл settings.py
источник
Модель пользователя по умолчанию наследует / расширяет абстрактный класс. Структура должна быть терпимой к определенному количеству изменений или дополнений.
Более простой способ взлома - это сделать следующее: Это в виртуальной среде.
СТРОКА 336 в атрибуте электронной почты добавьте уникальный и установите для него значение true
email = models.EmailField(_('email address'), blank=True,unique=True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username']
Делайте это на свой страх и риск,
источник