本文基于
实现了使用 refreshToken 自动刷新 accessToken 一劳永逸地来使用 api.oaifree.com 的 chat2api接口。
在复用之前文章中的kv变量”at”和“rt”的基础上,新增 “auth_key” 用来作为 api_key 的验证。
用通俗的话来说就是,在使用 chat2api 接口的时候,api_key不必设置为 accessToken, 而是设置为你在kv里面自定义 “auth_key” 的值即可。 CF worker 验证了key符合之后,会用kv中存储的”at”去最终调用chat2api接口, “at”过期的话也会实时用 ”rt” 去刷新 “at”.
worker代码:
20240502 删除了重复代码,并修改了一处bug
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
function parseJwt(token) {
const base64Url = token.split('.')[1]; // 获取载荷部分
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); // 将 Base64Url 转为 Base64
const jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload); // 返回载荷解析后的 JSON 对象
}
function isTokenExpired(token) {
const payload = parseJwt(token);
const currentTime = Math.floor(Date.now() / 1000); // 获取当前时间戳(秒)
return payload.exp < currentTime; // 检查 token 是否过期
}
async function handleRequest(request) {
// 1. 目标反代 URL
const url = new URL(request.url);
url.host = 'api.oaifree.com';
// 2. 获取 Authorization header
const authHeader = request.headers.get('Authorization');
const apikey = authHeader ? authHeader.split(' ')[1] : null;
// 3. 检查 token
const auth_key = await oai_global_variables.get('auth_key')
if (!apikey || apikey !== auth_key) {
// 4. Token 验证失败
return new Response('Unauthorized', { status: 401 });
}
// ------------ get at
let token = await oai_global_variables.get('at'); // 这里填入你的 JWT
if (isTokenExpired(token)) {
// 如果 Token 过期,执行获取新 Token 的逻辑
const url = 'https://token.oaifree.com/api/auth/refresh';
// @ts-ignore
const refreshToken = await oai_global_variables.get('rt'); // 实际情况下你可能会从某处获取这个值
// 发送 POST 请求
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body: `refresh_token=${refreshToken}`
});
// 检查响应状态
if (response.ok) {
const data = await response.json();
token = data.access_token;
// @ts-ignore
await oai_global_variables.put('at', token);
} else {
return response
}
}
// 如果 Token 未过期,继续执行原来的逻
// 5. 替换 token 并转发请求
const modifiedHeaders = new Headers(request.headers);
modifiedHeaders.set('Authorization', 'Bearer '+token);
// 创建新的请求对象以转发
const newRequest = new Request(url, {
method: request.method,
headers: modifiedHeaders,
body: request.body
});
// 发送新的请求到目标 API
const response = await fetch(newRequest);
return response;
}