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

问题描述 投票:0回答:3

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

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

我用

SOCIALACCOUNT_AUTO_SIGNUP = True
False
测试过,但没有效果。我尝试更改 facebook 的 auth_type,但除了“重新请求”之外我没有看到任何选项

我有以下设置.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"

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

注意:这个我已经尝试过了

更新:

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

django django-allauth
3个回答
28
投票
在深入研究 google 和 django 和 django-allauth 的源代码后我已经解决了它

问题正在解决:我只是希望能够使用相同的电子邮件 ID 使用 facebook 和 google 互换登录,并在成功登录后始终重定向到 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"
    

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

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

0
投票
我在 2024 年使用 Django 4.2 和 AllAuth 0.61.1 遇到了同样的问题

我使用了@amulllb 答案,但它有点过时了。

以下内容针对 Django 4.2 和 AllAuth 0.61.1 进行更新和测试,特别是针对 microsoft oauth 提供程序,网址为

https://docs.allauth.org/en/latest/socialaccount/providers/microsoft.html

在适配器.py中

from allauth.account.adapter import DefaultAccountAdapter from allauth.account.utils import perform_login from allauth.exceptions import ImmediateHttpResponse from allauth.socialaccount.adapter import DefaultSocialAccountAdapter from allauth.socialaccount.signals import pre_social_login from allauth.utils import get_user_model from django.conf import settings from django.dispatch import receiver from django.shortcuts import redirect # change yourproject.exceptions accordingly from yourproject.exceptions import EmailNotFoundException """ taken from https://stackoverflow.com/a/24358708/80353 tested against django 4.2 allauth 0.61.1 must use these as settings ACCOUNT_AUTHENTICATION_METHOD = "email" # Defaults to username_email ACCOUNT_USERNAME_REQUIRED = False # Defaults to True ACCOUNT_EMAIL_REQUIRED = True # Defaults to False THE FOLLOWING ARE USING DEFAULT, so can choose not to set SOCIALACCOUNT_QUERY_EMAIL = ACCOUNT_EMAIL_REQUIRED SOCIALACCOUNT_AUTO_SIGNUP = True SOCIALACCOUNT_EMAIL_REQUIRED = ACCOUNT_EMAIL_REQUIRED # change yourproject.adapter accordingly ACCOUNT_ADAPTER = "yourproject.adapter.MyLoginAccountAdapter" SOCIALACCOUNT_ADAPTER = 'yourproject.adapter.MySocialAccountAdapter' """ 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): """ get the redirect login """ 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 """ # Most oauth providers use "email" # but for microsoft graph uses "mail" # Check for 'email' or 'mail' in sociallogin.account.extra_data email_address = sociallogin.account.extra_data.get( "email" ) or sociallogin.account.extra_data.get("mail") if not email_address: # If neither is found, raise the custom exception raise EmailNotFoundException() User = get_user_model() if users := User.objects.filter(email=email_address): # 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)) )
在例外情况.py

class EmailNotFoundException(Exception): """Exception raised when email is not found in social login data.""" def __init__(self, message="Email or mail not found in social login data"): self.message = message super().__init__(self.message)
这与@amulllb 的答案有何不同?

  1. @amullb 使用

    is_authenticated()

     而我更改为 .is_authenticated 因为 Django 停止使用 is_authenticated 作为方法一段时间了。

  2. @amullb 假设

    email_address = sociallogin.account.extra_data['email']

    ,而我检查了 
    email
    mail
    mail
     是 Microsoft Graph 返回的内容。我还添加了一个例外,以防提供者既不使用 
    email
     也不使用 
    mail

  3. 我明确了必须使用的设置及其值,但我将它们更新为allauth 0.61.1

© www.soinside.com 2019 - 2024. All rights reserved.