django-allauth 社交帐户在登录时连接到现有帐户
django-allauth social account connect to existing account on login
我有一个自定义用户模型,我正在使用 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.
任何帮助将不胜感激。
我也知道其中的安全问题。但我还是想试试这个。
我设法通过稍微更改适配器的代码来实现此功能。
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
,我们必须在 settings.py
文件中指定 SOCIALACCOUNT_ADAPTER = 'myapp.my_adapter.MySocialAccountAdapter'
我找到了以下解决方案 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
它与最新的 allauth
开箱即用。您可以在模板中使用以下内容:
{% load socialaccount %}
<a href="{% provider_login_url "spotify" process="connect" %}">connect spotify account</a>
URL如下:
/accounts/spotify/login/?process=connect
不需要内部修改。
我有一个自定义用户模型,我正在使用 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.
任何帮助将不胜感激。
我也知道其中的安全问题。但我还是想试试这个。
我设法通过稍微更改适配器的代码来实现此功能。
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
,我们必须在 settings.py
文件中指定 SOCIALACCOUNT_ADAPTER = 'myapp.my_adapter.MySocialAccountAdapter'
我找到了以下解决方案 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
它与最新的 allauth
开箱即用。您可以在模板中使用以下内容:
{% load socialaccount %}
<a href="{% provider_login_url "spotify" process="connect" %}">connect spotify account</a>
URL如下:
/accounts/spotify/login/?process=connect
不需要内部修改。