前言
今天上我的"优雅"拼车神器,突然发现:
始皇官方回答:【号商在太岁头上动土,波及反代小虾米】
https://linux.do/t/topic/718597/15
所以需要迭代我的原版方案:
CF worker 代码改动点(可跳过这章)
我列一下对原版帖子代码的改动点(如果是用上述方案部署的可以直接改对应的这几行),或者跳到下一章
- // ------------ 反代到 fuclaude
- const path = requestURL.pathname;
- if (path !== '/login') {
- requestURL.host = HOST;
- return fetch(new Request(requestURL, request))
- }
...
- return Response.redirect(`https://${requestURL.host}${respData.login_url}`, 301)
+ return Response.redirect(`https://${HOST}${respData.login_url}`, 301)
...
完整版
配置方案参考 【优雅系列】Claude私人拼车神器——多账号+聊天隔离+站密码 ,代码换成以下:
var KV = kv_shared_fuclaude;
const HOST = 'demo.fuclaude.com';
const BASE_URL = `https://${HOST}`;
const AUTH_ENDPOINT = '/manage-api/auth/oauth_token';
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function generateLoginHtml(accounts) {
return `<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI服务</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
padding: 20px;
}
form, .response-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
max-width: 600px;
margin: 20px auto;
}
h1 {
text-align: center;
}
h2 {
text-align: center;
}
p {
display: block;
margin-bottom: 10px;
font-size: 16px;
}
input[type="text"], textarea {
width: calc(100% - 22px);
padding: 10px;
margin-top: 5px;
margin-bottom: 20px;
border-radius: 5px;
border: 1px solid #ccc;
}
textarea {
font-family: 'Courier New', monospace;
background-color: #f8f8f8;
height: 150px; /* Adjust height based on your needs */
}
button {
background-color: #000000;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
font-weight:600;
width:100% !important
}
button:hover {
background-color: #1e293b;
}
@media (max-width: 768px) {
body, form, .response-container {
padding: 10px;
}
}
.checkbox-group {
display: flex;
justify-content: space-between;
}
.checkbox-group input[type="checkbox"] {
margin-right: 5px;
}
.checkbox-group label {
margin-right: 10px;
}
select {
width: calc(100% - 22px);
padding: 10px;
margin-top: 5px;
margin-bottom: 20px;
border-radius: 5px;
border: 1px solid #ccc;
font-size: 16px;
background-color: white;
}
select:focus {
outline: none;
border-color: #000;
}
</style>
</head>
<body>
<h1>标题</h1>
<form method="POST">
<label for="account-select">请选择一个号:</label>
<select id="account-select" name="account">
<option value="" disabled selected>请选择一个账号</option>
${Object.keys(accounts).map((nickname) => `
<option value="${nickname}">${nickname}</option>
`).join('')}
</select>
<br/>
<label for="site_password">请输入本网站使用密码:</label>
<input type="text" id="site_password" name="site_password" placeholder="The website password">
<label for="unique_name">请输入独一无二的名字,以区分你的身份,用于会话隔离:</label>
<input type="text" id="unique_name" name="unique_name" placeholder="Your unique name" required value="">
<br/>
<button type="submit">访问使用</button>
</form>
</html>`;
}
async function handleRequest(request) {
const requestURL = new URL(request.url);
const accountsJsonStr = await KV.get('account_nickname_to_session_keys');
const accounts = JSON.parse(accountsJsonStr);
// 返回账号列表
if (request.method === "GET") {
const html = await generateLoginHtml(accounts);
return new Response(html, {
headers: {
'Content-Type': 'text/html; charset=utf-8'
},
});
}
// 选中账号进行登录
if (request.method === "POST") {
const formData = await request.formData();
const account = formData.get("account");
const sitePassword = formData.get('site_password') || '';
const uniqueName = formData.get('unique_name');
// @ts-ignore
const SITE_PASSWORD = await KV.get('SITE_PASSWORD') || '';
if (sitePassword !== SITE_PASSWORD) {
return new Response('站密码错误', { status: 401 }); //如果你不需要密码访问,注释此行代码
}
const sessionKey = accounts[account];
const apiResp = await fetch(`${BASE_URL}${AUTH_ENDPOINT}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
session_key: sessionKey,
unique_name: uniqueName
}),
});
const respData = await apiResp.json();
if (respData.login_url) {
return Response.redirect(`https://${HOST}${respData.login_url}`, 301)
}
return new Response("未知错误~", {
headers: {
'Content-Type': 'text/html; charset=utf-8'
},
});
}
}