# Token Auth 实现指南 ## 快速开始 本项目实现了 Public + Refresh + JWT access_token 双层签发认证机制。 ### 目录结构 ``` /Users/shenlan/workspaces/XControl/ ├── dashboard-fresh/ │ ├── config/ │ │ └── runtime-service-config.base.yaml │ └── lib/ │ └── auth/ │ ├── token_service.ts # Deno 前端认证模块 │ └── use_auth.ts # React Hook │ ├── account/ │ ├── config/ │ │ └── account.yaml │ └── internal/ │ └── auth/ │ ├── token_service.go # JWT 签发与验证 │ ├── mfa_service.go # MFA 服务 │ └── middleware.go # HTTP 中间件 │ ├── rag-server/ │ ├── config/ │ │ └── server.yaml │ └── internal/ │ └── auth/ │ ├── token_service.go # JWT 签发与验证 │ └── middleware.go # HTTP 中间件 │ ├── scripts/ │ └── update_token_auth.sh # 自动更新脚本 │ ├── TOKEN_AUTH_MANUAL.md # 完整维护手册 └── IMPLEMENTATION_GUIDE.md # 本文件 ``` ## 安装依赖 ### Go 服务 在 `account/` 和 `rag-server/` 目录下添加 `go.mod` 文件: ```bash # account/go.mod module account go 1.21 require ( github.com/gin-gonic/gin v1.9.1 github.com/golang-jwt/jwt/v5 v5.2.0 github.com/pquerna/otp v1.4.0 ) ``` ```bash # rag-server/go.mod module rag-server go 1.21 require ( github.com/gin-gonic/gin v1.9.1 github.com/golang-jwt/jwt/v5 v5.2.0 ) ``` 安装依赖: ```bash cd account && go mod tidy cd rag-server && go mod tidy ``` ## 使用示例 ### 1. Go 服务 (account) ```go package main import ( "time" "github.com/gin-gonic/gin" "account/internal/auth" ) func main() { // 初始化 Token 服务 tokenService := auth.NewTokenService(auth.TokenConfig{ PublicToken: "xcontrol-public-token-2024", RefreshSecret: "xcontrol-refresh-secret-2024", AccessSecret: "xcontrol-access-secret-2024", AccessExpiry: time.Hour, // 1小时 RefreshExpiry: time.Hour * 24 * 7, // 7天 }) r := gin.Default() // 登录接口 - 生成令牌 r.POST("/api/auth/login", func(c *gin.Context) { // 验证用户凭据... // 生成令牌 tokenPair, err := tokenService.GenerateTokenPair( "user123", "user@example.com", []string{"user"}, ) if err != nil { c.JSON(500, gin.H{"error": err.Error()}) return } c.JSON(200, tokenPair) }) // 刷新接口 r.POST("/api/auth/refresh", func(c *gin.Context) { var req struct { RefreshToken string `json:"refresh_token"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } accessToken, err := tokenService.RefreshAccessToken(req.RefreshToken) if err != nil { c.JSON(401, gin.H{"error": "Invalid refresh token"}) return } c.JSON(200, gin.H{ "access_token": accessToken, "expires_in": int64(tokenService.GetAccessTokenExpiry().Seconds()), }) }) // 受保护的接口 protected := r.Group("/api") protected.Use(tokenService.AuthMiddleware()) { protected.GET("/user/profile", func(c *gin.Context) { userID := auth.GetUserID(c) c.JSON(200, gin.H{ "user_id": userID, }) }) // 需要 MFA 的接口 protected.GET("/admin/dashboard", auth.RequireMFA(), auth.RequireRole("admin"), func(c *gin.Context) { c.JSON(200, gin.H{"message": "Admin dashboard"}) }) } r.Run(":8080") } ``` ### 2. Go 服务 (rag-server) ```go package main import ( "time" "github.com/gin-gonic/gin" "rag-server/internal/auth" ) func main() { tokenService := auth.NewTokenService(auth.TokenConfig{ PublicToken: "xcontrol-public-token-2024", RefreshSecret: "xcontrol-refresh-secret-2024", AccessSecret: "xcontrol-access-secret-2024", AccessExpiry: time.Hour, RefreshExpiry: time.Hour * 24 * 7, }) r := gin.Default() // 保护 RAG API r.Use(tokenService.AuthMiddleware()) r.POST("/api/rag/query", func(c *gin.Context) { userID := auth.GetUserID(c) email := auth.GetEmail(c) c.JSON(200, gin.H{ "user_id": userID, "email": email, "result": "RAG query processed", }) }) r.Run(":8090") } ``` ### 3. 前端 (Deno + Preact) ```typescript import { useAuth } from '../lib/auth/use_auth.ts'; function App() { const { user, login, logout, loading } = useAuth(); if (loading) { return