我正在使用Facebook iOS SDK将Facebook访问令牌POST到我的Django服务器URI。相应的views.py函数如下所示,当我从iOS进行POST时,我会得到200个响应代码。但是,在此之后,我立即从iOS设备调用第二个@login_required修饰的URI,它认为我未登录并重定向到主页。我做错了什么?在iOS成功POST后,如何保持已登录状态?
# 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
======= 更新 ==========
好的,谢谢您的评论。所以现在我也将Facebook电子邮件地址作为POST并手动获取用户并登录。然而,后续请求仍未经过身份验证。因此,@login_required装饰器仍然失败了...还有其他想法吗?
# 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
==== 另一个更新 ==========
根据这篇文章中的第二个答案: django authentication without a password
我创建了一个自定义的登录后端,不需要密码。该文章中的第三个答案讨论了如何实现这一点:
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
不在会话中存储登录验证信息,因此我尝试使用自定义后端。
这是我修改过的代码:
# 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
我使用hurl.it得到了HTTP 200响应,但仍然无法在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
allauth
没有太多的信息。然而,我知道Django的login_required
会执行类似于if request.user.is_authorized()==True
的操作。除非是allauth
在为您执行此操作,否则我没有看到任何更改用户授权状态的内容。因此,我的建议是更改您的django.auth
用户的状态,并使其is_authorized = True
。确保创建了Session
,以便当用户移动到另一个视图时,Django可以检查用户的身份验证状态。让我们看看在此过程之后发生了什么,这样我们就可以帮助您。 - Othman