aster Server 提供完整的认证和授权系统,支持 API Key、JWT 和 RBAC 权限控制。
最简单的认证方式,适用于服务间通信和 API 集成。
config := &server.Config{
Auth: server.AuthConfig{
APIKey: server.APIKeyConfig{
Enabled: true,
Keys: []string{
"sk_abc123...", // 预定义的 key
},
},
},
}
# Header 方式
curl -H "X-API-Key: sk_abc123..." http://localhost:8080/v1/agents
# Bearer Token 方式
curl -H "Authorization: Bearer sk_abc123..." http://localhost:8080/v1/agents
# Query 参数方式
curl http://localhost:8080/v1/agents?api_key=sk_abc123...
import "github.com/astercloud/aster/server/auth"
// 生成新的 API Key
key, _ := auth.GenerateAPIKey()
// 返回: sk_a1b2c3d4e5f6...
// 存储 API Key
apiKeyStore := auth.NewMemoryAPIKeyStore()
apiKeyStore.Create(ctx, &auth.APIKeyInfo{
Key: key,
UserID: "user123",
Roles: []string{"user"},
ExpiresAt: &expiryTime,
})
基于令牌的认证,支持无状态会话和细粒度控制。
config := &server.Config{
Auth: server.AuthConfig{
JWT: server.JWTConfig{
Enabled: true,
Secret: "your-jwt-secret-key",
Issuer: "aster",
Expiry: 86400, // 24 hours
},
},
}
jwtAuth := auth.NewJWTAuthenticator(auth.JWTConfig{
SecretKey: "your-secret",
Issuer: "aster",
ExpiryDuration: 24 * time.Hour,
})
user := &auth.User{
ID: "user123",
Username: "john",
Email: "john@example.com",
Roles: []string{"user"},
}
token, expiresAt, _ := jwtAuth.GenerateToken(user)
// 返回: eyJhbGciOiJIUzI1NiIs...
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
http://localhost:8080/v1/agents
newToken, expiresAt, _ := jwtAuth.RefreshToken(oldToken)
同时支持多种认证方法:
config := &server.Config{
Auth: server.AuthConfig{
APIKey: server.APIKeyConfig{Enabled: true, ...},
JWT: server.JWTConfig{Enabled: true, ...},
},
}
// 请求会依次尝试:
// 1. API Key 认证
// 2. JWT 认证
基于角色的访问控制,支持细粒度权限管理。
{
Name: "admin",
Permissions: []Permission{
{Resource: "*", Actions: []string{"*"}},
},
}
// 完全权限
{
Name: "user",
Permissions: []Permission{
{Resource: "agents", Actions: []string{"create", "read", "update", "delete"}},
{Resource: "sessions", Actions: []string{"create", "read", "update", "delete"}},
{Resource: "workflows", Actions: []string{"read", "execute"}},
},
}
// 基础 CRUD + 工作流执行
{
Name: "viewer",
Permissions: []Permission{
{Resource: "*", Actions: []string{"read"}},
},
}
// 只读权限
{
Name: "developer",
Permissions: []Permission{
{Resource: "agents", Actions: []string{"*"}},
{Resource: "workflows", Actions: []string{"*"}},
{Resource: "tools", Actions: []string{"*"}},
{Resource: "eval", Actions: []string{"*"}},
},
}
// 开发相关完全权限
rbac := auth.NewRBAC()
// 添加自定义角色
customRole := &auth.Role{
Name: "analyst",
Description: "Data analyst with read and eval permissions",
Permissions: []auth.Permission{
{Resource: "agents", Actions: []string{"read"}},
{Resource: "sessions", Actions: []string{"read"}},
{Resource: "eval", Actions: []string{"*"}},
},
}
rbac.AddRole(customRole)
func (h *AgentHandler) Delete(c *gin.Context) {
user := getUserFromContext(c) // 从 context 获取用户
// 检查权限
if !h.rbac.HasPermission(c.Request.Context(), user, "agents", "delete") {
c.JSON(http.StatusForbidden, gin.H{
"error": "Permission denied",
})
return
}
// 执行删除...
}
func RequirePermission(rbac *auth.RBAC, resource, action string) gin.HandlerFunc {
return func(c *gin.Context) {
user := getUserFromContext(c)
if !rbac.HasPermission(c.Request.Context(), user, resource, action) {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
"error": "Permission denied",
})
return
}
c.Next()
}
}
// 使用
router.DELETE("/agents/:id",
RequirePermission(rbac, "agents", "delete"),
h.Delete,
)
permissions := rbac.GetUserPermissions(user)
// 返回: []Permission{
// {Resource: "agents", Actions: ["create", "read", "update"]},
// {Resource: "sessions", Actions: ["read"]},
// }
✅ 推荐:
sk_ 前缀标识apiKeyInfo := &auth.APIKeyInfo{
Key: "sk_xxx",
UserID: "user123",
Name: "Production API Key",
Roles: []string{"user"},
ExpiresAt: &expiryTime,
Metadata: map[string]interface{}{
"environment": "production",
"created_by": "admin",
},
}
❌ 避免:
✅ 推荐:
jwtConfig := auth.JWTConfig{
SecretKey: os.Getenv("JWT_SECRET"), // 从环境变量
Issuer: "aster",
ExpiryDuration: 24 * time.Hour, // 24 小时
}
❌ 避免:
✅ 推荐:
// 按职能划分角色
roles := []string{
"admin", // 系统管理员
"developer", // 开发者
"analyst", // 数据分析师
"viewer", // 只读用户
}
❌ 避免:
✅ 推荐:
config := &server.Config{
TLS: server.TLSConfig{
Enabled: true,
CertFile: "/path/to/cert.pem",
KeyFile: "/path/to/key.pem",
},
}
package main
import (
"github.com/astercloud/aster/server"
"github.com/astercloud/aster/server/auth"
)
func main() {
// 1. 创建认证管理器
authManager := auth.NewManager(auth.AuthMethodAPIKey)
// 2. 注册 API Key 认证
apiKeyStore := auth.NewMemoryAPIKeyStore()
apiKeyAuth := auth.NewAPIKeyAuthenticator(apiKeyStore)
authManager.Register(apiKeyAuth)
// 3. 注册 JWT 认证
jwtAuth := auth.NewJWTAuthenticator(auth.JWTConfig{
SecretKey: os.Getenv("JWT_SECRET"),
Issuer: "aster",
ExpiryDuration: 24 * time.Hour,
})
authManager.Register(jwtAuth)
// 4. 创建 RBAC
rbac := auth.NewRBAC()
// 5. 配置服务器
config := &server.Config{
Auth: server.AuthConfig{
APIKey: server.APIKeyConfig{Enabled: true},
JWT: server.JWTConfig{Enabled: true},
},
}
srv, _ := server.New(config, deps)
srv.Start()
}
func (h *AuthHandler) Login(c *gin.Context) {
var req struct {
Username string `json:"username"`
Password string `json:"password"`
}
c.ShouldBindJSON(&req)
// 验证用户名密码
user, err := validateCredentials(req.Username, req.Password)
if err != nil {
c.JSON(401, gin.H{"error": "Invalid credentials"})
return
}
// 生成 JWT
token, expiresAt, _ := h.jwtAuth.GenerateToken(user)
c.JSON(200, gin.H{
"token": token,
"expires_at": expiresAt,
"user": user,
})
}
func AuthMiddleware(authManager *auth.Manager, rbac *auth.RBAC) gin.HandlerFunc {
return func(c *gin.Context) {
// 提取 token
token := extractToken(c)
if token == "" {
c.AbortWithStatusJSON(401, gin.H{"error": "Missing token"})
return
}
// 验证 token
user, err := authManager.Validate(c.Request.Context(), auth.AuthMethodJWT, token)
if err != nil {
c.AbortWithStatusJSON(401, gin.H{"error": "Invalid token"})
return
}
// 存储用户信息
c.Set("user", user)
c.Next()
}
}