当检索到的电子邮件与现有用户的电子邮件匹配时,django allauth facebook 重定向到注册?

Posted

技术标签:

【中文标题】当检索到的电子邮件与现有用户的电子邮件匹配时,django allauth facebook 重定向到注册?【英文标题】:django allauth facebook redirects to signup when retrieved email matches an existing user's email? 【发布时间】:2014-08-13 00:28:54 【问题描述】:

我可以使用 Django (1.6.4) 和 allauth (0.16.1) 和 Python (2.7) 成功通过 Google 和 Facebook 登录,并在没有现有用户的情况下重定向到 settings.LOGIN_REDIRECT_URL从提供商处检索到的电子邮件 ID。但是,当已经存在与从提供商(fb 或 goolge)检索到的用户具有相同 emailid 的用户时,它总是重定向到 /accounts/social/signup/#= 注册页面询问:

您即将使用您的 Facebook/Google 帐户登录 example.com。作为 最后一步,请填写以下表格: 电子邮件是自动填充的。

我用SOCIALACCOUNT_AUTO_SIGNUP = TrueFalse测试过,但没有效果。我尝试为 facebook 更改 auth_type,但我没有看到除“rerequest”以外的任何选项

我有以下settings.py:

ACCOUNT_AUTHENTICATION_METHOD = "email" # Defaults to username_email
ACCOUNT_USERNAME_REQUIRED = False       # Defaults to True
ACCOUNT_EMAIL_REQUIRED = True           # Defaults to False
SOCIALACCOUNT_QUERY_EMAIL = ACCOUNT_EMAIL_REQUIRED
SOCIALACCOUNT_AUTO_SIGNUP = True
SOCIALACCOUNT_EMAIL_REQUIRED = False
ACCOUNT_ADAPTER = "myproject.adapter.MyLoginAccountAdapter"
LOGIN_URL = "/"
LOGIN_REDIRECT_URL = "/users/id/mytags"

如何停止此重定向到注册,并让提供商登录重定向到具有相同电子邮件 ID 的现有用户的特定位置的 LOGIN_REDIRECT_URL?

注意:这个我试过了

我已经更新了 myproject.adapter.MyLoginAccountAdapter 中的 get_login_redirect_url。仅适用于 google,但不适用于 Django allauth - set facebook redirect 声称的 facebook 我已尝试“Bypass signup form using allauth”但不起作用

更新:

    感谢answer,我意识到在以下情况下,通过 facebook 登录将重定向到注册页面:当从 facebook 个人资料中检索到的电子邮件与现有用户的电子邮件 ID 匹配时。 我已更新问题以解决上述情况。 总而言之,这是多个提供商帐户具有相同电子邮件 ID 并且 django-allauth 不允许互换登录的情况(如果我使用 facebook 注册一次,django-allauth 将要求我仅使用 facebook 和不是谷歌或任何其他具有相同电子邮件 ID 的提供商) 我已经通过使用@receiver(pre_social_login)raise ImmediateHttpResponse(看看我的答案)和有用的链接解决了这个问题:this 和thisone

谢谢, 阿米特

【问题讨论】:

您想要用户的唯一电子邮件地址。 ?如果是,则该行为是必需的。 我只希望能够使用 facebook 和 google 以相同的电子邮件 ID 交替登录。我已经更新了这个问题。我也找到了答案。请看一下。 【参考方案1】:

这发生在我身上,原因是在再次向 Facebook 提交 access_token 以获取范围确定的数据后,不返回任何电子邮件或用户名。

    您需要确保 settings.py 上的 face_book 配置至少具有以下范围 'SCOPE': ['email', 'public_profile'], 在 facebook 开发者中设置应用程序为用户授予电子邮件

【讨论】:

【参考方案2】:

我在深入google和django和django-allauth的源代码后解决了这个问题

正在解决的问题:我只希望能够使用 facebook 和 google 使用相同的电子邮件 ID 交替登录,并在成功登录后始终重定向到 LOGIN_REDIRECT_URL,但 django-allauth 不允许我这样做.相反,它向我显示了一个我不想要的注册页面。

解决方案::使用@receiver(pre_social_login) 调用函数link_to_local_user(),该函数首先登录,然后引发 ImmediateHttpResponse 进而重定向到 LOGIN_REDIRECT_URL

#! myproject.adapter.py
from allauth.account.adapter import DefaultAccountAdapter
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
from allauth.exceptions import ImmediateHttpResponse
from allauth.socialaccount.signals import pre_social_login
from allauth.account.utils import perform_login
from allauth.utils import get_user_model
from django.http import HttpResponse
from django.dispatch import receiver
from django.shortcuts import redirect
from django.conf import settings
import json


class MyLoginAccountAdapter(DefaultAccountAdapter):
    '''
    Overrides allauth.account.adapter.DefaultAccountAdapter.ajax_response to avoid changing
    the HTTP status_code to 400
    '''

    def get_login_redirect_url(self, request):
        """ 
        """
        if request.user.is_authenticated():
            return settings.LOGIN_REDIRECT_URL.format(
                id=request.user.id)
        else:
            return "/"


class MySocialAccountAdapter(DefaultSocialAccountAdapter):
    '''
    Overrides allauth.socialaccount.adapter.DefaultSocialAccountAdapter.pre_social_login to 
    perform some actions right after successful login
    '''
    def pre_social_login(self, request, sociallogin):
        pass    # TODOFuture: To perform some actions right after successful login

@receiver(pre_social_login)
def link_to_local_user(sender, request, sociallogin, **kwargs):
    ''' Login and redirect
    This is done in order to tackle the situation where user's email retrieved
    from one provider is different from already existing email in the database
    (e.g facebook and google both use same email-id). Specifically, this is done to
    tackle following issues:
    * https://github.com/pennersr/django-allauth/issues/215

    '''
    email_address = sociallogin.account.extra_data['email']
    User = get_user_model()
    users = User.objects.filter(email=email_address)
    if users:
        # allauth.account.app_settings.EmailVerificationMethod
        perform_login(request, users[0], email_verification='optional')
        raise ImmediateHttpResponse(redirect(settings.LOGIN_REDIRECT_URL.format(id=request.user.id)))


#! settings.py
ACCOUNT_AUTHENTICATION_METHOD = "email" # Defaults to username_email
ACCOUNT_USERNAME_REQUIRED = False       # Defaults to True
ACCOUNT_EMAIL_REQUIRED = True           # Defaults to False
SOCIALACCOUNT_QUERY_EMAIL = ACCOUNT_EMAIL_REQUIRED
SOCIALACCOUNT_AUTO_SIGNUP = True
SOCIALACCOUNT_EMAIL_REQUIRED = False
ACCOUNT_ADAPTER = "myproject.adapter.MyLoginAccountAdapter"
SOCIALACCOUNT_ADAPTER = 'myproject.adapter.MySocialAccountAdapter'
LOGIN_URL = "/"
LOGIN_REDIRECT_URL = "/users/id/mytags"

【讨论】:

也许您也想尊重next 重定向功能:raise ImmediateHttpResponse(redirect(sociallogin.get_redirect_url(request))) @abarik - 这对我来说很有意义,我在我的代码中实现了相同的方法。但是,在登录用户并引发 ImmediateHttpResponse 之前,您似乎应该首先检查用户是否尚未与 social_account 关联。如果用户已连接,那么似乎不应该采取任何行动,应该允许他们继续。我的建议是在用户登录之前对user.socialaccount_set.count() == 0 进行简单检查。 这种方式似乎还是有问题,通过社交账号登录后,社交账号将无法连接到用户账号。 我只将 allauth 用于社交帐户,而对于本地帐户,我使用默认的 django 身份验证系统。所以这个解决方案不适合我。而且我还喜欢保留所有帐户(无论是社交帐户还是本地帐户)以保留唯一的电子邮件。顺便说一句,这样做对吗? 我仍然不明白这个库的作者几年后认为这是一个安全问题。如果您从根本上不信任 OAuth 提供者,他们为什么要创建这个库?

以上是关于当检索到的电子邮件与现有用户的电子邮件匹配时,django allauth facebook 重定向到注册?的主要内容,如果未能解决你的问题,请参考以下文章

如果新用户注册成功,如何打开一个屏幕,当现有用户使用 SwiftUI 成功登录时如何打开另一个屏幕?

是否可以使用客户端代码检索数据库数据? [复制]

检查电子邮件是不是匹配模糊

在 ASP.NET 中使用 Live Connect API 检索用户的电子邮件地址

现代 Web 应用程序中密码检索的有效技术

Gmail API:解码邮件正文(Java/Android)