问题 Django Social Auth中的AuthAlreadyAssociated Exception


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

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

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

如何实现以上两个功能之一?欢迎所有建议。

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


1018
2017-10-22 19:12


起源



答案:


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

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

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


10
2017-10-23 14:36



我尝试做选项#2,但没有成功。它成功地将用户注销,但不作为新的social.user返回。替换:msg ='此{0}帐户已被使用。'。format(provider)使用以下命令引发AuthAlreadyAssociated(strategy.backend,msg):logout(kwargs.get('request'))user = social.user - nwilson5
@omab:在使用Django的python社交认证中,如何在同一请求中无缝地注销当前用户并使用social_user管道替换为第二个用户设置会话? - jacob
@omab:在social.actions.do_complete中,is_authenticated基于现有用户(“用户A”)在开头设置。但是如果我在管道中注销“用户A”并返回“用户B”,则do_complete将不会登录“用户B”,因为它已经设置为“已验证”。在管道完成后do_complete是否应该再次重新评估会话用户以确定是否登录“用户B”? - jacob


答案:


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

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

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


10
2017-10-23 14:36



我尝试做选项#2,但没有成功。它成功地将用户注销,但不作为新的social.user返回。替换:msg ='此{0}帐户已被使用。'。format(provider)使用以下命令引发AuthAlreadyAssociated(strategy.backend,msg):logout(kwargs.get('request'))user = social.user - nwilson5
@omab:在使用Django的python社交认证中,如何在同一请求中无缝地注销当前用户并使用social_user管道替换为第二个用户设置会话? - jacob
@omab:在social.actions.do_complete中,is_authenticated基于现有用户(“用户A”)在开头设置。但是如果我在管道中注销“用户A”并返回“用户B”,则do_complete将不会登录“用户B”,因为它已经设置为“已验证”。在管道完成后do_complete是否应该再次重新评估会话用户以确定是否登录“用户B”? - jacob


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

3
2017-08-08 19:33



随着时间的推移,我早期的解决方案似乎不再适用,可能与最新的python社会认证。无论如何,您的解决方案确实可以正常工作,并且肯定比我的解决方案更简单。我已经从这个问题中删除了我的。谢谢。 - jacob
这不起作用(因为原来) complete 视图略有变化。我不得不潜入源代码并调整一下以匹配更改,但策略是可靠的,覆盖用户参数无条件地传递None。 - Paulo Scardine
我的完整功能的最新工作(0.3.x版本)版本 maketips.net/tip/450/... - user3479125


人们想知道如何在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',
)

在你压倒一切的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}

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


2
2017-12-05 18:09



您的方法是注销当前用户。但它没有登录新认证的用户。有帮助吗? - rishabsaraf93


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

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

0
2018-03-14 13:35





我所做的是:

  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 提出异常。


0
2017-07-27 21:28