django-allauth社交帐户在登录时连接到现有帐户

时间:2015-03-06 10:51:38

标签: python django django-allauth

我有一个自定义用户模型,我正在使用django-allauth进行社交注册和登录。 当用户使用已经使用电子邮件注册的社交帐户登录时,我正在尝试将现有用户连接到新的社交帐户。我找到了link

def pre_social_login(self, request, sociallogin):
    user = sociallogin.account.user
    if user.id:
        return
    try:
        customer = Customer.objects.get(email=user.email)
    except Customer.DoesNotExist:
        pass
    else:
        perform_login(request, customer, 'none')

但是当我尝试通过社交帐户登录时,我收到了错误。

RelatedObjectDoesNotExist at /accounts/facebook/login/callback/
SocialAccount has no user.

任何帮助将不胜感激。

此外,我也知道安全问题。但我还是想尝试一下。

3 个答案:

答案 0 :(得分:16)

我设法通过稍微改变适配器的代码来实现这一点。

adapter.py

from allauth.socialaccount.adapter import DefaultSocialAccountAdapter

class MySocialAccountAdapter(DefaultSocialAccountAdapter):
    def pre_social_login(self, request, sociallogin): 
        user = sociallogin.user
        if user.id:  
            return          
        try:
            customer = Customer.objects.get(email=user.email)  # if user exists, connect the account to the existing account and login
            sociallogin.state['process'] = 'connect'                
            perform_login(request, customer, 'none')
        except Customer.DoesNotExist:
            pass

如果继承DefaultSocialAccountAdapter,我们必须在SOCIALACCOUNT_ADAPTER = 'myapp.my_adapter.MySocialAccountAdapter'文件中指定settings.py

答案 1 :(得分:1)

我找到了以下解决方案here,它还会检查电子邮件地址是否已经过验证。

from allauth.account.models import EmailAddress

def pre_social_login(self, request, sociallogin):

        # social account already exists, so this is just a login
        if sociallogin.is_existing:
            return

        # some social logins don't have an email address
        if not sociallogin.email_addresses:
            return

        # find the first verified email that we get from this sociallogin
        verified_email = None
        for email in sociallogin.email_addresses:
            if email.verified:
                verified_email = email
                break

        # no verified emails found, nothing more to do
        if not verified_email:
            return

        # check if given email address already exists as a verified email on
        # an existing user's account
        try:
            existing_email = EmailAddress.objects.get(email__iexact=email.email, verified=True)
        except EmailAddress.DoesNotExist:
            return

        # if it does, connect this new social login to the existing user
        sociallogin.connect(request, existing_email.user)

如果您希望跳过验证步骤,我认为此解决方案仍然有点好处:

def pre_social_login(self, request, sociallogin):

    user = sociallogin.user
    if user.id:
        return
    if not user.email:
        return

    try:
        user = User.objects.get(email=user.email)  # if user exists, connect the account to the existing account and login
        sociallogin.connect(request, user)
    except User.DoesNotExist:
        pass

答案 2 :(得分:1)

使用最新的allauth开箱即用。您可以在模板中使用以下内容:

{% load socialaccount %}
<a href="{% provider_login_url "spotify" process="connect" %}">connect spotify account</a>

URL如下:

/accounts/spotify/login/?process=connect

不需要内部修改。