support refresh token fetch for access token

This commit is contained in:
Pikachu Ren 2025-06-16 00:48:18 +08:00
parent 02e1ffb9c1
commit 0e1fbaf859
12 changed files with 272 additions and 17 deletions

View File

@ -62,6 +62,10 @@
<button class="btn btn-primary" onclick="getLogin()">获取 Token</button>
</div>
<div class="d-grid gap-2 mb-3">
<button class="btn btn-primary" onclick="getLogin(true)">刷新 Token</button>
</div>
<div class="mb-3">
<label for="access-token" class="form-label">访问秘钥</label>
<textarea id="access-token" class="form-control" rows="3" readonly onclick="autoCopy(this)"></textarea>

View File

@ -1,14 +1,21 @@
// 获取登录秘钥 #######################################################
async function getLogin() {
async function getLogin(refresh = false) {
let server_use = document.getElementById("server_use").checked;
let secret_key = document.getElementById("secret-key").value;
let refresh_ui = document.getElementById("refresh-token").value;
let apps_uuid = document.getElementById("client-id").value;
let apps_keys = document.getElementById("app-secret").value;
let apps_type = document.getElementById("site-select").value;
let secret_key = document.getElementById("secret-key").value;
console.log(server_use);
// 阿里云盘扫码登录v2不需要验证客户端ID和应用机密
if (apps_type !== "alicloud_oa" && !server_use && (apps_uuid === "" || apps_keys === "")) {
Swal.fire({
// 验证秘钥情况 ==================================================
if (// 阿里云盘扫码登录v2不需要验证客户端ID和应用机密
(apps_type !== "alicloud_oa" && apps_type !== "baiduyun_go" &&
!server_use && (apps_uuid === "" || apps_keys === "")) ||
(apps_type === "baidunuy_go" && // 百度网盘不需ID
!server_use && (secret_key === "" || apps_keys === ""))
) {
await Swal.fire({
position: 'top',
icon: 'info',
title: '获取失败',
@ -22,11 +29,29 @@ async function getLogin() {
await startAlicloud2Login();
return;
}
// 刷新秘钥情况 =================================================
let base_urls = "/requests?client_uid="
if (refresh) {
if (!refresh_ui) {
Swal.fire({
position: 'top',
icon: 'info',
title: '刷新失败',
text: '请先填写Refresh Token',
showConfirmButton: true,
});
return;
}
base_urls = "/renewapi?client_uid="
}
let apps_subs = apps_type.split("_")[0]
let post_urls = "/" + apps_subs + "/requests?client_uid=" + apps_uuid
let post_urls = "/" + apps_subs + base_urls + apps_uuid
+ "&client_key=" + apps_keys + "&apps_types=" + apps_type
+ "&server_use=" + server_use
if (refresh) {
post_urls += "&refresh_ui=" + refresh_ui
}
if (apps_subs === "baiduyun") post_urls += "&secret_key=" + secret_key
try {
const response = await fetch(post_urls, {
@ -34,6 +59,29 @@ async function getLogin() {
});
// 解析响应内容 ===============================================
const response_data = await response.json();
// 刷新令牌模式 ===============================================
if (refresh) {
if (response.status === 200) {
access_key = document.getElementById("access-token")
access_key.value = response_data.access_token;
refresh_ui = document.getElementById("refresh-token")
refresh_ui.value = response_data.refresh_token;
Swal.fire({
icon: 'success',
title: '刷新令牌成功:',
showConfirmButton: true,
timer: 1000
});
} else Swal.fire({
icon: 'error',
title: '刷新令牌失败: ',
text: response_data.text,
showConfirmButton: true,
timer: 1000
});
return;
}
// 申请登录模式 ================================================================
if (response.status === 200) {
if (apps_subs === "onedrive" || apps_subs === "115cloud"
|| apps_subs === "baiduyun" || apps_subs === "googleui" || apps_subs === "yandex") {

View File

@ -1,11 +1,14 @@
import * as local from "hono/cookie";
import {Context} from "hono";
import {showErr} from "./error";
import * as configs from "./shares/configs";
import * as refresh from "./shares/refresh";
const driver_map: string[] = [
"https://passportapi.115.com/open/authorize",
"https://passportapi.115.com/open/authCodeToToken"
"https://passportapi.115.com/open/authCodeToToken",
"https://passportapi.115.com/open/refreshToken"
]
// 登录申请 ##############################################################################
@ -109,6 +112,17 @@ export async function oneToken(c: Context) {
}
}
// 登录申请 ##############################################################################
export async function genToken(c: Context) {
const refresh_text: string | undefined = c.req.query('refresh_ui');
if (!refresh_text) return c.json({text: "缺少刷新令牌"}, 500);
// 请求参数 ==========================================================================
const params: Record<string, any> = {
refresh_token: refresh_text
};
return await refresh.genToken(c, driver_map[2], params, "POST",
"data.access_token","data.refresh_token","error");
}
function getRandomString(length: number): string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

View File

@ -45,3 +45,8 @@ export async function oneLogin(c: Context) {
export async function oneToken(c: Context) {
return await oneLogin(c);
}
// 刷新令牌 ##############################################################################
export async function genToken(c: Context) {
return c.json({text: "此网盘不支持"}, 500);
}

View File

@ -1,5 +1,7 @@
import {Context} from "hono";
import * as local from "hono/cookie";
import * as configs from "./shares/configs";
import * as refresh from "./shares/refresh";
const driver_map = [
'https://openapi.aliyundrive.com/oauth/authorize/qrcode',
@ -111,3 +113,20 @@ export async function alyToken(c: Context) {
);
}
}
// 刷新令牌 ##############################################################################
export async function genToken(c: Context) {
const clients_info: configs.Clients | undefined = configs.getInfo(c);
const refresh_text: string | undefined = c.req.query('refresh_ui');
if (!clients_info) return c.json({text: "传入参数缺少"}, 500);
if (!refresh_text) return c.json({text: "缺少刷新令牌"}, 500);
// 请求参数 ==========================================================================
const params: Record<string, any> = {
client_id: clients_info.servers ? c.env.alicloud_uid : clients_info.app_uid,
client_secret: clients_info.servers ? c.env.alicloud_key : clients_info.app_key,
grant_type: 'refresh_token',
refresh_token: refresh_text
};
return await refresh.genToken(c, driver_map[1], params, "POST",
"access_token", "refresh_token", "message");
}

View File

@ -690,3 +690,8 @@ export async function logout(c: Context) {
return c.json({error: '退出登录失败'}, 500);
}
}
// 刷新令牌 ##############################################################################
export async function genToken(c: Context) {
return c.json({text: "此网盘不支持"}, 500);
}

View File

@ -1,11 +1,13 @@
import * as local from "hono/cookie";
import {Context} from "hono";
import {showErr} from "./error";
import * as refresh from "./shares/refresh"
import * as configs from "./shares/configs"
const driver_map: string[] = [
"https://openapi.baidu.com/oauth/2.0/authorize",
"https://openapi.baidu.com/oauth/2.0/token"
"https://openapi.baidu.com/oauth/2.0/token",
]
// 登录申请 ##############################################################################
@ -105,3 +107,19 @@ export async function oneToken(c: Context) {
}
}
// 刷新令牌 ##############################################################################
export async function genToken(c: Context) {
const clients_info: configs.Clients | undefined = configs.getInfo(c);
const refresh_text: string | undefined = c.req.query('refresh_ui');
if (!clients_info) return c.json({text: "传入参数缺少"}, 500);
if (!refresh_text) return c.json({text: "缺少刷新令牌"}, 500);
// 请求参数 ==========================================================================
const params: Record<string, any> = {
client_id: clients_info.servers ? c.env.baiduyun_key : clients_info.app_key,
client_secret: clients_info.servers ? c.env.baiduyun_ext : clients_info.secrets,
grant_type: 'refresh_token',
refresh_token: refresh_text
};
return await refresh.genToken(c, driver_map[1], params, "GET");
}

View File

@ -1,7 +1,8 @@
import * as local from "hono/cookie";
import {Context} from "hono";
import {showErr} from "./error";
import * as configs from "./shares/configs";
import * as refresh from "./shares/refresh";
const driver_map: string[] = [
"https://accounts.google.com/o/oauth2/v2/auth",
@ -117,3 +118,19 @@ function getRandomString(length: number): string {
}
return result;
}
// 刷新令牌 ##############################################################################
export async function genToken(c: Context) {
const clients_info: configs.Clients | undefined = configs.getInfo(c);
const refresh_text: string | undefined = c.req.query('refresh_ui');
if (!clients_info) return c.json({text: "传入参数缺少"}, 500);
if (!refresh_text) return c.json({text: "缺少刷新令牌"}, 500);
// 请求参数 ==========================================================================
const params: Record<string, any> = {
client_id: clients_info.servers ? c.env.googleui_uid : clients_info.app_uid,
client_secret: clients_info.servers ? c.env.googleui_key : clients_info.app_key,
grant_type: 'refresh_token',
refresh_token: refresh_text
};
return await refresh.genToken(c, driver_map[1], params, "POST","access_token","copy","none");
}

View File

@ -11,6 +11,7 @@ import * as ui123 from './123ui';
import * as baidu from './baidu';
import * as goapi from './goapi';
import * as yandex from './yandex';
import {genToken} from "./baidu";
export type Bindings = {
MAIN_URLS: string, baiduyun_ext: string,
@ -33,27 +34,36 @@ app.get('/onedrive/requests', async (c) => {
app.get('/onedrive/callback', async (c) => {
return oneui.oneToken(c);
})
// 令牌刷新 ##############################################################################
app.get('/onedrive/renewapi', async (c: Context) => {
return oneui.genToken(c);
});
// 登录申请 ##############################################################################
app.get('/alicloud/requests', async (c: Context) => {
return aliui.alyLogin(c);
});
// 令牌申请 ##############################################################################
app.get('/alicloud/callback', async (c: Context) => {
return aliui.alyToken(c);
});
// 令牌刷新 ##############################################################################
app.get('/alicloud/renewapi', async (c: Context) => {
return aliui.genToken(c);
});
// 阿里云盘扫码2 - 生成二维码 ##############################################################################
app.get('/alicloud2/generate_qr', async (c: Context) => {
return aliui2.generateQR(c);
});
// 阿里云盘扫码2 - 检查登录状态 ##############################################################################
app.get('/alicloud2/check_login', async (c: Context) => {
return aliui2.checkLogin(c);
});
// 令牌刷新 ##############################################################################
app.get('/alicloud/renewapi', async (c: Context) => {
return aliui2.genToken(c);
});
// 阿里云盘扫码2 - 获取用户信息 ##############################################################################
app.get('/alicloud2/get_user_info', async (c: Context) => {
return aliui2.getUserInfo(c);
@ -74,6 +84,11 @@ app.get('/baiduyun/callback', async (c: Context) => {
return baidu.oneToken(c);
});
// 令牌刷新 ##############################################################################
app.get('/baiduyun/renewapi', async (c: Context) => {
return baidu.genToken(c);
});
// 登录申请 ##############################################################################
app.get('/115cloud/requests', async (c: Context) => {
return ui115.oneLogin(c);
@ -84,6 +99,11 @@ app.get('/115cloud/callback', async (c: Context) => {
return ui115.oneToken(c);
});
// 令牌刷新 ##############################################################################
app.get('/115cloud/renewapi', async (c: Context) => {
return ui115.genToken(c);
});
// 登录申请 ##############################################################################
app.get('/123cloud/requests', async (c: Context) => {
return ui123.oneLogin(c);
@ -94,6 +114,11 @@ app.get('/123cloud/callback', async (c: Context) => {
return ui123.oneToken(c);
});
// 令牌刷新 ##############################################################################
app.get('/123cloud/renewapi', async (c: Context) => {
return ui123.genToken(c);
});
// 登录申请 ##############################################################################
app.get('/googleui/requests', async (c: Context) => {
return goapi.oneLogin(c);
@ -104,8 +129,24 @@ app.get('/googleui/callback', async (c: Context) => {
return goapi.oneToken(c);
});
app.get('/yandex/requests', async (c: Context) => {return yandex.yandexLogin(c)});
// 令牌刷新 ##############################################################################
app.get('/googleui/renewapi', async (c: Context) => {
return goapi.genToken(c);
});
app.get('/yandex/callback', async (c: Context) => {return yandex.yandexCallBack(c)});
// 登录申请 ##############################################################################
app.get('/yandexui/requests', async (c: Context) => {
return yandex.yandexLogin(c)
});
// 令牌申请 ##############################################################################
app.get('/yandexui/callback', async (c: Context) => {
return yandex.yandexCallBack(c)
});
// 令牌刷新 ##############################################################################
app.get('/yandexui/renewapi', async (c: Context) => {
return yandex.genToken(c);
});
export default app

View File

@ -1,7 +1,8 @@
import * as local from "hono/cookie";
import {Context} from "hono";
import {showErr} from "./error";
import * as configs from "./shares/configs";
import * as refresh from "./shares/refresh";
const driver_map: Record<string, string[]> = {
"onedrive_go": [
@ -145,3 +146,21 @@ export async function spSiteID(c: Context) {
return c.json({error: 'Zone does not exist'}, 400);
}
}
// 刷新令牌 ##############################################################################
export async function genToken(c: Context) {
const driver_txt: string = <string>c.req.query('apps_types');
const clients_info: configs.Clients | undefined = configs.getInfo(c);
const refresh_text: string | undefined = c.req.query('refresh_ui');
if (!clients_info) return c.json({text: "传入参数缺少"}, 500);
if (!refresh_text) return c.json({text: "缺少刷新令牌"}, 500);
// 请求参数 ==========================================================================
const params: Record<string, any> = {
client_id: clients_info.servers ? c.env.onedrive_uid : clients_info.app_uid,
client_secret: clients_info.servers ? c.env.onedrive_key : clients_info.app_key,
redirect_uri: 'https://' + c.env.MAIN_URLS + '/onedrive/callback',
grant_type: "refresh_token",
refresh_token: refresh_text
};
return await refresh.genToken(c, driver_map[driver_txt][1], params, "POST");
}

60
src/shares/refresh.ts Normal file
View File

@ -0,0 +1,60 @@
// 登录申请 ##############################################################################
import {Context} from "hono";
export async function genToken(c: Context,
APIUrl: string,
Params: Record<string, string>,
Method: string = "GET",
access_name: string = "access_token",
refresh_name: string = "refresh_token",
error_name: string = "error_description"
): Promise<any> {
// 请求参数 ==========================================================================
const parma_str = new URLSearchParams(Params).toString();
const parma_url = new URL(APIUrl);
Object.keys(Params).forEach(key => {
parma_url.searchParams.append(key, Params[key]);
});
try { // 执行请求 =====================================================================
const header_data = {'Content-Type': 'application/x-www-form-urlencoded'}
const result_data: Response = await fetch(
Method == "GET" ? parma_url.href : APIUrl, {
method: Method,
body: Method == "GET" ? undefined : parma_str,
headers: Method == "GET" ? undefined : header_data
}
);
const result_json: Record<string, any> = await result_data.json();
console.log(result_json);
if (getDynamicValue(result_json, refresh_name, Params.refresh_token))
return c.json({
refresh_token: getDynamicValue(result_json, refresh_name, Params.refresh_token),
access_token: getDynamicValue(result_json, access_name, ""),
}, 200);
return c.json({text: result_json[error_name]}, 500);
} catch (error) {
console.log(error);
return c.json({text: error}, 500);
}
}
function getDynamicValue(resultJson: Record<string, any>, path: string, origin_text: any): any {
if (path === "none") return "";
if (path === "copy") return origin_text;
// 将路径拆分为属性数组,例如 'data.refresh_token' 拆分为 ['data', 'refresh_token']
const properties = path.split('.');
// 从 resultJson 开始遍历属性
let currentValue = resultJson;
// 遍历每个属性,逐层深入对象
for (const prop of properties) {
// 检查当前值是否为对象且具有该属性
if (currentValue && typeof currentValue === 'object' && prop in currentValue) {
currentValue = currentValue[prop];
} else {
// 如果路径中的某一层不存在,则返回 undefined
return undefined;
}
}
return currentValue;
}

View File

@ -99,3 +99,8 @@ export async function yandexCallBack(c: Context) {
return c.redirect(showErr("Failed to get access token", "", ""));
}
}
// 刷新令牌 ##############################################################################
export async function genToken(c: Context) {
return c.json({text: "此网盘不支持"}, 500);
}