Django-rest-auth文档讨论了Facebook集成,但我对此不感兴趣——我的关注点是提供通过Google进行社交登录。我已经尝试了一段时间,想知道是否有其他人有关于如何做到这一点的文档...即使只是一个大致的草图也会很有帮助。到目前为止,我没有在这个搜索中找到任何结果。我已经接近成功,但无法与Django rest framework(DRF)可浏览API配合使用。
到目前为止,我所做的是: 我从django-rest-auth github页面提供的演示项目开始,并修改了社交登录模板HTML页面,只要求输入“code”,而不是“code”和“access_token”两者都要。当我提供一个有效的代码(通过单独请求谷歌的认证端点获得)时,这个方法可以正常工作;可浏览API呈现出通常的网页,并在响应中返回“key”(我的应用程序对用户的API令牌)。检查Django管理界面,一切都正常——用户已登录,电子邮件已经过身份验证等等。 到目前为止很好。
问题在于提供“code”的起点以及我如何首先从谷歌获取该代码。当我之前(成功地)使用allauth包时,我只需要点击一个链接,就可以“隐形地”执行整个OAuth2流程(即请求代码,使用该代码获取访问令牌,并使用访问令牌获取用户的Google账户信息)。
为了重新创建那个无缝的流程(即不从代码开始),我想我可以打断OAuth2流程并“拦截”从谷歌返回的代码,然后将该代码POST到rest-auth社交登录API。为此,我通过覆盖dispatch方法创建了一个自定义的allauth.socialaccount.providers.oauth2.views.OAuth2CallbackView:
到目前为止,我所做的是: 我从django-rest-auth github页面提供的演示项目开始,并修改了社交登录模板HTML页面,只要求输入“code”,而不是“code”和“access_token”两者都要。当我提供一个有效的代码(通过单独请求谷歌的认证端点获得)时,这个方法可以正常工作;可浏览API呈现出通常的网页,并在响应中返回“key”(我的应用程序对用户的API令牌)。检查Django管理界面,一切都正常——用户已登录,电子邮件已经过身份验证等等。 到目前为止很好。
问题在于提供“code”的起点以及我如何首先从谷歌获取该代码。当我之前(成功地)使用allauth包时,我只需要点击一个链接,就可以“隐形地”执行整个OAuth2流程(即请求代码,使用该代码获取访问令牌,并使用访问令牌获取用户的Google账户信息)。
为了重新创建那个无缝的流程(即不从代码开始),我想我可以打断OAuth2流程并“拦截”从谷歌返回的代码,然后将该代码POST到rest-auth社交登录API。为此,我通过覆盖dispatch方法创建了一个自定义的allauth.socialaccount.providers.oauth2.views.OAuth2CallbackView:
class CustomOAuth2CallbackView(OAuth2CallbackView):
def dispatch(self, request):
# gets the code correctly:
code = request.GET['code']
# rp is of type requests.methods.Response
rp = requests.post(<REST-AUTH API ENDPOINT>, data = {'code':code})
return rp
通常情况下,当谷歌向您最初提供给谷歌的验证终点发送GET请求时,将调用此方法。使用此覆盖,我能够成功解析从谷歌返回的代码。POST请求有效,并在resp._content字段中具有用户密钥。但是,它最终无法在DRF浏览API中产生预期的视图。
通过深入调用栈,我发现rest_framework.views.APIView.dispatch返回rest_framework.response.Response类型的对象。 但是,当上面使用requests.post方法完成时,它返回requests.models.Response实例。因此,它没有正确的属性并在django中间件中失败。例如,它没有acceptable_renderer属性和get方法(用于django.middleware.clickjacking.py)。我可以想象将这些要求添加到requests.models.Response(rp)实例中,但那么这个hack将变得更加笨拙。
感谢您能提供的任何帮助!