【问题标题】:AuthAlreadyAssociated Exception in Django Social AuthDjango Social Auth中的AuthAlreadyAssociated异常
【发布时间】:2022-04-21 02:14:58
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: python django django-socialauth


    【解决方案1】:

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

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

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

    【讨论】:

    • 我尝试执行选项#2,但没有成功。它成功地注销了用户,但没有作为新的 social.user 重新登录。替换: msg = '此 {0} 帐户已在使用中。'.format(provider) raise AuthAlreadyAssociated(strategy.backend, msg) with: logout(kwargs.get('request')) user = social.user跨度>
    • @omab:在使用 Django 的 python social auth 上,我如何在同一个请求中无缝地注销当前用户并使用 social_user 管道替换为第二个用户设置会话?
    • @omab:在 social.actions.do_complete 中,is_authenticated 是根据现有用户(“用户 A”)在开头设置的。但是,如果我在管道中注销“用户 A”并返回“用户 B”,do_complete 将不会登录“用户 B”,因为它的 is_authenticated 已设置为 True。 do_complete是否应该在管道完成后再次重新评估会话用户以确定是否登录“用户B”?
    【解决方案2】:

    为想知道如何在 python-social-auth 版本 3+ 下覆盖 social_user 管道的人提供的解决方案

    在您的 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}
    

    您可以根据需要删除注释行。

    【讨论】:

    • 您的方法是注销当前用户。但它没有登录新认证的用户。有什么帮助吗?
    【解决方案3】:

    我解决这个问题的方法有点不同,我没有在管道中解决这个问题,而是首先确保用户永远不会被传递到管道中。这样,即使 social_auth.user 与登录用户不匹配,social_auth.user 也会在当前登录用户之上登录。

    我认为这就像覆盖 complete 操作一样简单。

    urls.py

    path('complete/<str:backend>/', 'account.views.complete', name='complete'),
    

    帐户/views.py

    from django.contrib.auth import REDIRECT_FIELD_NAME
    from django.views.decorators.cache import never_cache
    from django.views.decorators.csrf import csrf_exempt
    from social_core.actions import do_complete
    from social_django.utils import psa
    from social_django.views import _do_login
    
    @never_cache
    @csrf_exempt
    @psa('social:complete')
    def complete(request, backend, *args, **kwargs):
        """Override this method so we can force user to be logged out."""
        return do_complete(request.backend, _do_login, user=None,
                           redirect_name=REDIRECT_FIELD_NAME, request=request,
                           *args, **kwargs)
    

    【讨论】:

    • 随着时间的推移,我之前的解决方案似乎不再正常工作,也许是使用最新的 python social auth。无论如何,您的解决方案确实可以正常工作,而且肯定比我的更简单。我已经从这个问题中删除了我的。谢谢。
    • 这不起作用(原样),因为原始 complete 视图略有变化。我不得不深入研究源代码并对其进行一些调整以匹配更改,但是策略是可靠的,无条件地覆盖用户参数。
    • 对我来说完整功能的最新工作(0.3.x版本)版本maketips.net/tip/450/…
    【解决方案4】:

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

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

    【讨论】:

    • 不确定,不是无效答案。
    【解决方案5】:

    我所做的是:

    1. 定义一个继承自SocialAuthExceptionMiddleware的类

    2. 实现方法process_exception

    3. 将实现的类添加到settings.py上的MIDDLEWARE列表中。

    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 异常时我能够处理控制流。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-18
      • 1970-01-01
      • 2017-11-11
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多