Django Social Auth中的AuthAlreadyAssociated Exception

时间:2012-10-22 19:12:59

标签: python django django-socialauth

在我使用说Facebook(让我们说fbuser)或Google(googleuser)创建用户之后。如果我通过普通的django admin(normaluser)创建另一个用户,并在第三个用户(normaluser)登录时尝试使用Facebook或Google再次登录,则会抛出错误异常AuthAlreadyAssociated。

  1. 理想情况下,它应该抛出一个名为您已登录的错误 用户normaluser。

  2. 或者它应该注销普通用户,并尝试与之关联 已经与FB或Google关联的帐户,视情况而定 可能是。

  3. 如何实施上述两项功能之一?欢迎所有建议。

    此外,当我尝试自定义SOCIAL_AUTH_PIPELINE时,无法使用FB或Google登录,并强制登录网址/ accounts / login /

5 个答案:

答案 0 :(得分:11)

DSA目前不会注销帐户(或刷新会话)。 AuthAlreadyAssociated突出显示当前用户未与尝试使用的当前社交帐户相关联的情况。有几种解决方案可能适合您的项目:

  1. 定义social_auth.middleware.SocialAuthExceptionMiddleware的子类并覆盖默认行为(process_exception()),以您喜欢的方式重定向或设置您喜欢的警告。

  2. 添加注销当前用户的管道方法(替换social_auth.backend.pipeline.social.social_auth_user),而不是引发异常。

答案 1 :(得分:3)

我解决这个问题的方法略有不同,而不是在管道中解决这个问题,我确保用户从未首先进入管道。这样,即使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)

答案 2 :(得分:3)

人们想知道如何在python-social-auth版本0.2.x下覆盖social_user管道的解决方案

在您的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',
)

在您的首要社会用户

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}

如果需要,您可以删除注释行。

答案 3 :(得分:0)

我遇到了同样的问题。我通过在设置中插入以下代码来解决它

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

答案 4 :(得分:0)

我所做的是:

  1. 定义一个继承自SocialAuthExceptionMiddleware

  2. 的类
  3. 实现方法process_exception

  4. 将实现的类添加到 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异常时,我能够处理控制流程。