
对接实例:GitHub
准备工作
- 在 GitHub 注册 OAuth 应用,获取
client_id和client_secret。 - 在项目环境变量中配置凭据和回调地址;不要把真实密钥提交到代码仓库。
授权流程
- 前端向后端请求 GitHub 授权 URL。
- 后端生成包含
client_id、scope、state和redirect_uri的授权 URL。 - 浏览器跳转到 GitHub 授权页面。
- 用户同意后,GitHub 重定向到回调地址并附带
code和原始state。 - 后端校验
state,再用code向 GitHub 兑换访问令牌。 - 后端使用访问令牌获取 GitHub 用户信息,并创建或关联本地用户。
- 后端为本系统生成自己的会话或访问令牌;GitHub 的访问令牌不应直接当成本系统的登录凭据。
生成授权 URL
def get_authorization_url(self, state: str) -> str:
"""生成 GitHub 授权 URL。"""
params = {
"client_id": self.client_id,
"redirect_uri": self.redirect_uri,
"scope": "user:email",
"state": state,
}
return f"{self.AUTHORIZE_URL}?{urlencode(params)}"
用授权码兑换访问令牌
def exchange_code_for_token(self, code: str) -> str:
"""用授权码换取 access_token。"""
response = requests.post(
self.TOKEN_URL,
data={
"client_id": self.client_id,
"client_secret": self.client_secret,
"code": code,
"redirect_uri": self.redirect_uri,
},
headers={"Accept": "application/json"},
timeout=10,
)
response.raise_for_status()
return response.json()["access_token"]
获取用户信息
def get_github_user_info(self, access_token: str) -> dict:
headers = {
"Authorization": f"Bearer {access_token}",
"Accept": "application/json",
}
response = requests.get(self.USER_API_URL, headers=headers, timeout=10)
response.raise_for_status()
user_data = response.json()
# 若公开资料没有邮箱,再从邮箱接口中选择已验证的主邮箱。
if not user_data.get("email"):
emails_response = requests.get(
self.USER_EMAILS_URL, headers=headers, timeout=10
)
emails_response.raise_for_status()
for email_data in emails_response.json():
if email_data.get("primary") and email_data.get("verified"):
user_data["email"] = email_data["email"]
break
return user_data
实现时还应使用短期、一次性的 state 防止 CSRF,校验回调地址,并通过安全的环境变量或密钥管理服务保存 client_secret。
Yoleo
正在构建