Использование нескольких полей для входа, электронной почты или номера телефона в Django All Auth - PullRequest
0 голосов
/ 22 апреля 2019

Я использую Django All Auth для аутентификации пользователя, но мне нужно использовать номер телефона или поле электронной почты при входе в систему. Я расширил пользовательский класс следующим образом:

class User(AbstractUser):
    phone_number = models.CharField(max_length=10, unique=True)


    def __unicode__(self):
        return self.username 

Моя форма регистрации выглядит так:

class SignupForm(forms.Form):
    phone_number = forms.CharField(max_length=10,label='phone_number')

    def signup(self, request, user):
        user.phone_number = self.cleaned_data['phone_number']
        user.save()

Номер телефона сохраняется в бэкэнде с использованием этого, но мне нужно аутентифицировать пользователя, если он вводит либо адрес электронной почты, либо номер телефона. Какой класс мне нужно расширить для Django All Auth. Я прочитал много вопросов, но не смог найти ничего хорошего.

Если я добавлю ACCOUNT_USER_MODEL_USERNAME_FIELD = 'phone_number' в settings.py, он будет аутентифицироваться по телефону, но не по электронной почте.

РЕДАКТ. 1:

Я создал файл backends.py и написал этот код

class PhoneNumberBackend(object):
    """
    Custom Phone Number Backend to perform authentication via phone number
    """
    def authenticate(self, username=None, password=None):
        my_user_model = get_user_model()

        try:
            user = my_user_model.objects.get(phone_number=username)
            if user.check_password(password):
                return user # return user on valid credentials
        except my_user_model.DoesNotExist:
            return None # return None if custom user model does not exist 
        except:
            return None # return None in case of other exceptions

    def get_user(self, user_id):
        my_user_model = get_user_model()
        try:
            return my_user_model.objects.get(pk=user_id)
        except my_user_model.DoesNotExist:
            return None

Settings.py теперь выглядит так:

AUTHENTICATION_BACKENDS = (
    # 'userauth.backends.PhoneNumberBackend',
    # Needed to login by username in Django admin, regardless of `allauth`
    'django.contrib.auth.backends.ModelBackend',

    # `allauth` specific authentication methods, such as login by e-mail
    'allauth.account.auth_backends.AuthenticationBackend',

)

Он должен проходить проверку подлинности с использованием номера телефона, а если нет, то переходить на другие способы проверки подлинности, верно? Это так не работает.

1 Ответ

0 голосов
/ 22 апреля 2019

сначала вам нужно создать аутентификационный бэкэнд в djagno, подобный этому для электронной почты.

class EmailAuthentication(object):
def authenticate(self, request, username=None, password=None):
    try:
        user = User.objects.get(email=username)
        if user.check_password(password):
            return user
        return None
    except:
        return None
def get_user(self, user_id):
    try:
        return User.objects.get(id=user_id)
    except:
return None

вы можете сделать еще один для номера телефона, но убедитесь, что сделали его уникальным в вашей базе данных, чтобы никому не пришлосьучетные записи с теми же учетными данными, и вы можете проверить это в форме чистого метода, как это снова, это для электронной почты

def clean_email(self):
    email = self.cleaned_data['email']
    if User.objects.filter(email=email).exists():
        raise forms.ValidationError(' user with this email is already registered -- Try loginigin or resting the password')    
    return email

, тогда вы должны поместить аутентификационный бэкэнд в файл настроек и не забудьте включить оригиналимя пользователя бэкэнда django

AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'account.authentication.EmailAuthentication',
]

в предыдущем коде, я предположил, что ваш аутентификационный бэкэнд находится внутри файла с именем аутентификации в приложении учетной записи

, затем в представлении вы аутентифицируете пользователя, затем регистрируете егов

  username = form.cleaned_data['username']
  password = form.cleaned_data['password2']
  user = authenticate(username=username, password=password)
  if user:
      login(request, user)

или вы можете использовать LoginView из django.contrib.auth.views, чтобы упростить

...