Sto utilizzando l'SDK di Facebook iOS per inviare il token di accesso di Facebook al mio URI del server Django. La funzione views.py corrispondente è mostrata di seguito e ottengo un codice di risposta 200 quando eseguo il POST da iOS. Tuttavia, ho un secondo URI decorato @ login_required che chiamo dal dispositivo iOS immediatamente afterword che mi considera non connesso e che mi reindirizza alla mia pagina principale. Che cosa sto facendo di sbagliato? Come posso "rimanere" connesso dopo il mio POST di successo da iOS?django-allauth accesso con token Facebook dal dispositivo iOS
# For POSTing the facebook token
from django.views.decorators.csrf import csrf_exempt
from allauth.socialaccount import providers
from allauth.socialaccount.models import SocialLogin, SocialToken, SocialApp
from allauth.socialaccount.providers.facebook.views import fb_complete_login
from allauth.socialaccount.helpers import complete_social_login
# Log in from Facebook
@csrf_exempt
def mobile_facebook_login(request):
response = HttpResponse() ## Create an HTTP Response Object
if request.method == "POST": # The method better be a POST
access_token = request.POST.get('access_token') # Get token
try:
app = SocialApp.objects.get(provider="facebook")
token = SocialToken(app=app, token=access_token)
# Check token against facebook
login = fb_complete_login(request, app, token)
login.token = token
login.state = SocialLogin.state_from_request(request)
# Add or update the user into users table
ret = complete_social_login(request, login)
# If we get here we've succeeded
response['Auth-Response'] = 'success'
response.status_code = 200 # Set status
return response
except Exception,e:
# If we get here we've failed
response['Auth-Response'] = 'failure: %s'%(e)
response.status_code = 401 # Set status
return response
else:
# If we get here we've failed
response['Auth-Response'] = 'failure'
response.status_code = 401 # Set status
return response
UPDATE ======= ==========
Ok, grazie per i commenti. Così ora invio anche l'indirizzo email di Facebook e chiedo l'accesso e l'accesso manuale. Tuttavia, le richieste successive STILL non sono autenticate. Quindi il decoratore @login_required fallisce ancora. Altre idee?
# Log in from Facebook
@csrf_exempt
def mobile_facebook_login(request):
response = HttpResponse() ## Create an HTTP Response Object
if request.method == "POST": # The method better be a POST
access_token = request.POST.get('access_token') # Get token
email = request.POST.get('email') # Get email
try:
app = SocialApp.objects.get(provider="facebook")
token = SocialToken(app=app, token=access_token)
# Check token against facebook
login = fb_complete_login(request, app, token)
login.token = token
login.state = SocialLogin.state_from_request(request)
# Add or update the user into users table
ret = complete_social_login(request, login)
# Try to get username from email
try:
user = User.objects.get(email=email) # Get User
# Login the user from Django's perspective
user.backend = 'django.contrib.auth.backends.ModelBackend'
auth_login(request,user)
except User.DoesNotExist:
# If we get here we've failed
response['Auth-Response'] = 'failure: %s'%(e)
response.status_code = 401 # Set status
return response
# If we get here we've succeeded
response['Auth-Response'] = 'success'
response.status_code = 200 # Set status
return response
except Exception,e:
# If we get here we've failed
response['Auth-Response'] = 'failure: %s'%(e)
response.status_code = 401 # Set status
return response
else:
# If we get here we've failed
response['Auth-Response'] = 'failure'
response.status_code = 401 # Set status
return response
==== Un altro aggiornamento ==========
Sulla base della seconda risposta in questo post: django authentication without a password
ho creato un backend di login personalizzato che fa non richiede una password. La terza risposta in questo post discute come:
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
Non memorizza la convalida dell'accesso nella sessione. Così ho provato a utilizzare un back-end personalizzato.
Ecco il mio codice modificato:
# Log in from Facebook
@csrf_exempt
def mobile_facebook_login(request):
response = HttpResponse() ## Create an HTTP Response Object
if request.method == "POST": # The method better be a POST
access_token = request.POST.get('access_token') # Get token
email = request.POST.get('email') # Get email
try:
app = SocialApp.objects.get(provider="facebook")
token = SocialToken(app=app, token=access_token)
# Check token against facebook
login = fb_complete_login(request, app, token)
login.token = token
login.state = SocialLogin.state_from_request(request)
# Add or update the user into users table
ret = complete_social_login(request, login)
# Try to get username from email
try:
user = User.objects.get(email=email) # Get User
# Login the user from Django's perspective
user.backend = 'django_tours.auth_backend.PasswordlessAuthBackend'
user = authenticate(email=user.email)
auth_login(request,user)
#request.session.cycle_key()
except User.DoesNotExist:
# If we get here we've failed
response['Auth-Response'] = 'failure: %s'%(e)
response.status_code = 401 # Set status
return response
# If we get here we've succeeded
response['Auth-Response'] = 'success'
response['User-Is-Authenticated'] = '%s'%(request.user.is_authenticated())
response.status_code = 200 # Set status
return response
except Exception,e:
# If we get here we've failed
response['Auth-Response'] = 'failure: %s'%(e)
response.status_code = 401 # Set status
return response
else:
# If we get here we've failed
response['Auth-Response'] = 'failure'
response.status_code = 401 # Set status
return response
Utilizzando hurl.it ho questa risposta HTTP 200, ma sono ancora considerati loggato da iPhone:
Auth-Response: success
Content-Encoding: gzip
Content-Length: 20
Content-Type: text/html; charset=utf-8
Date: Thu, 08 May 2014 00:22:47 GMT
Server: Apache/2.2.22 (Ubuntu)
Set-Cookie: csrftoken=UuJDP6OB3YCSDtXLEa10MgJ70tDtIfZX; expires=Thu, 07-May-2015 00:22:48 GMT; Max-Age=31449600; Path=/, sessionid=kdr061v1pcsbqtvgsn3pyyqj9237z6k8; expires=Thu, 22-May-2014 00:22:48 GMT; httponly; Max-Age=1209600; Path=/, messages="4f919699a4730a3df220a0eb3799ed59d2756825$[[\"__json_message\"\0540\05425\054\"Successfully signed in as philbot.\"]]"; Path=/
User-Is-Authenticated: True
Vary: Cookie,Accept-Encoding
Hai provato a farlo nel browser? Il problema si ripresenta se chiami URL dal browser? I cookie sono abilitati nell'SDK di iOS? –
Non penso che tu possa usare @login_required. La prossima volta che chiami una vista django, django non sa chi è l'utente, perché il sdk non passerà le informazioni sui cookie. L'uscita è per passare il token per ogni chiamata effettuata alla vista e accedere all'utente utilizzando un decoratore personalizzato. Tieni presente che non è la migliore strada da seguire. –
Non ho molte informazioni su 'allauth'. Tuttavia, so che Django 'login_required' farà qualcosa come' if request.user.is_authorized() == True'. Non vedo nulla cambia lo stato di autorizzazione dell'utente, a meno che Allauth lo stia facendo per te. Quindi quello che sto suggerendo è di cambiare lo stato del tuo utente 'django.auth' e rendere is_authorized = True. Assicurati che il 'Session' sia creato in modo che quando l'utente si sposta su un'altra vista Django possa controllare lo stato di autenticazione dell'utente. Lasciaci cosa vedere dopo questo processo, così possiamo aiutarti. – Othman