一、应用登记
https://github.com/settings/applications/new
登记完成后,获取两个参数
客户端 ID(client ID)
客户端密钥(client secret)
二、GitHub登录授权
1、网站让用户跳转到 GitHub。
GET https://github.com/login/oauth/authorize? client_id=7e015d8ce32370079895& redirect_uri=http://localhost:8080/oauth/redirect
两个参数:
client_id告诉 GitHub 谁在请求
redirect_uri是稍后跳转回来的网址
2、 GitHub 用户登录授权,重定向回网站,同时返回【授权码code】。
GET http://localhost:8080/oauth/redirect? code=859310e7cecc9196f4af
3、 网站后台使用授权码,向 GitHub 请求【令牌】, 需要加json请求头
POST https://github.com/login/oauth/access_token Accept: application/json 参数: client_id:客户端的 ID client_secret:客户端的密钥 code:授权码
三、请求数据
网站使用令牌,向 GitHub 请求用户数据。
GET https://api.github.com/user Authorization: Bearer {access_token} Accept: application/jso
代码实现
依赖requirements.txt
requests flask environs mo-cache
run.py
# -*- coding: utf-8 -*- from urllib.parse import urljoin from flask import Flask, request, url_for from github_api import get_github_auth_url, user, get_access_token from mo_cache import FileCache from environs import Env # 注册应用获取的参数 env = Env() env.read_env() clientID = env.str('clientID') clientSecret = env.str('clientSecret') # 使用文件缓存 access_token cache = FileCache() ACCESS_TOKEN_KEY = 'access_token_key' app = Flask(__name__) def full_url_for(endpoint, **values): """获取完整路径""" return urljoin(request.host_url, url_for(endpoint, **values)) @app.route('/') def hello_world(): """首页暴露接口地址""" return { 'auth_url': full_url_for('get_auth_url'), 'get_user': full_url_for('get_user') } @app.route('/auth_url') def get_auth_url(): """获取由后端拼接的Github第三方登录授权地址""" redirect_uri = full_url_for('oauth_redirect') auth_url = get_github_auth_url(client_id=clientID, redirect_uri=redirect_uri) return {'auth_url': auth_url} @app.route('/oauth/redirect') def oauth_redirect(): """github验证回调地址,从请求参数中获取code""" code = request.args.get('code') # 拿到code后继续请求获取access_token res = get_access_token(client_id=clientID, client_secret=clientSecret, code=code) # 存储用户的access_token access_token = res.get('access_token') cache.set(ACCESS_TOKEN_KEY, access_token) return res @app.route('/user') def get_user(): """通过access_token 获取用户信息""" # 从缓存中取出 access_token = cache.get(ACCESS_TOKEN_KEY) res = user(access_token=access_token) return res if __name__ == '__main__': print(app.url_map) # 服务地址需要和应用配置一致 app.run(port=8080, debug=True)
github_apipy
# -*- coding: utf-8 -*- import requests def get_github_auth_url(client_id, redirect_uri): """ :param client_id: 告诉 GitHub 谁在请求 :param redirect_uri: 跳转回来的网址 :return: """ authorize_uri = 'https://github.com/login/oauth/authorize' return f'{authorize_uri}?client_id={client_id}&redirect_uri={redirect_uri}' def get_access_token(client_id, client_secret, code): """获取 access_token 此操作在后台完成""" url = 'https://github.com/login/oauth/access_token' params = { 'client_id': client_id, 'client_secret': client_secret, 'code': code } headers = { 'accept': 'application/json' } res = requests.post(url=url, params=params, headers=headers) return res.json() def user(access_token): """获取用户信息""" url = 'https://api.github.com/user' headers = { 'Authorization': f'Bearer {access_token}' } res = requests.get(url=url, headers=headers) return res.json()