From 9874b4af3fc01b2b0d2bc5875f11a8ed243051bb Mon Sep 17 00:00:00 2001 From: Zexi Li Date: Wed, 19 Mar 2025 10:10:55 +0800 Subject: [PATCH] optimized(keystone): local sql auth by password (#22305) --- pkg/keystone/models/passwords.go | 25 ++++++++++++++++++++++--- pkg/keystone/models/users.go | 8 ++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/pkg/keystone/models/passwords.go b/pkg/keystone/models/passwords.go index e594d88a5f..6b56c7e755 100644 --- a/pkg/keystone/models/passwords.go +++ b/pkg/keystone/models/passwords.go @@ -26,6 +26,7 @@ import ( "yunion.io/x/log" "yunion.io/x/pkg/errors" "yunion.io/x/pkg/utils" + "yunion.io/x/sqlchemy" notifyapi "yunion.io/x/onecloud/pkg/apis/notify" "yunion.io/x/onecloud/pkg/cloudcommon/db" @@ -107,12 +108,30 @@ func (manager *SPasswordManager) FetchLastPassword(localUserId int) (*SPassword, return &passes[0], nil } -func (manager *SPasswordManager) fetchByLocaluserId(localUserId int) ([]SPassword, error) { - passes := make([]SPassword, 0) +func (manager *SPasswordManager) getFetchByLocaluserIdQuery(localUserId int) *sqlchemy.SQuery { passwords := manager.Query().SubQuery() - q := passwords.Query().Equals("local_user_id", localUserId) q = q.Desc(passwords.Field("created_at_int")) + return q +} + +func (manager *SPasswordManager) FetchByLocaluserIdNewestPassword(localUserId int) (*SPassword, error) { + obj, err := db.NewModelObject(manager) + if err != nil { + return nil, errors.Wrap(err, "new password object") + } + + q := manager.getFetchByLocaluserIdQuery(localUserId).Limit(1) + if err := q.First(obj); err != nil { + return nil, errors.Wrap(err, "get newest password object") + } + return obj.(*SPassword), nil +} + +func (manager *SPasswordManager) fetchByLocaluserId(localUserId int) ([]SPassword, error) { + passes := make([]SPassword, 0) + + q := manager.getFetchByLocaluserIdQuery(localUserId) err := db.FetchModelObjects(manager, q, &passes) if err != nil && err != sql.ErrNoRows { return nil, errors.Wrap(err, "db.FetchModelObjects") diff --git a/pkg/keystone/models/users.go b/pkg/keystone/models/users.go index 3584aa0926..974c79267a 100644 --- a/pkg/keystone/models/users.go +++ b/pkg/keystone/models/users.go @@ -348,11 +348,11 @@ func VerifyPassword(user *api.SUserExtended, passwd string) error { } func localUserVerifyPassword(user *api.SUserExtended, passwd string) error { - passes, err := PasswordManager.fetchByLocaluserId(user.LocalId) + pass, err := PasswordManager.FetchByLocaluserIdNewestPassword(user.LocalId) if err != nil { return errors.Wrap(err, "fetchPassword") } - if len(passes) == 0 { + if pass == nil { return errors.Error("no valid password") } // password expiration check skip system account @@ -360,14 +360,14 @@ func localUserVerifyPassword(user *api.SUserExtended, passwd string) error { // return errors.Error("password expires") // } // password expires, no error returns but set user need to reset password silently - if passes[0].IsExpired() { + if pass.IsExpired() { localUsr, err := LocalUserManager.fetchLocalUser("", "", user.LocalId) if err != nil { return errors.Wrap(err, "fetchLocalUser") } localUsr.markNeedResetPassword(true, api.PasswordResetHintExpire) } - err = seclib2.BcryptVerifyPassword(passwd, passes[0].PasswordHash) + err = seclib2.BcryptVerifyPassword(passwd, pass.PasswordHash) if err == nil { return nil }