Authalreadyassociated исключение в социальной аутентификации Django

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

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

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

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

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

5 ответов


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

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

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


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

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

urls.py

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

account/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)

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

в вашем settings.py:

SOCIAL_AUTH_PIPELINE = (
    'social.pipeline.social_auth.social_details',
    'social.pipeline.social_auth.social_uid',
    'social.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.pipeline.user.get_username',
    'social.pipeline.user.create_user',
    'social.pipeline.social_auth.associate_user',
    'social.pipeline.social_auth.load_extra_data',
    'social.pipeline.user.user_details',
)

в social_user перекрытая:

from django.contrib.auth import logout
def social_user(backend, uid, user=None, *args, **kwargs):
    '''OVERRIDED: It will logout the current user
    instead of raise an exception '''

    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)
            #msg = 'This {0} account is already in use.'.format(provider)
            #raise AuthAlreadyAssociated(backend, msg)
        elif not user:
            user = social.user
    return {'social': social,
            'user': user,
            'is_new': user is None,
            'new_association': False}

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


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

AUTHENTICATION_BACKENDS = (
    '...',
    'social_core.backends.facebook.FacebookOAuth2',
    '...',
)
SOCIAL_AUTH_PIPELINE = (
    '...',
    'social_core.pipeline.user.user_details',
    '...',
)

что я сделал:

  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 исключение.