Django 如何正确接入 GitHub OAuth
?
项目地址: https://github.com/hsowan/CSDNBot/tree/web
首先, 创建 GitHub OAuth Apps
{% img /images/new-github-oauth-app.png %}
其中值得注意的有:
Authorization callback URL
(认证后的回调地址), 比如: http://localhost:8000/api/login/oauth/code/github/, 在认证之后将跳转到这个地址并带上一个code
参数, 这个参数会用来请求access_token
Client ID
和Client Secret
也是用户请求access_token
的参数
然后, 在 Django
项目中添加路由
from django.urls import re_path
from . import apis
urlpatterns = [
re_path(r'^api/login/oauth/code/github/?$', apis.github_oauth_callback),
]
实现 github_oauth_callback:
import requests
from django.conf import settings
import json
from django.shortcuts import redirect
# https://github.com/login/oauth/authorize?client_id=bd4692513cb71ba05c22&scope=user
def github_oauth_callback(request):
code = request.GET.get('code', '')
# 没有 code 参数时的处理
if code == '':
return redirect('/')
data = {
'client_id': settings.GITHUB_CLIENT_ID,
'client_secret': settings.GITHUB_CLIENT_SECRET,
'code': code
}
github_api_base_url = 'https://api.github.com'
get_access_token_url = 'https://github.com/login/oauth/access_token'
r = requests.post(get_access_token_url, data)
content = r.content.decode('utf-8')
if r.status_code == 200:
# content: access_token=e72e16c7e42f292c6912e7710c838347ae178b4a&token_type=bearer
access_token = content.split('&')[0].split('=')[1]
headers = {
'Authorization': 'token ' + access_token,
}
# Get user
get_user_url = github_api_base_url + '/user'
get_user_res = requests.get(get_user_url, headers=headers)
content = get_user_res.content.decode('utf-8')
if get_user_res.status_code == 200:
# Refer: https://developer.github.com/v3/users/#get-a-single-user
github_user = json.loads(content)
# 省略持久化的操作
else:
print('GitHub 登录失败: ' + str(get_user_res.status_code) + ', ' + content)
return redirect('/')
else:
print('GitHub 登录失败: ' + str(r.status_code) + ', ' + content)
return redirect('/')
# 将用户信息保存到session
request.session['github_id'] = github_id
return redirect('/')
现在就可以访问 https://github.com/login/oauth/authorize?client_id=your_client_id&scope=user 实现 GitHub
登录,
其中需要 client_id
和 scope
两个参数, scope
表示认证后请求到的 access_token
可以使用哪些 API, 具体参考 Understanding scopes for OAuth Apps