image-20260111010029081


对接实例 - GitHub

准备阶段:

  1. 去GitHub申请注册应用,获取client_id、secret等信息。

  2. 在项目中配置相关的配置:

    github的client_id等,作为环境变量引入项目。

完整的链路:

  1. 前端请求后端获取 GitHub 授权页面 URL

  2. 后端生成包含 client_id、scope、state 的授权 URL

  3. 前端跳转到 GitHub 授权页面

  4. 用户同意授权后,GitHub 重定向回前端(URL 中带 code)

  5. 前端将 code 发送给后端

  6. 后端用 code 向 GitHub 换取 access_token,再用 access_token 获取 GitHub 用户信息

  7. 后端创建或关联本地用户,生成 JWT Token,返回给前端用于后续认证

参考代码:

  • 生成授权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)}"
  • 换取 Access Token

    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()
        data = response.json()
        return data.get('access_token')
  • 获取用户信息

    def get_github_user_info(self, access_token: str) -> Dict:
        """获取 GitHub 用户信息"""
        headers = {
            'Authorization': f'Bearer {access_token}',
            'Accept': 'application/json'
        }
     
        # 获取基本信息
        response = requests.get(self.USER_API_URL, headers=headers)
        user_data = response.json()
     
        # 如果没有公开邮箱,获取邮箱列表
        if not user_data.get('email'):
            emails_response = requests.get(self.USER_EMAILS_URL, headers=headers)
            if emails_response.ok:
                emails = emails_response.json()
                for email_data in emails:
                    if email_data.get('primary') and email_data.get('verified'):
                        user_data['email'] = email_data['email']
                        break
     
        return user_data