fix: 修复绑定名称冲突 - 将PASSWORD改为AUTH_PASSWORD避免Cloudflare保留名称
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
# Cloudflare Pages 部署修复指南
|
||||||
|
|
||||||
|
## 问题描述
|
||||||
|
|
||||||
|
在Cloudflare Pages部署时遇到绑定名称冲突:
|
||||||
|
```
|
||||||
|
Error: Failed to publish your Function. Got error: Binding name 'PASSWORD' already in use.
|
||||||
|
```
|
||||||
|
|
||||||
|
## 解决方案
|
||||||
|
|
||||||
|
我们已经将环境变量名从 `PASSWORD` 更改为 `AUTH_PASSWORD` 以避免Cloudflare的保留绑定名称冲突。
|
||||||
|
|
||||||
|
## 需要的操作
|
||||||
|
|
||||||
|
### 1. 更新 wrangler.toml 配置
|
||||||
|
✅ 已完成 - `PASSWORD` 已更改为 `AUTH_PASSWORD`
|
||||||
|
|
||||||
|
### 2. 更新代码中的引用
|
||||||
|
✅ 已完成 - 所有 `process.env.PASSWORD` 已更改为 `process.env.AUTH_PASSWORD`
|
||||||
|
|
||||||
|
### 3. 在 Cloudflare Pages 控制台中设置环境变量
|
||||||
|
|
||||||
|
由于您提到无法在控制台中直接修改环境变量(因为通过 wrangler.toml 管理),我们需要:
|
||||||
|
|
||||||
|
1. **重新部署项目** - 新的 wrangler.toml 配置会自动设置 `AUTH_PASSWORD` 变量
|
||||||
|
2. **验证环境变量** - 确保 `AUTH_PASSWORD` 正确设置
|
||||||
|
|
||||||
|
### 4. 立即执行步骤
|
||||||
|
|
||||||
|
现在执行以下命令重新部署:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
git add -A
|
||||||
|
git commit -m "fix: 修复绑定名称冲突 - 将PASSWORD改为AUTH_PASSWORD"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
## 更新说明
|
||||||
|
|
||||||
|
### 变更的文件:
|
||||||
|
- `wrangler.toml` - 更新环境变量名称
|
||||||
|
- `src/middleware.ts` - 更新认证逻辑
|
||||||
|
- `src/app/api/login/route.ts` - 更新登录验证
|
||||||
|
- `src/app/api/register/route.ts` - 更新注册逻辑
|
||||||
|
|
||||||
|
### 环境变量变更:
|
||||||
|
- `PASSWORD` → `AUTH_PASSWORD`
|
||||||
|
- 功能保持完全一致,只是变量名称改变
|
||||||
|
|
||||||
|
## 预期结果
|
||||||
|
|
||||||
|
部署成功后:
|
||||||
|
1. 不再出现绑定名称冲突错误
|
||||||
|
2. `AUTH_PASSWORD` 环境变量将自动通过 wrangler.toml 设置
|
||||||
|
3. 网站应该正常运行,认证功能正常
|
||||||
|
|
||||||
|
## 验证步骤
|
||||||
|
|
||||||
|
部署完成后:
|
||||||
|
1. 访问您的 Cloudflare Pages 网站
|
||||||
|
2. 尝试登录(用户名: katelya,密码: your-secure-password-here)
|
||||||
|
3. 如果能正常登录,说明修复成功
|
||||||
|
|
||||||
|
如果仍有问题,请检查 Cloudflare Pages 的部署日志。
|
||||||
@@ -56,10 +56,10 @@ async function generateAuthCookie(
|
|||||||
authData.password = password;
|
authData.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (username && process.env.PASSWORD) {
|
if (username && process.env.AUTH_PASSWORD) {
|
||||||
authData.username = username;
|
authData.username = username;
|
||||||
// 使用密码作为密钥对用户名进行签名
|
// 使用密码作为密钥对用户名进行签名
|
||||||
const signature = await generateSignature(username, process.env.PASSWORD);
|
const signature = await generateSignature(username, process.env.AUTH_PASSWORD);
|
||||||
authData.signature = signature;
|
authData.signature = signature;
|
||||||
authData.timestamp = Date.now(); // 添加时间戳防重放攻击
|
authData.timestamp = Date.now(); // 添加时间戳防重放攻击
|
||||||
}
|
}
|
||||||
@@ -71,9 +71,9 @@ export async function POST(req: NextRequest) {
|
|||||||
try {
|
try {
|
||||||
// 本地 / localStorage 模式——仅校验固定密码
|
// 本地 / localStorage 模式——仅校验固定密码
|
||||||
if (STORAGE_TYPE === 'localstorage') {
|
if (STORAGE_TYPE === 'localstorage') {
|
||||||
const envPassword = process.env.PASSWORD;
|
const envPassword = process.env.AUTH_PASSWORD;
|
||||||
|
|
||||||
// 未配置 PASSWORD 时直接放行
|
// 未配置 AUTH_PASSWORD 时直接放行
|
||||||
if (!envPassword) {
|
if (!envPassword) {
|
||||||
const response = NextResponse.json({ ok: true });
|
const response = NextResponse.json({ ok: true });
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ export async function POST(req: NextRequest) {
|
|||||||
// 可能是站长,直接读环境变量
|
// 可能是站长,直接读环境变量
|
||||||
if (
|
if (
|
||||||
username === process.env.USERNAME &&
|
username === process.env.USERNAME &&
|
||||||
password === process.env.PASSWORD
|
password === process.env.AUTH_PASSWORD
|
||||||
) {
|
) {
|
||||||
// 验证成功,设置认证cookie
|
// 验证成功,设置认证cookie
|
||||||
const response = NextResponse.json({ ok: true });
|
const response = NextResponse.json({ ok: true });
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ async function generateAuthCookie(username: string): Promise<string> {
|
|||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// 使用process.env.PASSWORD作为签名密钥,而不是用户密码
|
// 使用process.env.AUTH_PASSWORD作为签名密钥,而不是用户密码
|
||||||
const signingKey = process.env.PASSWORD || '';
|
const signingKey = process.env.AUTH_PASSWORD || '';
|
||||||
const signature = await generateSignature(username, signingKey);
|
const signature = await generateSignature(username, signingKey);
|
||||||
authData.signature = signature;
|
authData.signature = signature;
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -14,7 +14,7 @@ export async function middleware(request: NextRequest) {
|
|||||||
|
|
||||||
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
|
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
|
||||||
|
|
||||||
if (!process.env.PASSWORD) {
|
if (!process.env.AUTH_PASSWORD) {
|
||||||
// 如果没有设置密码,重定向到警告页面
|
// 如果没有设置密码,重定向到警告页面
|
||||||
const warningUrl = new URL('/warning', request.url);
|
const warningUrl = new URL('/warning', request.url);
|
||||||
return NextResponse.redirect(warningUrl);
|
return NextResponse.redirect(warningUrl);
|
||||||
@@ -29,7 +29,7 @@ export async function middleware(request: NextRequest) {
|
|||||||
|
|
||||||
// localstorage模式:在middleware中完成验证
|
// localstorage模式:在middleware中完成验证
|
||||||
if (storageType === 'localstorage') {
|
if (storageType === 'localstorage') {
|
||||||
if (!authInfo.password || authInfo.password !== process.env.PASSWORD) {
|
if (!authInfo.password || authInfo.password !== process.env.AUTH_PASSWORD) {
|
||||||
return handleAuthFailure(request, pathname);
|
return handleAuthFailure(request, pathname);
|
||||||
}
|
}
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
@@ -46,7 +46,7 @@ export async function middleware(request: NextRequest) {
|
|||||||
const isValidSignature = await verifySignature(
|
const isValidSignature = await verifySignature(
|
||||||
authInfo.username,
|
authInfo.username,
|
||||||
authInfo.signature,
|
authInfo.signature,
|
||||||
process.env.PASSWORD || ''
|
process.env.AUTH_PASSWORD || ''
|
||||||
);
|
);
|
||||||
|
|
||||||
// 签名验证通过即可
|
// 签名验证通过即可
|
||||||
|
|||||||
+18
-3
@@ -1,5 +1,20 @@
|
|||||||
name = "katelyatv"
|
name = "katelyat[env.preview.vars]
|
||||||
compatibility_date = "2024-09-01"
|
NEXT_PUBLIC_STORAGE_TYPE = "d1"
|
||||||
|
NEXT_PUBLIC_SITE_NAME = "KatelyaTV"
|
||||||
|
NEXT_PUBLIC_SITE_DESCRIPTION = "高性能影视播放平台"
|
||||||
|
NEXTAUTH_URL = "https://your-domain.pages.dev"
|
||||||
|
USERNAME = "katelya"
|
||||||
|
AUTH_PASSWORD = "your-secure-password-here"
|
||||||
|
IMAGE_PROXY_ENABLED = "true"
|
||||||
|
CACHE_TTL = "3600"
|
||||||
|
CORS_ORIGIN = "*"
|
||||||
|
RATE_LIMIT_MAX = "100"
|
||||||
|
RATE_LIMIT_WINDOW = "60000"
|
||||||
|
HEALTH_CHECK_ENABLED = "true"
|
||||||
|
HEALTH_CHECK_INTERVAL = "30"
|
||||||
|
LOG_LEVEL = "info"
|
||||||
|
LOG_FORMAT = "json"
|
||||||
|
NODE_ENV = "production"_date = "2024-09-01"
|
||||||
compatibility_flags = ["nodejs_compat"]
|
compatibility_flags = ["nodejs_compat"]
|
||||||
pages_build_output_dir = ".vercel/output/static"
|
pages_build_output_dir = ".vercel/output/static"
|
||||||
|
|
||||||
@@ -20,7 +35,7 @@ NEXT_PUBLIC_SITE_NAME = "KatelyaTV"
|
|||||||
NEXT_PUBLIC_SITE_DESCRIPTION = "高性能影视播放平台"
|
NEXT_PUBLIC_SITE_DESCRIPTION = "高性能影视播放平台"
|
||||||
NEXTAUTH_URL = "https://your-domain.pages.dev"
|
NEXTAUTH_URL = "https://your-domain.pages.dev"
|
||||||
USERNAME = "katelya"
|
USERNAME = "katelya"
|
||||||
PASSWORD = "your-secure-password-here"
|
AUTH_PASSWORD = "your-secure-password-here"
|
||||||
IMAGE_PROXY_ENABLED = "true"
|
IMAGE_PROXY_ENABLED = "true"
|
||||||
CACHE_TTL = "3600"
|
CACHE_TTL = "3600"
|
||||||
CORS_ORIGIN = "*"
|
CORS_ORIGIN = "*"
|
||||||
|
|||||||
Reference in New Issue
Block a user