سؤال

آمل أن تتمكن من مساعدتي في تحديد أفضل طريقة لتنفيذ تسجيل دخول يدوي (بدأ من جانب الخادم) بدون باستخدام كلمة المرور. اسمحوا لي أن أشرح سير العمل:

  • سجلات المستخدم
  • شكرًا لك! تم إرسال بريد إلكتروني مع رابط تنشيط
  • (الحساب موجود الآن ولكن لا يتم تمكينه)
  • يفتح المستخدم البريد الإلكتروني ، رابط النقرات
  • (تم تمكين الحساب)
  • شكرًا لك! يمكنك الآن استخدام الموقع

ما أحاول القيام به هو تسجيل الدخول إلى المستخدم بعد النقر على رابط البريد الإلكتروني حتى يتمكن من البدء في استخدام موقع الويب على الفور.

لا يمكنني استخدام كلمة المرور الخاصة به نظرًا لأنها مشفرة في DB ، هل الخيار الوحيد كتابة الواجهة الخلفية للمصادقة المخصصة؟

هل كانت مفيدة؟

المحلول

لا تحتاج إلى كلمة مرور لتسجيل المستخدم فيه. auth.login وظيفة فقط يأخذ User الكائن ، الذي من المفترض أن تحصل عليه بالفعل من قاعدة البيانات عند تمكين الحساب. حتى تتمكن من تمرير ذلك مباشرة login.

بالطبع ، ستحتاج إلى أن تكون جداً احرص على أنه لا توجد طريقة يمكن للمستخدم محادثة رابط إلى حساب موجود بالفعل بالفعل ، والذي من شأنه أن يسجلها تلقائيًا على أنه هذا المستخدم.

from django.contrib.auth import login

def activate_account(request, hash):
    account = get_account_from_hash(hash)
    if not account.is_active:
        account.activate()
        account.save()
        user = account.user
        login(request, user)

... إلخ.

تحرير:

حسنًا ، لم يلاحظ هذا الشرط للاستخدام authenticate بسبب الخاصية الإضافية التي يضيفها. بالنظر إلى الكود ، كل ما يفعله هو أ backend السمة المكافئة لمسار الوحدة النمطية للواجهة الخلفية المصادقة. لذلك يمكنك فقط مزيفة - قبل استدعاء تسجيل الدخول أعلاه ، قم بذلك:

user.backend = 'django.contrib.auth.backends.ModelBackend'

نصائح أخرى

إجابة دانيال جيدة جدًا.

هناك طريقة أخرى للقيام بذلك وهي إنشاء hashmodelbackend بعد خلفية التفويض المخصص https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#writing-an-authentication-backend مثله:

class HashModelBackend(object):
    def authenticate(self, hash=None):
        user = get_user_from_hash(hash)
        return user

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

ثم قم بتثبيت هذا في إعداداتك:

AUTHENTICATION_BACKENDS = (
    'myproject.backends.HashModelBackend',
    'django.contrib.auth.backends.ModelBackend',
)

ثم سيكون وجهة نظرك شيئًا من هذا القبيل:

def activate_account(request, hash):
    user = authenticate(hash=hash)
    if user:
        # check if user is_active, and any other checks
        login(request, user)
    else:
        return user_not_found_bad_hash_message

اعتبارًا من Django 1.10 ، تم تبسيط العملية.

في جميع إصدارات Django ، من أجل تسجيل الدخول ، يجب أن يكونوا مصادق عليه من قبل أحد أبراج التطبيق الخاص بك (يسيطر عليها AUTHENTICATION_BACKENDS ضبط).

إذا كنت ترغب ببساطة في فرض تسجيل الدخول ، فيمكنك فقط الادعاء بأن المستخدم تمت مصادقته من خلال الواجهة الخلفية الأولى من تلك القائمة:

from django.conf import settings
from django.contrib.auth import login


# Django 1.10+
login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0])

# Django <1.10 -  fake the authenticate() call
user.backend = settings.AUTHENTICATION_BACKENDS[0]
login(request, user)

استجابة ل دانإجابة.

طريقة لكتابة الواجهة الخلفية:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class HashModelBackend(ModelBackend):

def authenticate(self, username=None, **kwargs):
    UserModel = get_user_model()
    if username is None:
        username = kwargs.get(UserModel.USERNAME_FIELD)
    try:
        user = UserModel._default_manager.get_by_natural_key(username)
        return user
    except UserModel.DoesNotExist:
        return None

الجواب يعتمد على django.contrib.auth.backends.modelbackend مصدر الرمز. إنه فعلي لـ Django 1.9

وأفضل وضع الواجهة الخلفية المخصصة أدناه الافتراضي لـ Django:

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'yours.HashModelBackend',
]

لأن تنشيط الحساب أقل ممكنة من تسجيل الدخول نفسه. وفق https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#specification-authentication-backends:

إن ترتيب المصادقة _backends يهم ، لذلك إذا كان اسم المستخدم وكلمة المرور نفسه صالحًا في العديد من الخلايا الخلفية ، فسيتوقف Django عن المعالجة في المباراة الإيجابية الأولى.

كن حذراسيصادق هذا الرمز المستخدمين حتى بكلمات مرور غير صحيحة.

يمكنك استخدام ska الحزمة ، التي تحتوي على تسجيل الدخول إلى Django الذي يحتوي على كلمة مرور إلى Django. ska يعمل مع رموز المصادقة وأمانها على مشارك_كي والتي يجب أن تكون متساوية لجميع الأطراف (الخوادم) المعنية.

على جانب العميل (الطرف الذي يطلب تسجيل دخول أقل كلمة مرور) ، يمكنك إنشاء عنوان URL وتوقعه ، باستخدامه باستخدام ska. مثال:

from ska import sign_url
from ska.contrib.django.ska.settings import SECRET_KEY

server_ska_login_url = 'https://server-url.com/ska/login/'

signed_url = sign_url(
    auth_user='test_ska_user_0',
    secret_key=SECRET_KEY,
    url=server_ska_login_url
    extra={
        'email': 'john.doe@mail.example.com',
        'first_name': 'John',
        'last_name': 'Doe',
    }
)

العمر الافتراضي من الرمز المميز هو 600 ثانية. يمكنك تخصيص ذلك بإثبات أ lifetime جدال.

على جانب الخادم (الموقع الذي سجله للمستخدمين) ، مع الأخذ في الاعتبار أنك قمت بتثبيتها ska بشكل صحيح ، يتم تسجيل الدخول إلى المستخدم عند زيارة عنوان URL إذا كان موجودًا (تطابق اسم المستخدم) ، أو غير ذلك - تم إنشاؤه. هناك 3 عمليات اتصال يمكنك تخصيصها في إعدادات Django لمشروعك.

  • USER_GET_CALLBACK (سلسلة): تم إطلاقه إذا تم جلب المستخدم بنجاح من قاعدة البيانات (المستخدم الحالي).
  • USER_CREATE_CALLBACK (سلسلة): تم إطلاق النار مباشرة بعد إنشاء المستخدم (لم يكن المستخدم موجودًا).
  • USER_INFO_CALLBACK (سلسلة): أطلقت على المصادقة الناجحة.

انظر الوثائق (http://pythonhosted.org/ska/) للمزيد من.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top