fix: stabilize console scrolling and protect administrator login

This commit is contained in:
2026-09-30 00:09:01 +08:00
parent 9a15406f76
commit f56f233704
32 changed files with 1308 additions and 86 deletions

View File

@@ -25,10 +25,20 @@ const (
// ConsoleAuthStore 管理控制台的人类账号和 HttpOnly 会话。
// 账号绑定一个已有的 Orbit 业务凭据,登录后沿用该凭据的权限范围;
// 因此控制台登录不会改变 SDK 令牌,也不会绕过原有的 API 授权。
type ConsoleAuthStore struct{ db *sql.DB }
type ConsoleAuthStore struct {
db *sql.DB
policy consoleauth.LoginPolicy
}
// NewConsoleAuthStore 创建控制台认证存储。
func NewConsoleAuthStore(db *sql.DB) *ConsoleAuthStore { return &ConsoleAuthStore{db: db} }
func NewConsoleAuthStore(db *sql.DB, policies ...consoleauth.LoginPolicy) *ConsoleAuthStore {
policy := consoleauth.DefaultLoginPolicy()
if len(policies) > 0 {
policy = policies[0]
}
return &ConsoleAuthStore{db: db, policy: policy}
}
func (s *ConsoleAuthStore) LoginPolicy() consoleauth.LoginPolicy { return s.policy }
var _ consoleauth.Store = (*ConsoleAuthStore)(nil)
@@ -108,59 +118,6 @@ func (s *ConsoleAuthStore) CreateConsoleUser(ctx context.Context, in ConsoleUser
return ConsoleUser{ID: string(id), Username: in.Username, DisplayName: name}, nil
}
// Login 校验账号密码并建立一个独立会话。失败时统一返回未认证,避免泄露账号存在性。
func (s *ConsoleAuthStore) Login(ctx context.Context, username, password, userAgent, remoteAddr string) (ConsoleLogin, error) {
if s == nil || s.db == nil || username == "" || password == "" || len(password) > 1024 {
return ConsoleLogin{}, fault.Unauthorized
}
var user ConsoleUser
var userID core.ID
var namespace, credential core.ID
var hash string
var enabled bool
err := s.db.QueryRowContext(ctx, `SELECT u.id,u.username,u.display_name,u.password_hash,u.enabled,u.namespace_id,u.credential_id
FROM orbit_console_users u
JOIN orbit_credentials c ON c.namespace_id=u.namespace_id AND c.id=u.credential_id
JOIN orbit_namespaces n ON n.id=u.namespace_id
JOIN orbit_applications a ON a.id=n.application_id
WHERE u.username=? AND c.revoked_at IS NULL
AND (c.expires_at IS NULL OR c.expires_at>UTC_TIMESTAMP(6))
AND n.enabled=TRUE AND a.enabled=TRUE`, username).
Scan(&userID, &user.Username, &user.DisplayName, &hash, &enabled, &namespace, &credential)
if err != nil || !enabled || bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) != nil {
return ConsoleLogin{}, fault.Unauthorized
}
user.ID = string(userID)
token, secretDigest, err := auth.Issue(namespace, credential)
if err != nil {
return ConsoleLogin{}, err
}
var now time.Time
if err := s.db.QueryRowContext(ctx, "SELECT UTC_TIMESTAMP(6)").Scan(&now); err != nil {
return ConsoleLogin{}, err
}
now = now.UTC()
expires := now.Add(ConsoleSessionLifetime)
sessionID, err := core.NewID()
if err != nil {
return ConsoleLogin{}, err
}
if len(userAgent) > 512 {
userAgent = userAgent[:512]
}
if len(remoteAddr) > 64 {
remoteAddr = remoteAddr[:64]
}
_, err = s.db.ExecContext(ctx, `INSERT INTO orbit_console_sessions
(id,user_id,namespace_id,credential_id,token_digest,expires_at,last_seen_at,user_agent,remote_addr)
VALUES (?,?,?,?,?,?,UTC_TIMESTAMP(6),?,?)`,
sessionID, userID, namespace, credential, secretDigest, expires, userAgent, remoteAddr)
if err != nil {
return ConsoleLogin{}, err
}
return ConsoleLogin{User: user, Token: token, ExpiresAt: expires}, nil
}
// ValidateSession 检查会话是否仍然有效,并更新最近使用时间。
// API 授权还会再次读取该会话对应凭据的权限,不信任浏览器提交的身份字段。
func (s *ConsoleAuthStore) ValidateSession(ctx context.Context, token auth.Token) error {