add initial implementation - #500
Conversation
|
|
||
| // 第一次 MD5: password + 固定盐 | ||
| passwd := req.Password + "_bt_all_in_ssl" | ||
| keyMd5 := md5.Sum([]byte(passwd)) |
Check failure
Code scanning / CodeQL
Use of a broken or weak cryptographic hashing algorithm on sensitive data High
|
|
||
| // generateSignature 生成 API 签名(内部使用) | ||
| func generateSignature(timestamp, apiKey string) string { | ||
| keyMd5 := md5.Sum([]byte(apiKey)) |
Check failure
Code scanning / CodeQL
Use of a broken or weak cryptographic hashing algorithm on sensitive data High
There was a problem hiding this comment.
Pull request overview
This PR introduces JWT- and API-key–based authentication for the backend API (to support third-party API/SDK usage per #423), and updates the frontend + build/docs so clients can obtain/store tokens and call authenticated endpoints.
Changes:
- Backend: add JWT utilities/config and new
/v1/token/*endpoints for generating/refreshing tokens and managing API keys. - Backend middleware: accept
Authorization: Bearer ...for JWT and API-key signature auth (in addition to existing session/cookie auth). - Frontend & ops/docs: store JWT on login, attach it to requests, add Docker multi-stage frontend build, build scripts, and an API auth guide.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates installation/build/development instructions (incl. prerequisites). |
| README_EN.md | English installation/build/development + architecture/contributing/contact sections. |
| API_AUTH_GUIDE.md | New guide describing JWT and API-key authentication flows. |
| Dockerfile | Adds frontend build stage and copies built assets into Go build context. |
| build.sh | New Linux/macOS build script (frontend then backend). |
| build.bat | New Windows build script (frontend then backend). |
| backend/route/route.go | Registers new /v1/token/* routes. |
| backend/public/jwt.go | Adds JWT generation/parsing and API-token signature helpers. |
| backend/public/config.go | Adds JWT secret/expiry settings and reload logic. |
| backend/middleware/auth.go | Adds Bearer auth handling and changes auth bypass logic. |
| backend/app/api/token.go | Adds token/API-key management handlers. |
| backend/app/api/login.go | Extends login response to include a JWT token. |
| frontend/apps/allin-ssl/src/types/public.d.ts | Updates login response typing to include token fields. |
| frontend/apps/allin-ssl/src/api/public.ts | Stores token after login and clears it on sign-out. |
| frontend/apps/allin-ssl/src/api/index.ts | Adds token storage helpers and attaches Authorization header to requests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // 检查时间戳是否过期(5 分钟) | ||
| ts, err := ParseTimestamp(timestamp) | ||
| if err != nil { | ||
| return false | ||
| } | ||
|
|
||
| if time.Now().Unix()-ts > 300 { |
| func generateSignature(timestamp, apiKey string) string { | ||
| keyMd5 := md5.Sum([]byte(apiKey)) | ||
| keyMd5Hex := strings.ToLower(hex.EncodeToString(keyMd5[:])) | ||
|
|
||
| signMd5 := md5.Sum([]byte(timestamp + keyMd5Hex)) |
| if time.Now().Unix()-timestamp > 60*5 { | ||
| c.JSON(http.StatusUnauthorized, gin.H{"error": "timestamp expired"}) | ||
| return false | ||
| } |
| } | ||
|
|
||
| // 生成 JWT token | ||
| token, _ := public.GenerateToken(form.Username, userID, public.JWTExpire) |
| export const createApiToken = (): ApiTokenResult => { | ||
| const now = new Date().getTime(); | ||
| const apiKey = "123456"; // 注意: 此处为硬编码密钥,建议后续优化 | ||
| const apiKey = "123456"; // 注意:此处为硬编码密钥,仅用于开发测试 | ||
| const api_token = MD5(now + MD5(apiKey).toString()).toString(); | ||
| return { api_token, timestamp: now }; |
| if time.Now().Unix()-timestamp > 60*5 { | ||
| c.JSON(http.StatusUnauthorized, gin.H{"error": "timestamp expired"}) | ||
| return false | ||
| } |
| // 先尝试 JSON 绑定,失败则尝试 form 绑定 | ||
| if err := c.ShouldBindJSON(&req); err != nil { | ||
| if err := c.ShouldBind(&req); err != nil { | ||
| public.FailMsg(c, "参数错误:"+err.Error()) | ||
| return | ||
| } |
| "api_key": apiKey, | ||
| "timestamp": req.Timestamp, | ||
| "api_token": apiToken, | ||
| "bearer": "api_key:" + apiKey + ":" + req.Timestamp + ":" + apiToken, | ||
| "expire_in": 300, // 5 分钟 | ||
| "usage": "Authorization: Bearer " + "api_key:" + apiKey + ":" + req.Timestamp + ":" + apiToken, |
| public.SuccessData(c, gin.H{ | ||
| "api_key": apiKey, | ||
| "enabled": true, | ||
| }, 0) |
| "timestamp": "1234567890", | ||
| "api_token": "abc123...", | ||
| "bearer": "api_key:your_secret_api_key:1234567890:abc123...", | ||
| "expire_in": 300, | ||
| "usage": "Authorization: Bearer api_key:your_secret_api_key:1234567890:abc123..." |
Add token and api-key based authorization for api. See also #423.