Python Social Auth为不同用户复制电子邮件

时间:2016-11-16 10:30:57

标签: django django-authentication python-social-auth

在我的网站上可以登录:

  • 用户名和密码
  • 电子邮件和密码
  • google auth 2

我在使用django用户内置系统和python社会认证。

问题:

假设我创建了以下帐户:

用户名:losimonassi 电子邮件:lorenzosimonassi@gmail.com

然后当我尝试使用我的gmail(lorenzosimonassi@gmail.com)登录时,python social auth会使用相同的电子邮件创建另一个用户。因此,当我尝试使用我的电子邮件登录时,auth系统会发现两个类似的电子邮件,这会引发错误。

我试图找到一种方法,当用户尝试使用gmail登录时,他的电子邮件会被检查,如果它已经存在,则会通过重定向和警告消息停止进程(我认为它可能是通过中间件制作的。)

但是当然对数据库的检查应该只检查其他后端用户和普通用户,以避免阻止他自己的登录。

我不想关联帐户。

settings.py

SOCIAL_AUTH_PIPELINE = (
    'social.pipeline.social_auth.social_details',
    'social.pipeline.social_auth.social_uid',
    'social.pipeline.social_auth.auth_allowed',
    'social.pipeline.social_auth.social_user',
    'social.pipeline.user.get_username',
    'social.pipeline.user.create_user',
    #'social.pipeline.social_auth.associate_user',
    #'social.pipeline.social_auth.load_extra_data',
    'social.pipeline.user.user_details'
)

admin image

2 个答案:

答案 0 :(得分:1)

您可以选择按用户的电子邮件地址关联用户,方法是在管道中添加内置但默认情况下不活动的步骤。 请注意,只有在您确定社交提供商验证电子邮件地址时才应执行此操作。否则,我可以使用您的电子邮件注册社交提供商,登录您的网站并访问您网站上的用户。

Python社交身份验证文档以及如何通过电子邮件关联用户: https://python-social-auth-docs.readthedocs.io/en/latest/use_cases.html?highlight=associate%20user#associate-users-by-email

从以上链接:

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.auth_allowed',
    'social_core.pipeline.social_auth.social_user',
    'social_core.pipeline.user.get_username',
    'social_core.pipeline.social_auth.associate_by_email',  # <--- enable this one
    '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',
)

答案 1 :(得分:0)

我遇到过你描述的情况。方式我解决了它:向社会认证管道添加自定义步骤:

def check_email_exists(backend, details, uid, user=None, *args, **kwargs):
    email = details.get('email', '')
    provider = backend.name

    # check if social user exists to allow logging in (not sure if this is necessary)
    social = backend.strategy.storage.user.get_social_auth(provider, uid)
    # check if given email is in use
    exists = User.objects.filter(username=email).exists()

    # user is not logged in, social profile with given uid doesn't exist
    # and email is in use
    if not user and not social and exists:
        raise AuthException(backend)

将您的callable添加到管道:

SOCIAL_AUTH_PIPELINE = (
    'social.pipeline.social_auth.social_details',
    'social.pipeline.social_auth.social_uid',
    'social.pipeline.social_auth.auth_allowed',
    'social.pipeline.social_auth.social_user',
    'social.pipeline.user.get_username',
    'path.to.module.check_email_exists',  # move if appropriate
    'social.pipeline.user.create_user',
    'social.pipeline.user.user_details'
)

提升AuthException会将用户重定向到您的settings.SOCIAL_AUTH_LOGIN_ERROR_URL。但是,如果这不是你想要的,那么还有另一种方法。 Python-social-auth检查管道任何部分的返回值。如果返回值为None,则会继续。如果它是dict,它将使用该字典更新kwargs,以便稍后在管道中可以使用这些值。但是,如果返回值为HttpResponse,例如HttpResponseRedirect,则会将该响应返回给用户。因此,您可以执行

,而不是提出AuthException
return HttpResponseRedirect(reverse('desired-endpoint'))

但是,请注意这一点:文档没有明确说明这一点,而且我很久以前也这样做了,所以我可能会弄错。