Исключение AuthAlreadyAssociated в Django Social Auth

После того, как я создаю пользователя, используя, скажем, Facebook (скажем, fbuser) или Google (googleuser). Если я создаю другого пользователя через обычного администратора django (normaluser) и пытаюсь снова войти в систему с помощью Facebook или Google, пока третий пользователь (normaluser) вошел в систему, он выдает исключение ошибки AuthAlreadyAssociated.

  1. В идеале он должен выдать ошибку, что вы уже вошли в систему как пользователь normaluser.

  2. Или он должен выйти из системы обычного пользователя и попытаться установить связь с учетной записью, которая уже связана с FB или Google, в зависимости от обстоятельств.

Как мне реализовать одну из этих двух вышеперечисленных функций? Все советы приветствуются.

Также, когда я пытаюсь настроить SOCIAL_AUTH_PIPELINE, невозможно войти в систему с помощью FB или Google, и принудительно используется URL-адрес для входа /accounts/login/


person ramdaz    schedule 22.10.2012    source источник


Ответы (5)


В настоящее время DSA не отключает учетные записи (или не очищает сеансы). AuthAlreadyAssociated выделяет сценарий, в котором текущий пользователь не связан с текущей социальной учетной записью, которую пытаются использовать. Есть несколько решений, которые могут подойти для вашего проекта:

  1. Определите подкласс social_auth.middleware.SocialAuthExceptionMiddleware и переопределите поведение по умолчанию (process_exception()), чтобы перенаправить или настроить предупреждение, которое вам нравится, так, как вы предпочитаете.

  2. Добавьте конвейерный метод (заменяющий social_auth.backend.pipeline.social.social_auth_user), который выполняет выход текущего пользователя из системы вместо создания исключения.

person omab    schedule 23.10.2012
comment
Я пытался сделать вариант № 2, но это не удалось. Он успешно выходит из системы, но не возвращается как новый social.user. замена: msg = «Эта учетная запись {0} уже используется». - person nwilson5; 21.12.2013
comment
@omab: При социальной аутентификации Python с использованием Django, как мне легко в том же запросе выйти из системы текущего пользователя и настроить сеанс для второго пользователя, используя замену конвейера social_user? - person jacob; 14.01.2014
comment
@omab: В social.actions.do_complete is_authenticated устанавливается вначале на основе существующего пользователя (пользователь A). Но если я выйду из конвейера пользователя A и верну пользователя B, do_complete не войдет в систему пользователя B, потому что is_authenticated уже имеет значение True. Должен ли do_complete повторно оценивать пользователя сеанса после завершения конвейера, чтобы определить, следует ли входить в систему пользователю B? - person jacob; 14.01.2014

Решение для людей, которым интересно, как переопределить конвейер social_user в версии python-social-auth 3+

В вашем файле settings.py:

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.auth_allowed',
    # Path to your overrided method
    # You can set any other valid path.
    'myproject.apps.python-social-auth-overrided.pipeline.social_auth.social_user',
    'social_core.pipeline.user.get_username',
    'social_core.pipeline.user.create_user',
    'social_core.pipeline.social_auth.associate_user',
    'social_core.pipeline.social_auth.load_extra_data',
    'social_core.pipeline.user.user_details',
)

В вашем переопределенном social_user:

from django.contrib.auth import logout

def social_user(backend, uid, user=None, *args, **kwargs):
    provider = backend.name
    social = backend.strategy.storage.user.get_social_auth(provider, uid)
    if social:
        if user and social.user != user:
            logout(backend.strategy.request)
        elif not user:
            user = social.user
    return {'social': social,
            'user': user,
            'is_new': user is None,
            'new_association': False}

Вы можете удалить прокомментированные строки, если хотите.

person Adrian Lopez    schedule 05.12.2014
comment
ваш подход - выход из системы текущего пользователя. Но это не вход нового аутентифицированного пользователя. Любая помощь? - person rishabsaraf93; 23.03.2016

Мой подход к этой проблеме был немного другим: вместо того, чтобы решать эту проблему в конвейере, я в первую очередь позаботился о том, чтобы пользователь никогда не попадал в конвейер. Таким образом, даже если social_auth.user не соответствует вошедшему в систему пользователю, social_auth.user будет входить в систему поверх текущего вошедшего в систему пользователя.

Я думаю, что это так же просто, как переопределить действие complete.

urls.py

url(r'^complete/(?P<backend>[^/]+)/$', 'account.views.complete', name='complete'),

аккаунт/views.py

from social.actions import do_complete
from social.apps.django_app.utils import strategy
from social.apps.django_app.views import _do_login

@csrf_exempt
@strategy('social:complete')
def complete(request, backend, *args, **kwargs):
    """Override this method so we can force user to be logged out."""
    return do_complete(request.social_strategy, _do_login, user=None,
                       redirect_name=REDIRECT_FIELD_NAME, *args, **kwargs)
person CambridgeMike    schedule 08.08.2014
comment
Где-то со временем мое предыдущее решение, похоже, больше не работает должным образом, возможно, с последней социальной аутентификацией python. В любом случае ваше решение работает правильно и, безусловно, проще моего. Я удалил свой из этого вопроса. Спасибо. - person jacob; 08.06.2015
comment
Это не работает (как есть), потому что исходное представление complete немного изменилось. Мне пришлось погрузиться в исходный код и немного подправить его, чтобы он соответствовал изменениям, но стратегия надежна, переопределить пользовательский параметр, безоговорочно передавая None. - person Paulo Scardine; 04.11.2015
comment
последняя рабочая (версия 0.3.x) версия полной функции для меня maketips.net/tip/450/ - person Ivan Borshchov; 05.11.2017

У меня та же проблема. Я решил это, вставив код ниже в настройках

AUTHENTICATION_BACKENDS = (
    '...',
    'social_core.backends.facebook.FacebookOAuth2',
    '...',
)
SOCIAL_AUTH_PIPELINE = (
    '...',
    'social_core.pipeline.user.user_details',
    '...',
)
person anjaneyulubatta505    schedule 14.03.2017
comment
Не уверен, это не неверный ответ. - person Shayne; 31.05.2019

Что я сделал:

  1. Определите класс, который наследуется от SocialAuthExceptionMiddleware

  2. Реализовать метод process_exception,

  3. Добавьте реализованный класс в список MIDDLEWARE на settings.py.

В middleware.py, который должен находиться в каталоге ваших приложений, т. е. в том же каталоге вашего файла views.py, который связан с вашим приложением, определите следующий класс:

from django.shortcuts import redirect
from django.urls import reverse

from social_core.exceptions import AuthAlreadyAssociated

class FacebookAuthAlreadyAssociatedMiddleware(SocialAuthExceptionMiddleware):
    """Redirect users to desired-url when AuthAlreadyAssociated exception occurs."""
    def process_exception(self, request, exception):
        if isinstance(exception, AuthAlreadyAssociated):
            if request.backend.name == "facebook":
                message = "This facebook account is already in use."
                if message in str(exception):
                    # Add logic if required

                    # User is redirected to any url you want
                    # in this case to "app_name:url_name"
                    return redirect(reverse("app_name:url_name"))

В settings.py добавьте реализованный класс в список MIDDLEWARE:

MIDDLEWARE = [
    # Some Django middlewares
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.locale.LocaleMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "social_django.middleware.SocialAuthExceptionMiddleware",

    # the middleware you just implemented
    "app_name.middleware.FacebookAuthAlreadyAssociatedMiddleware",
]

Это решило мою проблему, и я смог обработать поток управления, когда возникло исключение AuthAlreadyAssociated.

person lmiguelvargasf    schedule 27.07.2018