Py学习  »  Django

重新实现社会登录(在Django)

Dan Gittik • 4 年前 • 377 次点击  

tl;dr:可以不存储(google/facebook)oauth2访问令牌,而是在每次登录时请求新的令牌吗?

我会解释:

要向django应用程序添加社交登录(“使用google/facebook登录”),您需要 Python Social Auth . 它的问题是,至少对我来说,它比我想要的要复杂得多,需要很多配置,在数据库中创建额外的表,而且总的来说,对于一个相当简单的任务来说,感觉像是很多我不理解的移动部件。

所以,我读了一些关于 Google's Facebook's 流程非常简单:

  • 服务器有一个 身份证件 和A 秘密 .
  • 客户端/用户具有其标准登录凭据。

然后:

  1. 服务器将用户重定向到google/facebook,并提供 身份证件 和A 重定向uri .
  2. 用户登录后,google/facebook会使用 代码 .
  3. 服务器发送 身份证件 , 秘密 ,并且 代码 去google/facebook,然后 访问令牌 在exchange中,它现在可以使用它来代表用户进行api调用。
  4. 即使最基本的权限也足以查询google/facebook上用户的电子邮件,然后可以与django的标准用户模型进行匹配(如果不存在,则可以创建一个无密码用户)。

访问令牌现在可以被丢弃,因为只需要将google/facebook登录转换为一个实际的电子邮件(由他们验证),它被用作 只有 用户标识符-当通过不同的社会服务登录时,不再由于不同的帐户而产生混淆;没有额外的表;没有不必要的复杂性。

下面是代码,只是为了说明需要的东西有多少:

# views.py

def login_view(request):
    return render(request, 'login.html', {
        'google_url': 'https://accounts.google.com/o/oauth2/v2/auth?' + urllib.parse.urlencode({
            'client_id': GOOGLE_ID,
            'redirect_uri': request.build_absolute_uri(reverse('oauth_google')),
            'scope': 'profile email',
            'response_type': 'code',
        }),
    }) # use this url in the template as a social login

def oauth_google(request):
    code = request.GET['code']
    response = requests.post('https://www.googleapis.com/oauth2/v4/token', {
        'code': code,
        'client_id': GOOGLE_ID,
        'client_secret': GOOGLE_SECRET,
        'redirect_uri': request.build_absolute_uri(reverse('oauth_google')),
        'grant_type': 'authorization_code',
    }).json()
    id_token = response['id_token']
    response = requests.get('https://www.googleapis.com/oauth2/v3/tokeninfo', {
        'id_token': id_token,
    }).json()
    email = response['email']
    user = User.objects.filter(username=email).first()
    if not user:
        user = User(username=email)
        user.save()
    auth.login(request, user)
    return redirect('index')

# urls.py

urlpatterns = [
    ...
    path('oauth/google', views.oauth_google, name='oauth_google'),
]

我的问题是:我错过了什么?如果真的那么简单,为什么我在stackoverflow/tutorials上找不到任何关于这个的答案呢?

我能想到的唯一原因是访问令牌有一个过期时间(1小时到60天之间的任何地方);因此,也许我应该继续重用同一个访问令牌,只要它是有效的(这将需要存储它,并解释为什么python social auth需要额外的表)google/facebook会因为我请求新的访问令牌太频繁而对我发火吗?我在他们的文件里找不到任何关于这个的内容。

编辑

以下是Facebook代码,以防有人发现这些代码片段有用:

# views.py

def login_view(request):
    return render(request, 'login.html', {
        'facebook_url': 'https://www.facebook.com/v3.2/dialog/oauth?' + urllib.parse.urlencode({
            'client_id': FACEBOOK_ID,
            'redirect_uri': request.build_absolute_uri(reverse('oauth_facebook')),
            'scope': 'email',
        }),
    }) # use this url in the template as a social login

def oauth_facebook(request):
    code = request.GET['code']
    response = requests.get('https://graph.facebook.com/v3.2/oauth/access_token', {
        'code': code,
        'client_id': FACEBOOK_ID,
        'client_secret': FACEBOOK_SECRET,
        'redirect_uri': request.build_absolute_uri(reverse('oauth_facebook')),
    }).json()
    access_token = response['access_token']
    response = requests.get('https://graph.facebook.com/me', {
        'access_token': access_token,
        'fields': 'email',
    }).json()
    email = response['email']
    user = User.objects.filter(username=email).first()
    if not user:
        user = User(username=email)
        user.save()
    auth.login(request, user)
    return redirect('index')

# urls.py

urlpatterns = [
    ...
    path('oauth/facebook', views.oauth_facebook, name='oauth_facebook'),
]
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/40737
 
377 次点击