2014-06-23 18 views
17

Z powodzeniem mogę zalogować się przez Google i Facebooka za pomocą Django (1.6.4) i allauth (0.16.1) i Python (2.7) z oczekiwanym przekierowaniem do ustawień.LOGIN_REDIRECT_URL w przypadku, gdy nie ma istniejącego użytkownika z emailidem pobrany od dostawcy. Jednak, gdy istnieje już użytkownik o takim samym EMAILID jako jeden pobranej od dostawcy (fb lub goolge), to zawsze przekierowuje do/accounts/social/rejestracja/# = strona zarejestruj wywoławcza:django allauth facebook przekierowuje do rejestracji, gdy pobrany e-mail pasuje do adresu e-mail istniejącego użytkownika?

Jesteś o użyciu konta Facebook/Google do zalogowania się na example.com. Ostatnim krokiem jest : E-mail jest automatycznie wypełniany.

Testowałem z SOCIALACCOUNT_AUTO_SIGNUP = True lub False, ale bez efektu. Próbuję zmienić AUTH_TYPE na Facebooku, ale nie widzę żadnych innych niż opcje „rerequest”

Mam następujący 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 = "https://stackoverflow.com/users/{id}/mytags" 

Jak mogę zatrzymać tego Przekierowanie do rejestracja, i mieć dostawca logowania przekierować do LOGIN_REDIRECT_URL w szczególności już istniejącego użytkownika z tym samym emailidem?

UWAGA: Próbowałem

aktualizacje:

  1. Dzięki tej answer, zdałem sobie sprawę, że logowanie przez facebook przekieruje do strony rejestracji w przypadku: gdy wiadomość e-mail pobrana z profilu na Facebooku pasuje do adresu e-mail istniejącego użytkownika.
  2. Mam zaktualizowane pytanie w celu uwzględnienia powyższej sprawy.
  3. Podsumowując, jest to przypadek, w którym wiele kont dostawców ma taki sam identyfikator e-mail, a django-allauth nie pozwala na zamiennie logowania (ei jeśli raz zarejestrowałem się przy użyciu Facebooka, django-allauth będzie wymagać ode mnie używania tylko Facebooka i nie google lub cokolwiek innego dostawcy z tym samym identyfikatorem e-mail)
  4. mam rozwiązać go za pomocą @receiver(pre_social_login) i raise ImmediateHttpResponse (spójrz na moją odpowiedź) z przydatnych linków: this i thisone

Dzięki Amit

+0

Chcesz unikalny adres e-mail użytkownika. ? Jeśli tak, to zachowanie jest czymś, co jest wymagane. – vibhor

+0

Po prostu chcę możliwość wymienianego logowania za pomocą Facebooka i google z tym samym identyfikatorem e-mail. Zaktualizowałem pytanie. Znalazłem też odpowiedź. Proszę, spójrz na to. – abarik

Odpowiedz

13

mam rozwiązać go po kopanie w głąb google i kod źródłowy Django Django-allauth

Problem jest rozwiązany: Chcę tylko zdolność zamiennie logowanie przez Facebooka i Google z tym samym identyfikatorem e-mail i zawsze przekierowanie LOGIN_REDIRECT_URL po udanym logowaniu, ale django-allauth nie pozwala mi tego zrobić. Zamiast tego pokazuje mi stronę rejestracji, której nie chcę.

Rozwiązanie: Use @receiver(pre_social_login) wywołać funkcję link_to_local_user() który loguje się 1, a następnie podnosi ImmediateHttpResponse co z kolei przekierowuje do 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 = "https://stackoverflow.com/users/{id}/mytags" 
+0

Może chcesz również uszanować funkcję przekierowania 'next': raise ImmediateHttpResponse (przekierowanie (sociallogin.get_redirect_url (request))) – sspross

+0

@abarik - to ma dla mnie wiele sensu, a ja zaimplementowałem to samo podejście w moim kodzie. Jednak przed zalogowaniem użytkownika i podniesieniem ImmediateHttpResponse wydaje się, że powinieneś najpierw sprawdzić, czy użytkownik nie jest jeszcze powiązany z kontem social_account. Jeśli użytkownik jest podłączony, wydaje się, że nie należy podejmować żadnych działań i powinien im zezwolić na kontynuowanie. Moja sugestia jest prostym sprawdzeniem dla 'user.socialaccount_set.count() == 0' przed zalogowaniem użytkownika. –

+2

Wygląda na to, że problem z takim podejściem będzie nadal występował po zalogowaniu się za pośrednictwem portalu społecznościowego. konto społecznościowe nie zostanie połączone z kontem użytkownika. – Devang