Django - ईमेल के साथ लॉगिन


86

मैं 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)

क्या पहले उपयोगकर्ता नाम प्राप्त करने के अलावा कोई अन्य लॉगिन है?

जवाबों:


109

आपको एक कस्टम प्रमाणीकरण बैकएंड लिखना चाहिए। कुछ इस तरह काम करेगा:

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


6
Django 1.9.8 के उपयोग से मुझे एक त्रुटि मिली है: 'EmailBackend' ऑब्जेक्ट में कोई विशेषता नहीं है 'get_user'। इस stackoverflow.com/a/13954358/2647009 के
बाल्टसवेसज

कृपया बताएं कि किस Django संस्करण में यह कोड काम कर सकता है। कुछ get_user विधि के गुम होने की शिकायत कर रहे हैं।
डॉ। यूनिस हेन्नी

2
बजाय इसके if user.check_password(password):कि आप शायद इसे शामिल करना चाहते हैं जो Django डिफ़ॉल्ट रूप से करता है ModelBackend: if user.check_password(password) and self.user_can_authenticate(user):उपयोगकर्ता की जांच के लिए is_active=True
jmq

1
क्या यह टाइमिंग हमले के लिए संवेदनशील नहीं है क्योंकि इसमें स्रोत कोड पर Django शमन शामिल नहीं है?
गेब्रियल गार्सिया

अब, अनुरोध के मुख्य भाग में उपयोगकर्ता नाम और पासवर्ड जैसे फ़ील्ड शामिल होने चाहिए। क्या इसे ईमेल और पासवर्ड में बदलने का कोई तरीका है?
करोल

55

यदि आप एक नई परियोजना शुरू कर रहे हैं, तो django ने आपको एक कस्टम उपयोगकर्ता मॉडल सेट करने के लिए अत्यधिक अनुशंसा की है। (देखें https://docs.djangoproject.com/en/dev/topics/auth/customizing/#use-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)काम करना बंद कर देता है।


3
जब निर्माणकर्ता चला रहा है, तो यह स्वयं एक त्रुटि फेंकता है: TypeError: create_superuser () 1 आवश्यक स्थितीय तर्क गुम: 'उपयोगकर्ता नाम'। आपको कस्टम उपयोगकर्ता प्रबंधक का उपयोग करने की आवश्यकता है: 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
मीकल होलुब

17
यहां पूर्ण निर्देश: fomfus.com/articles/…
user2061057

1
यदि आप एक पुन: प्रयोज्य एप्लिकेशन बना रहे हैं तो फिर, Django डॉक्स एक कस्टम उपयोगकर्ता मॉडल का उपयोग करने के खिलाफ सलाह देता है
djvg

14

Django 3.x के लिए ईमेल प्रमाणीकरण

डिफ़ॉल्ट उपयोगकर्ता नाम और पासवर्ड प्रमाणीकरण के बजाय प्रमाणीकरण के लिए ईमेल / उपयोगकर्ता नाम और पासवर्ड का उपयोग करने के लिए, हमें ModelBackend वर्ग के दो तरीकों को ओवरराइड करने की आवश्यकता है: प्रमाणीकृत () और get_user ():

Get_user विधि एक user_id लेती है - जो एक उपयोगकर्ता नाम, डेटाबेस आईडी या जो कुछ भी हो सकता है, लेकिन आपके उपयोगकर्ता ऑब्जेक्ट के लिए अद्वितीय होना चाहिए - और उपयोगकर्ता ऑब्जेक्ट या कोई भी नहीं लौटाता है। यदि आपने ईमेल को एक अद्वितीय कुंजी के रूप में नहीं रखा है, तो आपको 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']

सेटिंग्स थिंकपैड फ़ाइल में, डिफ़ॉल्ट को ओवरराइड करने के लिए नीचे में निम्नलिखित जोड़ें:

AUTHENTICATION_BACKENDS = ('appname.filename.EmailBackend',)

यह बहुत अच्छा है, धन्यवाद। मैंने बहुत कुछ प्रोजेक्ट पूरा किया है, टेम्प्लेट, फ़ॉर्म, विचार, बहुत कुछ, इसलिए फिर से शुरू करना उतना आकर्षक नहीं है! अब मैं ईमेल पते पर प्रमाणित कर सकता हूं कि उपयोगकर्ता नाम फ़ील्ड को हटाने का कोई तरीका है ताकि यह प्रमाणीकरण और टेम्प्लेट में दिए गए रूपों में शामिल न हो?
चंद्रकर

11

मेरी भी ऐसी ही आवश्यकता थी जहाँ उपयोगकर्ता नाम / ईमेल को उपयोगकर्ता नाम फ़ील्ड के लिए काम करना चाहिए। यदि कोई व्यक्ति ऐसा करने के प्रमाणीकरण बैकएंड के लिए देख रहा है, तो निम्नलिखित कार्य कोड देखें। यदि आप केवल ईमेल की इच्छा रखते हैं तो आप क्वेरी को बदल सकते हैं।

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') जोड़ें


यह मेरे लिए तब तक काम करता था जब तक मैं 1.11 से 2.1.5 तक अपग्रेड नहीं हो जाता। किसी भी विचार क्यों यह इस संस्करण के साथ काम नहीं करेगा?
ज़ीरोहेज

@zerohedge प्रामाणिक विधि के मापदंडों के लिए अनुरोध जोड़ें। देखें docs.djangoproject.com/en/2.2/topics/auth/customizing/...
वान

यह आपको एक टाइमिंग हमले के लिए खुला छोड़ देता है, यह इस तरह की कमजोरियों को रोकने के लिए Django कार्यान्वयन को बारीकी से नकल करने की कोशिश करने के लायक है: github.com/django/django/blob/master/django/contrib/auth/…
गैब्रियल गार्सिया

यह निष्क्रिय उपयोगकर्ताओं को प्रमाणित करने में भी सक्षम करेगा।
गैब्रियल गार्सिया

5

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'

लेकिन किसी और को उनके ईमेल का उपयोग करने से रोकने के लिए, आपको इसके बजाय ईमेल सत्यापन को जोड़ना चाहिए और आपकी पंजीकरण और लॉगिन प्रक्रिया को ध्यान में रखना चाहिए कि ईमेल अद्वितीय नहीं हो सकते हैं (और शायद नए उपयोगकर्ताओं को मौजूदा और मान्य ईमेल पते का उपयोग करने से रोकें)।


4

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

हमेशा अपनी सेटिंग्स को जोड़ने के लिए याद रखें कि सही प्रमाणीकरण बैकेंड है


1
क्या मेरी समझ सही है कि UserModel().set_password(password)हमलावरों को यह निर्धारित करने से रोकने के लिए है कि क्या उपयोगकर्ता किसी अन्य राशि के क्रिप्टोग्राफिक कार्य की परवाह किए बिना मौजूद है या नहीं (मुझे लगता है कि यह आपके द्वारा किए गए समय का हमला है)?
ग्रैंड फुबा

2

आपको 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

और सेटिंग्स फ़ाइल में, जोड़ें:

AUTHENTICATION_BACKENDS = ['path.to.class.YourBackend']

Django 2.1.1 के लिए विधि में requestपैरामीटर को शामिल करने के लिए अपने कोड को अपडेट करेंauthenticate
गणेश

2

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']

1
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:

AUTHENTICATION_BACKENDS = (
  'articles.backends.EmailAuthenticate',
)

जहां लेख मेरे Django-अनुप्रयोग है, backends.pyमेरे ऐप के अंदर अजगर फ़ाइल है और EmailAuthenticateमेरी अंदर प्रमाणीकरण बैकएंड वर्ग है backends.pyफ़ाइल


1

बहुत साधारण। इसके लिए किसी अतिरिक्त कक्षा की आवश्यकता नहीं है।

जब आप किसी उपयोगकर्ता को ईमेल से बनाते और अपडेट करते हैं, तो बस ईमेल के साथ उपयोगकर्ता नाम फ़ील्ड सेट करें।

इस तरह जब आप उपयोगकर्ता नाम को प्रमाणित करते हैं तो ईमेल का समान मूल्य होगा।

कोड:

# 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)

1
कृपया यह दर्शाने के लिए कुछ नमूना कोड जोड़ें कि आपका उत्तर समस्या को हल करने में कैसे मदद कर सकता है।
सूट बॉय एप्स

1
यदि आप अतिरिक्त जानकारी नहीं जोड़ते हैं तो @CasmanRidder आपका उत्तर हटा दिया जाएगा।
10 प्रतिनिधि कहते हैं कि


0

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')

क्या आप यह समझाने के लिए थोड़ा पाठ जोड़ सकते हैं कि आपका उत्तर क्या करता है और यह प्रश्न का उत्तर देने में कैसे मदद करता है?
जेकज

संपादित किया हुआ। धन्यवाद
शकील अहमद

0

यदि आपने कस्टम डेटाबेस बनाया है, वहाँ से यदि आप अपनी ईमेल आईडी और पासवर्ड को मान्य करना चाहते हैं।

  1. ईमेल आईडी और पासवर्ड प्राप्त करें models.objects.value_list('db_columnname').filter(db_emailname=textbox email)

2. सूची में रखा गया है object_query_list

3. सूची सूची स्ट्रिंग करने के लिए

Ex:

  1. Html Email_idऔर Passwordमान लेंViews.py

    u_email = request.POST.get('uemail')

    u_pass = request.POST.get('upass')

  2. डेटाबेस से ईमेल आईडी और पासवर्ड प्राप्त करें

    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)

  3. Queryमूल्य सेट से सूची में ईमेल आईडी और पासवर्ड मान लें

    Email_Value = Email[0]

    Password_Value=Password[0]

  4. सूची को स्ट्रिंग में बदलें

    string_email = ''.join(map(str, Email_Value))

    string_password = ''.join(map(str, Password_Value))

अंत में आपकी लॉगिन स्थिति

if (string_email==u_email and string_password ==u_pass)

0

मैंने उस के लिए एक सहायक बनाया है: फ़ंक्शन 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)

0

ऐसा लगता है कि ऐसा करने का तरीका Django 3.0 के साथ अपडेट किया गया है।

मेरे लिए एक काम करने का तरीका है:

प्रमाणीकरण # # - मैंने इसे एक एप्लिकेशन में रखा (सेटिंग्स के साथ प्रोजेक्ट फ़ोल्डर में काम नहीं किया

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

फिर इसे सेटिंग्स फ़ाइल में जोड़ दिया

AUTHENTICATION_BACKENDS = (
    'appname.authentication.EmailBackend',
)

0

डिफ़ॉल्ट उपयोगकर्ता मॉडल एक सार वर्ग का उत्तराधिकार / विस्तार करता है। ढांचे में परिवर्तन या परिवर्तन की एक निश्चित मात्रा के लिए उत्तरदायी होना चाहिए।

एक सरल हैक निम्नलिखित करना है: यह एक आभासी वातावरण में है

  1. अपने django स्थापना स्थान पर जाएं और Lib फ़ोल्डर ढूंढें
  2. django / contrib / परिस्थिति / पर नेविगेट करें
  3. मॉडल की खोज करें और खोलें। AbstractUser क्लास लाइन 315 खोजें

ईमेल विशेषता पर लाइन 336 अद्वितीय जोड़ें और इसे सही पर सेट करें

email = models.EmailField(_('email address'), blank=True,unique=True)

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
  1. हो गया, makemigrations और पलायन

आप अपने जोखिम पर ऐसा करें,

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.