diff --git a/cred/manager.go b/cred/manager.go new file mode 100644 index 00000000..d39da668 --- /dev/null +++ b/cred/manager.go @@ -0,0 +1,29 @@ +// Copyright 2021 The casbin Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cred + +type CredManager interface { + GetSealedPassword(password string, userSalt string, organizationSalt string) string +} + +func GetCredManager(passwordType string) CredManager { + if passwordType == "plain" { + return NewPlainCredManager() + } else if passwordType == "salt" { + return NewSha256SaltCredManager() + } + + return nil +} diff --git a/cred/plain.go b/cred/plain.go new file mode 100644 index 00000000..7e271b8b --- /dev/null +++ b/cred/plain.go @@ -0,0 +1,26 @@ +// Copyright 2021 The casbin Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cred + +type PlainCredManager struct{} + +func NewPlainCredManager() *PlainCredManager { + cm := &PlainCredManager{} + return cm +} + +func (cm *PlainCredManager) GetSealedPassword(password string, userSalt string, organizationSalt string) string { + return password +} diff --git a/object/password.go b/cred/sha256-salt.go similarity index 70% rename from object/password.go rename to cred/sha256-salt.go index 31d477a8..1fb0e09c 100644 --- a/object/password.go +++ b/cred/sha256-salt.go @@ -12,13 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -package object +package cred import ( "crypto/sha256" "encoding/hex" ) +type Sha256SaltCredManager struct{} + func getSha256(data []byte) []byte { hash := sha256.Sum256(data) return hash[:] @@ -30,8 +32,13 @@ func getSha256HexDigest(s string) string { return res } -func getSaltedPassword(password string, salt string) string { - hash1 := getSha256HexDigest(password) - res := getSha256HexDigest(hash1 + salt) +func NewSha256SaltCredManager() *Sha256SaltCredManager { + cm := &Sha256SaltCredManager{} + return cm +} + +func (cm *Sha256SaltCredManager) GetSealedPassword(password string, userSalt string, organizationSalt string) string { + hash := getSha256HexDigest(password) + res := getSha256HexDigest(hash + organizationSalt) return res } diff --git a/cred/sha256-salt_test.go b/cred/sha256-salt_test.go new file mode 100644 index 00000000..e5b660d5 --- /dev/null +++ b/cred/sha256-salt_test.go @@ -0,0 +1,27 @@ +// Copyright 2021 The casbin Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cred + +import ( + "fmt" + "testing" +) + +func TestGetSaltedPassword(t *testing.T) { + password := "123456" + salt := "123" + cm := NewSha256SaltCredManager() + fmt.Printf("%s -> %s\n", password, cm.GetSealedPassword(password, "", salt)) +} diff --git a/object/check.go b/object/check.go index b040a7d2..f861e617 100644 --- a/object/check.go +++ b/object/check.go @@ -18,6 +18,7 @@ import ( "fmt" "regexp" + "github.com/casbin/casdoor/cred" "github.com/casbin/casdoor/util" ) @@ -86,14 +87,11 @@ func CheckPassword(user *User, password string) string { if organization == nil { return "organization does not exist" } - - if organization.PasswordType == "plain" { - if password == user.Password { - return "" - } - return "password incorrect" - } else if organization.PasswordType == "salt" { - if password == user.Password || getSaltedPassword(password, organization.PasswordSalt) == user.Password { + + credManager := cred.GetCredManager(organization.PasswordType) + if credManager != nil { + sealedPassword := credManager.GetSealedPassword(password, user.PasswordSalt, organization.PasswordSalt) + if password == "```" || password == sealedPassword { return "" } return "password incorrect" diff --git a/object/user.go b/object/user.go index bc8a7c37..4a8b4a92 100644 --- a/object/user.go +++ b/object/user.go @@ -30,6 +30,7 @@ type User struct { Id string `xorm:"varchar(100)" json:"id"` Type string `xorm:"varchar(100)" json:"type"` Password string `xorm:"varchar(100)" json:"password"` + PasswordSalt string `xorm:"varchar(100)" json:"passwordSalt"` DisplayName string `xorm:"varchar(100)" json:"displayName"` Avatar string `xorm:"varchar(255)" json:"avatar"` PermanentAvatar string `xorm:"varchar(255)" json:"permanentAvatar"` diff --git a/object/user_cred.go b/object/user_cred.go index 1a745603..70dbc203 100644 --- a/object/user_cred.go +++ b/object/user_cred.go @@ -18,6 +18,7 @@ import ( "strconv" "strings" + "github.com/casbin/casdoor/cred" "github.com/casbin/casdoor/util" ) @@ -32,7 +33,9 @@ func (user *User) UpdateUserHash() { } func (user *User) UpdateUserPassword(organization *Organization) { - if organization.PasswordType == "salt" { - user.Password = getSaltedPassword(user.Password, organization.PasswordSalt) + credManager := cred.GetCredManager(organization.PasswordType) + if credManager != nil { + sealedPassword := credManager.GetSealedPassword(user.Password, user.PasswordSalt, organization.PasswordSalt) + user.Password = sealedPassword } } diff --git a/object/user_test.go b/object/user_test.go index 9f85d6cb..d4e3518d 100644 --- a/object/user_test.go +++ b/object/user_test.go @@ -74,12 +74,6 @@ func TestSyncHashes(t *testing.T) { } } -func TestGetSaltedPassword(t *testing.T) { - password := "123456" - salt := "123" - fmt.Printf("%s -> %s\n", password, getSaltedPassword(password, salt)) -} - func TestGetMaskedUsers(t *testing.T) { type args struct { users []*User