# API Basic Auth 认证指南 本文档说明外部服务器如何安全地调用本项目的 API 接口(已配置 Basic Auth)。 ## 安全原则 **⚠️ 重要:永远不要在代码中硬编码用户名和密码!** 应该使用以下方式存储凭证: - 环境变量(推荐) - 密钥管理服务(如 AWS Secrets Manager、HashiCorp Vault) - 配置文件(不提交到 Git,使用 `.gitignore`) --- ## 配置方式 ### 1. 设置环境变量 在外部服务器的环境中设置以下变量: ```bash # Basic Auth 用户名 export BYREAL_API_USERNAME=admin # Basic Auth 密码 export BYREAL_API_PASSWORD=your_password_here ``` 或者在 `.env` 文件中(不要提交到 Git): ```bash BYREAL_API_USERNAME=admin BYREAL_API_PASSWORD=your_password_here ``` --- ## 代码示例 ### 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}` // 发送请求 const response = await fetch('http://your-server-ip/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('http://your-server-ip/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('http://your-server-ip/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( 'http://your-server-ip/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('http://your-server-ip/api/my-lp', headers=headers) ``` --- ### curl 命令 ```bash # 从环境变量读取 curl -u "${BYREAL_API_USERNAME}:${BYREAL_API_PASSWORD}" \ http://your-server-ip/api/my-lp # 或者直接指定(不推荐,密码会出现在命令历史中) curl -u "admin:your_password" \ http://your-server-ip/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", "http://your-server-ip/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("http://your-server-ip/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. ✅ **使用环境变量**:永远不要在代码中硬编码密码 2. ✅ **使用 `.gitignore`**:确保包含密码的 `.env` 文件不会被提交 3. ✅ **使用密钥管理服务**:生产环境推荐使用 AWS Secrets Manager、Azure Key Vault 等 4. ✅ **定期轮换密码**:定期更换 Basic Auth 密码 5. ✅ **使用 HTTPS**:生产环境必须使用 HTTPS(当前是 HTTP,仅用于开发/内网) 6. ✅ **限制访问 IP**:在 Nginx 中配置 `allow/deny` 限制允许访问的 IP 7. ✅ **最小权限原则**:只为需要的服务提供凭证 --- ## 测试连接 使用 curl 测试 Basic Auth 是否配置正确: ```bash # 测试(会提示输入密码) curl -u admin http://your-server-ip/api/my-lp # 或者从环境变量读取 curl -u "${BYREAL_API_USERNAME}:${BYREAL_API_PASSWORD}" \ http://your-server-ip/api/my-lp ``` 如果返回 401 Unauthorized,说明凭证错误;如果返回 200 或其他业务状态码,说明认证成功。 --- ## 常见问题 ### Q: 如何获取 Basic Auth 凭证? A: 联系项目管理员获取用户名和密码。密码存储在服务器的 `htpasswd` 文件中。 ### Q: 密码忘记了怎么办? A: 在服务器上重新生成: ```bash htpasswd ./htpasswd admin # 输入新密码 ``` 然后重启 Docker 容器: ```bash docker compose restart nginx ``` ### Q: 如何在生产环境使用 HTTPS? A: 需要配置 SSL 证书,修改 `nginx.conf` 添加 SSL 配置,并更新 `docker-compose.yml` 映射 443 端口。 --- ## 相关文件 - `nginx.conf` - Nginx Basic Auth 配置 - `htpasswd` - Basic Auth 密码文件(不提交到 Git) - `docker-compose.yml` - Docker 服务配置