lushdog@outlook.com před 3 týdny
rodič
revize
de60c0b5aa
2 změnil soubory, kde provedl 314 přidání a 2 odebrání
  1. 311 0
      API_AUTH.md
  2. 3 2
      README.md

+ 311 - 0
API_AUTH.md

@@ -0,0 +1,311 @@
+# 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<String> 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 服务配置

+ 3 - 2
README.md

@@ -34,10 +34,11 @@ SOL_SECRET_KEY=your_secret_key_here
 
 apt install httpd
 
-htpasswd -c ./htpasswd admin
 # 按提示输入两次密码
+htpasswd -c ./htpasswd admin
+
+docker compose up -d
 
-`docker compose up -d`
 ```
 
 ### 使用 RPC 地址