# API Basic Auth 认证指南(Caddy 版本) 本文档说明外部服务器如何安全地调用本项目的 API 接口(已配置 Basic Auth)。 ## 安全原则 **⚠️ 重要:永远不要在代码中硬编码用户名和密码!** 应该使用以下方式存储凭证: - 环境变量(推荐) - 密钥管理服务(如 AWS Secrets Manager、HashiCorp Vault) - 配置文件(不提交到 Git,使用 `.gitignore`) --- ## 配置 Basic Auth ### 1. 生成 htpasswd 文件 Caddy 使用 htpasswd 文件存储用户名和密码。使用以下命令生成: ```bash # 使用 Docker 生成 htpasswd 文件(推荐) docker run --rm httpd:alpine htpasswd -nbB admin your_password > htpasswd # 示例输出(内容会写入 htpasswd 文件): # admin:$2y$05$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` **参数说明:** - `-n`:输出到标准输出而不是文件 - `-b`:使用批处理模式(密码在命令行提供) - `-B`:使用 bcrypt 加密(Caddy 要求) ### 2. 配置 htpasswd 文件 生成的 `htpasswd` 文件会自动被 Caddy 读取(已通过 docker-compose 挂载到容器中)。 **注意**:`htpasswd` 文件已添加到 `.gitignore`,不会被提交到 Git。 --- ## 代码示例 ### Node.js / TypeScript #### 使用原生 fetch ```typescript // 从环境变量读取凭证 const username = process.env.BYREAL_API_USERNAME || '' const password = process.env.BYREAL_API_PASSWORD || '' // 生成 Basic Auth header const credentials = Buffer.from(`${username}:${password}`).toString('base64') const authHeader = `Basic ${credentials}` // 发送请求(使用 HTTPS) const response = await fetch('https://love.hdlife.me/api/my-lp', { method: 'GET', headers: { Authorization: authHeader, 'Content-Type': 'application/json', }, }) const data = await response.json() ``` #### 使用 axios ```typescript import axios from 'axios' const username = process.env.BYREAL_API_USERNAME || '' const password = process.env.BYREAL_API_PASSWORD || '' const response = await axios.get('https://love.hdlife.me/api/my-lp', { auth: { username, password, }, headers: { 'Content-Type': 'application/json', }, }) const data = response.data ``` #### 使用 ky ```typescript import ky from 'ky' const username = process.env.BYREAL_API_USERNAME || '' const password = process.env.BYREAL_API_PASSWORD || '' const credentials = Buffer.from(`${username}:${password}`).toString('base64') const response = await ky.get('https://love.hdlife.me/api/my-lp', { headers: { Authorization: `Basic ${credentials}`, }, }) const data = await response.json() ``` --- ### Python #### 使用 requests ```python import os import requests from requests.auth import HTTPBasicAuth # 从环境变量读取 username = os.getenv('BYREAL_API_USERNAME', '') password = os.getenv('BYREAL_API_PASSWORD', '') # 方式 1: 使用 HTTPBasicAuth(推荐) response = requests.get( 'https://love.hdlife.me/api/my-lp', auth=HTTPBasicAuth(username, password), headers={'Content-Type': 'application/json'} ) data = response.json() # 方式 2: 手动设置 header import base64 credentials = base64.b64encode(f'{username}:{password}'.encode()).decode() headers = { 'Authorization': f'Basic {credentials}', 'Content-Type': 'application/json' } response = requests.get('https://love.hdlife.me/api/my-lp', headers=headers) ``` --- ### curl 命令 ```bash # 从环境变量读取 curl -u "${BYREAL_API_USERNAME}:${BYREAL_API_PASSWORD}" \ https://love.hdlife.me/api/my-lp # 或者直接指定(不推荐,密码会出现在命令历史中) curl -u "admin:your_password" \ https://love.hdlife.me/api/my-lp ``` --- ### Go ```go package main import ( "encoding/base64" "fmt" "io" "net/http" "os" ) func main() { username := os.Getenv("BYREAL_API_USERNAME") password := os.Getenv("BYREAL_API_PASSWORD") credentials := base64.StdEncoding.EncodeToString([]byte(username + ":" + password)) req, _ := http.NewRequest("GET", "https://love.hdlife.me/api/my-lp", nil) req.Header.Set("Authorization", "Basic "+credentials) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) if err != nil { panic(err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) } ``` --- ### Java ```java import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.URI; import java.util.Base64; public class ApiClient { public static void main(String[] args) { String username = System.getenv("BYREAL_API_USERNAME"); String password = System.getenv("BYREAL_API_PASSWORD"); String credentials = Base64.getEncoder().encodeToString( (username + ":" + password).getBytes() ); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://love.hdlife.me/api/my-lp")) .header("Authorization", "Basic " + credentials) .header("Content-Type", "application/json") .GET() .build(); try { HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } catch (Exception e) { e.printStackTrace(); } } } ``` --- ## Docker 环境配置 如果外部服务器也在 Docker 中运行,在 `docker-compose.yml` 中配置: ```yaml services: your-service: image: your-image environment: - BYREAL_API_USERNAME=${BYREAL_API_USERNAME} - BYREAL_API_PASSWORD=${BYREAL_API_PASSWORD} # 或者从 .env 文件读取 env_file: - .env ``` --- ## 部署步骤 ### 1. 生成 htpasswd 文件 在服务器上执行: ```bash # 生成 htpasswd 文件 docker run --rm httpd:alpine htpasswd -nbB admin your_password > htpasswd # 查看生成的文件 cat htpasswd ``` ### 2. 配置环境变量 在服务器上创建 `.env` 文件: ```bash # Solana 配置 SOL_ENDPOINT=your_solana_endpoint SOL_SECRET_KEY=your_secret_key ``` ### 3. 启动服务 ```bash docker compose down docker compose up -d ``` ### 4. 验证 HTTPS 访问 `https://love.hdlife.me`,应该会自动跳转到 HTTPS 并要求 Basic Auth。 --- ## 安全最佳实践 1. ✅ **使用环境变量**:永远不要在代码中硬编码密码 2. ✅ **使用 `.gitignore`**:确保 `htpasswd` 文件不会被提交 3. ✅ **使用密钥管理服务**:生产环境推荐使用 AWS Secrets Manager、Azure Key Vault 等 4. ✅ **定期轮换密码**:定期更换 Basic Auth 密码 5. ✅ **使用 HTTPS**:Caddy 自动配置 HTTPS,无需额外操作 6. ✅ **限制访问 IP**:在服务器防火墙中限制允许的 IP 7. ✅ **最小权限原则**:只为需要的服务提供凭证 --- ## 测试连接 使用 curl 测试 Basic Auth 和 HTTPS: ```bash # 测试(会提示输入密码) curl -u admin https://love.hdlife.me/api/my-lp # 或者从环境变量读取 curl -u "${BYREAL_API_USERNAME}:${BYREAL_API_PASSWORD}" \ https://love.hdlife.me/api/my-lp ``` 如果返回 401 Unauthorized,说明凭证错误;如果返回 200 或其他业务状态码,说明认证成功。 --- ## 常见问题 ### Q: 如何获取 Basic Auth 凭证? A: 联系项目管理员获取用户名和密码。密码存储在服务器的 `htpasswd` 文件中。 ### Q: 密码忘记了怎么办? A: 在服务器上重新生成 htpasswd 文件: ```bash # 生成新密码 docker run --rm httpd:alpine htpasswd -nbB admin new_password > htpasswd # 重启服务 docker compose restart caddy ``` ### Q: 如何查看 Caddy 日志? A: ```bash # 查看 Caddy 容器日志 docker logs byreal-caddy # 查看访问日志(如果在 Caddyfile 中配置了日志文件) docker exec byreal-caddy cat /var/log/caddy/access.log ``` ### Q: HTTPS 证书如何续期? A: Caddy 会自动管理 Let's Encrypt 证书的续期,无需手动操作。 --- ## 相关文件 - `Caddyfile` - Caddy HTTPS + Basic Auth 配置 - `htpasswd` - Basic Auth 密码文件(不提交到 Git) - `docker-compose.yml` - Docker 服务配置 - `.env` - 环境变量配置(不提交到 Git)