v2.0【优雅系列】Claude私人拼车神器——多账号+聊天隔离+站密码

前言

今天上我的"优雅"拼车神器,突然发现:

始皇官方回答:【号商在太岁头上动土,波及反代小虾米】

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'
      },
    });
  }

}
10 Likes

太强了!大佬!

支持,我也刚出现这个问题,就是跟朋友共享的

但是这样如果有多个号就切不回去了啊

1 Like

是的,没有办法,只能直连 demo.fuclaude 了

感谢分享

求个车队啊,原来的车队炸了

佬,怎么直接跳转fuclaude了

这个帖子有缘由:

https://linux.do/t/topic/718597

1 Like