• 首页

  • 写作

  • 文章归档

  • 照片

  • 友情链接

  • 旅行

  • 读书

  • 日志

  • 随记

  • 人文历史

  • linux

  • 前端
b l o g
b l o g

admin

lzp

03月
24
cloudflare

cloudflare-memoflow 添加 github app auth 登录

发表于 2025-03-24 • 字数统计 7426 • 被 6 人看爆

##2025/3/24 15:16:34:

cloudflare-memoflow 添加 github app auth 登录

github commit:

add github app auth
https://github.com/qyzhizi/hono-auth-test-app-D1-func/commit/18c2c22cc144463f3c8cae04569a92d1b88f732f
update GitHub 授权回调路由
https://github.com/qyzhizi/hono-auth-test-app-D1-func/commit/271a4a47c5078c75b3de9213637887821ca0bd0d
这两个提交,实现了 浏览器中输入 https://github.com/login/oauth/authorize?client_id=Iv23lifuoku8yVW9MtLh 就可以返回 accesstoken 的信息,其中 client_id=Iv23lifuoku8yVW9MtLh 是 github app 的信息,这样其实是写死了,应该从环境变量中获取 这个client_id 信息,然后再动态发送这个GET请求。
这里是参考了 Memoflow 的相关函数,让 AI 以 cloudflare hono 的方式重构 ,没有使用第三方库,而是直接发送 url 请求,相对来说更简单方便。

add button login with github
https://github.com/qyzhizi/hono-auth-test-app-D1-func/commit/cab6225bc674020029960f56ff5ff53900df3c59
add github auth redirect
https://github.com/qyzhizi/hono-auth-test-app-D1-func/commit/16a78478ee8294e9c4a5a9721a1af0b60302dc20
这两个提交是添加了一个按钮,可以进行 github app auth 认证。实现了上面的要求,即从环境变量中获取 这个client_id 信息,然后再动态发送这个GET请求

类型定义文件

另外填加了 env.d.ts 这个文件,这个文件是一个类型定义文件,可以这样使用:

// 定义处理函数
export const githubAuthHandler = (c: Context<{ Bindings: CloudflareEnv }>) => {
  // 从环境变量中获取 GitHub Client ID
  const clientId = c.env.GITHUB_APP_CLIENT_ID
  const githubAuthUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}`
  return c.redirect(githubAuthUrl)
}

其中 CloudflareEnv 是 env.d.ts 这个文件 定义的类型:

// Generated by Wrangler by running `wrangler types --env-interface CloudflareEnv env.d.ts`

interface CloudflareEnv {
	GITHUB_APP_CLIENT_ID: "Iv23lifuoku8yVW9MtLh";
	GITHUB_APP_CLIENT_SECRETS: "2a4e48523ee020f1d1a47ae13fca31f72cdd4800";
	ACCESS_TOKEN_SECRET: string;
	REFRESH_TOKEN_SECRET: string;
	ACCESS_TOKEN_EXPIRY: string;
	REFRESH_TOKEN_EXPIRY: string;
	GITHUB_ID: string;
	GITHUB_SECRET: string;
	DB: D1Database;
}

GitHub app 注册

填写的 callback
https://hono-auth-test-app-d1-func.pages.dev/api/github-app-auth-callbackuu
Repository permissions 3 selected

  • Codespaces
  • Commit statuses
  • Contents

Account permissions 1 selected

  • Email addresses read only

AI 协助 函数的重构与解耦

first example:

def get_access_token(self, code):

        CLIENT_SECRET = CONF.diary_log['CLIENT_SECRET']
        CLIENT_ID = CONF.diary_log['CLIENT_ID']
        # 回调 URL,需与 GitHub App 中设置的一致
        # REDIRECT_URI = '/v1/diary-log/github-authenticate-callback'

        # 使用 code 获取访问令牌
        token_url = 'https://github.com/login/oauth/access_token'
        payload = {
            'client_id': CLIENT_ID,
            'client_secret': CLIENT_SECRET,
            'code': code,
            # 'redirect_uri': REDIRECT_URI
        }
        headers = {'Accept': 'application/json'}

        # 创建 POST 请求对象
        request = Request.blank(token_url, method='POST',
                                POST=payload, headers=headers)
        try:
            # 发送请求
            response = request.get_response()
        except Exception as e:
            LOG.error(e)
            raise e

        # 解析响应内容
        if response.status_code == 200:
            # print(response.json())
            data = json.loads(response.text)
            # access_token = data.get('access_token', None)
            # if not access_token:
            #     # return 'Failed to retrieve access token'
            #     LOG.error('Failed to retrieve access token')
            return data
        else:
            return None

改写为 在 cloudflare hono 框架下的函数
下面给出一个使用 Cloudflare Workers 上的 Hono 框架实现的等效函数示例。假设你已经在 Workers 的环境绑定(例如 secrets 或 environment variables)中配置了 CLIENT_ID 和 CLIENT_SECRET,代码示例如下:

import { Context } from 'hono'

// 该函数处理 GitHub OAuth 回调,获取访问令牌
export async function getAccessToken(c: Context): Promise<Response> {
  // 从查询参数中获取 code
  const code = c.req.query('code')
  if (!code) {
    return c.text('Missing code', 400)
  }

  // 从环境变量中获取 GitHub 应用的 Client ID 与 Client Secret
  const CLIENT_ID = c.env.CLIENT_ID
  const CLIENT_SECRET = c.env.CLIENT_SECRET

  const tokenUrl = 'https://github.com/login/oauth/access_token'

  // 构造表单数据(application/x-www-form-urlencoded)
  const params = new URLSearchParams()
  params.append('client_id', CLIENT_ID)
  params.append('client_secret', CLIENT_SECRET)
  params.append('code', code)
  // 如果需要,也可以加入 redirect_uri 参数
  // params.append('redirect_uri', 'your_redirect_uri')

  try {
    // 发送 POST 请求获取访问令牌
    const res = await fetch(tokenUrl, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: params.toString()
    })

    if (!res.ok) {
      const errorMsg = await res.text()
      console.error('Error fetching token:', errorMsg)
      return c.json({ error: 'Failed to retrieve access token' }, res.status)
    }

    const data = await res.json()
    return c.json(data)
  } catch (error) {
    console.error('Fetch error:', error)
    return c.json({ error: 'Internal Server Error' }, 500)
  }
}

@@@ 说明

  • 获取参数与环境变量:函数首先从查询字符串中读取 code,并从环境变量中获取 CLIENT_ID 和 CLIENT_SECRET。在 Cloudflare Workers 中,这通常通过绑定(Bindings)实现。
  • 构造请求:使用 URLSearchParams 构造表单数据,并设置请求头为 application/x-www-form-urlencoded 以及 Accept: application/json(保证 GitHub 返回 JSON 格式的数据)。
  • 错误处理:利用 try-catch 捕获请求异常,并在请求失败时返回相应的错误信息。
  • 返回结果:请求成功后,解析 JSON 数据并返回。

将该函数添加到 Hono 应用中,比如:

import { Hono } from 'hono'
import { getAccessToken } from './your_module'

const app = new Hono()

// 设置回调路由,用户在 GitHub 授权后会跳转到此路由
app.get('/github-authenticate-callback', getAccessToken)

export default app

这样就完成了将原来的 Python 代码改写为 Cloudflare Hono 框架下的实现。

将原有的js 的 getAccessToken函数解耦,分为 响应路由 /github-authenticate-callback 的 handler 与获取 AccessToken 的 函数
下面给出一个将获取 AccessToken 的逻辑与响应路由处理解耦后的示例。示例中,我们将与 GitHub 通信获取 access token 的逻辑封装在一个独立的函数 fetchAccessToken 中,然后在路由处理函数 githubAuthCallbackHandler 中调用该函数。

@@@ tokenService.ts

// tokenService.ts
/**
 * 该函数用于与 GitHub 交互,使用 code 获取 access token
 * @param clientId GitHub App 的 Client ID
 * @param clientSecret GitHub App 的 Client Secret
 * @param code 授权回调中传回的 code
 * @returns 返回解析后的 token 数据
 */
export async function fetchAccessToken(clientId: string, clientSecret: string, code: string): Promise<any> {
  const tokenUrl = 'https://github.com/login/oauth/access_token'
  const params = new URLSearchParams()
  params.append('client_id', clientId)
  params.append('client_secret', clientSecret)
  params.append('code', code)
  // 如果需要,加入 redirect_uri 参数
  // params.append('redirect_uri', 'your_redirect_uri')

  const res = await fetch(tokenUrl, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: params.toString()
  })

  if (!res.ok) {
    const errorMsg = await res.text()
    throw new Error(`获取 access token 失败:${errorMsg}`)
  }

  return res.json()
}

@@@ handler.ts

// handler.ts
import { Context } from 'hono'
import { fetchAccessToken } from './tokenService'

/**
 * GitHub 授权回调路由处理函数
 * 该函数从请求中提取 code,然后调用 fetchAccessToken 获取 token,并返回 JSON 响应
 */
export async function githubAuthCallbackHandler(c: Context): Promise<Response> {
  // 从查询参数中获取 code
  const code = c.req.query('code')
  if (!code) {
    return c.text('缺少 code 参数', 400)
  }

  // 从环境变量中读取 Client ID 与 Client Secret(需要在 Workers 中绑定)
  const CLIENT_ID = c.env.CLIENT_ID
  const CLIENT_SECRET = c.env.CLIENT_SECRET

  try {
    const tokenData = await fetchAccessToken(CLIENT_ID, CLIENT_SECRET, code)
    return c.json(tokenData)
  } catch (error) {
    console.error('获取 access token 过程中出错:', error)
    return c.json({ error: '获取 access token 失败' }, 500)
  }
}

@@@ app.ts

// app.ts
import { Hono } from 'hono'
import { githubAuthCallbackHandler } from './handler'

const app = new Hono()

// 注册 GitHub 授权回调路由
app.get('/github-authenticate-callback', githubAuthCallbackHandler)

export default app

@@@ 说明

  • 解耦设计:fetchAccessToken 专注于与 GitHub 通信获取 token,而 githubAuthCallbackHandler 负责处理路由请求、参数校验与错误处理。
  • 环境变量:在 Cloudflare Workers 中,可以通过绑定的方式传入 CLIENT_ID 和 CLIENT_SECRET。
  • 错误处理:当请求参数缺失或获取 token 失败时,分别返回相应的错误提示。

这样就实现了将原有的 getAccessToken 函数解耦,分别为响应路由处理和获取 AccessToken 的逻辑。

second example:

app.get('/github/auth', (c) => {
  // 从环境变量中获取 GitHub Client ID
  const clientId = c.env.GITHUB_CLIENT_ID
  const githubAuthUrl = https://github.com/login/oauth/authorize?client_id=${clientId}
  return c.redirect(githubAuthUrl)
})

解耦为路由注册 与 handler

下面是将路由注册与处理函数解耦的示例代码:

import { Hono } from 'hono'
import type { Context } from 'hono'

interface Env {
  GITHUB_CLIENT_ID: string;
}

// 定义处理函数
const githubAuthHandler = (c: Context<{ Bindings: Env }>) => {
  // 从环境变量中获取 GitHub Client ID
  const clientId = c.env.GITHUB_CLIENT_ID
  const githubAuthUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}`
  return c.redirect(githubAuthUrl)
}

// 注册路由
const app = new Hono()
app.get('/github/auth', githubAuthHandler)

export default app

@@@ 说明

  • 处理函数解耦: 将 GitHub 授权重定向逻辑封装在 githubAuthHandler 函数中,路由注册时直接引用该处理函数。
  • 环境变量绑定: 使用 TypeScript 的接口 Env 指定环境变量类型,确保在 Cloudflare Workers 部署时能正确获取 GITHUB_CLIENT_ID。
分享到:
cloudflare memoflow 更新数据库表,将gitthub app auth 数据存入数据库
cloudflare pages 实现 hono jsx dom github 登录认证
  • 文章目录
  • 站点概览
admin

! lzp

hello

Github Twitter QQ Email Telegram RSS
看爆 Top5
  • 历史与人文 视频链接 189次看爆
  • 2022日志随笔 175次看爆
  • 我的青海湖骑行 164次看爆
  • 读书随笔 124次看爆
  • rs2 设置教程 97次看爆

站点已萌萌哒运行 00 天 00 小时 00 分 00 秒(●'◡'●)ノ♥

Copyright © 2025 admin

由 Halo 强力驱动 · Theme by Sagiri · 站点地图