5759c1862e
M0-M7 已完成:核心网关(身份/RBAC/TOTP/OIDC/SAML/Provider/配额/路由/内容策略/审计/定价)+ 资源市场(MCP/Skills/数字员工)。 含 22 个 PostgreSQL 迁移、管理端/门户端前端源码、OpenAPI 契约、部署 compose。 Co-Authored-By: Claude <noreply@anthropic.com>
76 lines
1.8 KiB
Go
76 lines
1.8 KiB
Go
package apikey
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
ErrInvalid = errors.New("invalid API key")
|
|
ErrStore = errors.New("API key store unavailable")
|
|
)
|
|
|
|
type Record struct {
|
|
ID string
|
|
TenantID *string
|
|
Name string
|
|
KeyPrefix string
|
|
KeyHash []byte
|
|
Scopes []string
|
|
Enabled bool
|
|
RequestsPerMinute int
|
|
MonthlyRequestQuota int64
|
|
MonthlyTokenQuota int64
|
|
ExpiresAt *time.Time
|
|
LastUsedAt *time.Time
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type Principal struct {
|
|
APIKeyID string `json:"api_key_id"`
|
|
TenantID *string `json:"tenant_id,omitempty"`
|
|
Scopes []string `json:"scopes"`
|
|
RequestsPerMinute int `json:"requests_per_minute"`
|
|
MonthlyRequestQuota int64 `json:"monthly_request_quota"`
|
|
MonthlyTokenQuota int64 `json:"monthly_token_quota"`
|
|
}
|
|
|
|
func Generate() (secret, prefix string, hash []byte, err error) {
|
|
random := make([]byte, 32)
|
|
if _, err = rand.Read(random); err != nil {
|
|
return "", "", nil, err
|
|
}
|
|
secret = "gw_" + base64.RawURLEncoding.EncodeToString(random)
|
|
prefix = secret[:16]
|
|
digest := sha256.Sum256([]byte(secret))
|
|
return secret, prefix, digest[:], nil
|
|
}
|
|
|
|
func Digest(secret string) ([]byte, string) {
|
|
digest := sha256.Sum256([]byte(strings.TrimSpace(secret)))
|
|
return digest[:], hex.EncodeToString(digest[:])
|
|
}
|
|
|
|
func HasScope(scopes []string, required string) bool {
|
|
for _, scope := range scopes {
|
|
if scope == "*" || scope == required {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
type KeyAuthenticator interface {
|
|
Authenticate(context.Context, string) error
|
|
}
|
|
|
|
type PrincipalAuthenticator interface {
|
|
AuthenticatePrincipal(context.Context, string) (Principal, error)
|
|
}
|