tl;dr:可以不存储(google/facebook)oauth2访问令牌,而是在每次登录时请求新的令牌吗?
我会解释:
要向django应用程序添加社交登录(“使用google/facebook登录”),您需要
Python Social Auth
. 它的问题是,至少对我来说,它比我想要的要复杂得多,需要很多配置,在数据库中创建额外的表,而且总的来说,对于一个相当简单的任务来说,感觉像是很多我不理解的移动部件。
所以,我读了一些关于
Google's
和
Facebook's
流程非常简单:
-
服务器有一个
身份证件
和A
秘密
.
-
客户端/用户具有其标准登录凭据。
然后:
-
服务器将用户重定向到google/facebook,并提供
身份证件
和A
重定向uri
.
-
用户登录后,google/facebook会使用
代码
.
-
服务器发送
身份证件
,
秘密
,并且
代码
去google/facebook,然后
访问令牌
在exchange中,它现在可以使用它来代表用户进行api调用。
-
即使最基本的权限也足以查询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'),
]