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)
사용자 이름을 먼저 얻는 것 외에 다른 로그인이 있습니까?
답변
사용자 지정 인증 백엔드를 작성해야합니다. 다음과 같이 작동합니다.
from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
class EmailBackend(ModelBackend):
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
그런 다음 설정에서 해당 백엔드를 인증 백엔드로 설정합니다.
AUTHENTICATION_BACKENDS = ['path.to.auth.module.EmailBackend']
업데이트되었습니다 . 이미 ModelBackend
같은 메서드를 구현하므로 상속하십시오 get_user()
.
https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-an-authentication-backend에서 문서를 참조하십시오.
답변
새 프로젝트를 시작하는 경우 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)
멈추고 작동합니다.
답변
Django 3.x에 대한 이메일 인증
기본 사용자 이름 및 암호 인증 대신 인증을 위해 이메일 / 사용자 이름 및 암호를 사용하려면 다음과 같은 ModelBackend 클래스의 두 가지 메서드 인 authenticate () 및 get_user ()를 재정의해야합니다.
get_user 메소드는 user_id (사용자 이름, 데이터베이스 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
또한 settings.py에 AUTHENTICATION_BACKENDS = ( ‘path.to.CustomBackend’,)를 추가하십시오.
답변
장고 2.x
위의 Ganesh가 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에 대한 이메일 및 사용자 이름 인증
공통 질문은 마음이되는 데, 여기에 모방 정의 구현의 장고 소스 코드는 하지만 인증하는 유지 중 사용자 이름 또는 이메일, 대문자와 소문자를 구별하지 않고로와 사용자 타이밍 공격 보호 및 되지는 비활성 사용자를 인증 .
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 올바른 인증 백엔드 를 추가하는 것을 항상 기억하십시오 .
답변
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']
