我有一个应用程序询问用户的用户名和密码。目前,对于 Unix 系统(大多数),我从中读取密码哈希,/etc/shadow但对于 macOS 来说更麻烦(他们使用自己的标准),所以我想知道是否有一种简单的方法来验证用户名和密码。
我正在考虑login以一种奇怪的方式使用该程序,但这不是最好的解决方案。
我正在使用 golang,但 C 或 C++ 中的解决方案也会很有用。
编辑
@TheNextman 的答案正是我所要求的,但与其他人交谈时,他们建议我使用 PAM,因为它适用于多个操作系统。我花了一些精力来理解它,因为我正在寻找一个简单的 API 来验证用户和密码,verify(username string, password string) -> boolean但我知道 PAM 更通用,因此更复杂。
但这是我最终使用的代码,它是在 GO 中使用 C 绑定制作的。
package Authentication
import "C"
import (
"encoding/json"
"fmt"
"github.com/vvanpo/golang-pam"
)
func ValidateUser(username, password string) (bool, error) {
// TODO correct handle of errors
UserPssword := userPassword{
Username : username,
Password : password,
}
b, _ := json.Marshal(UserPssword)
conn := myConHand{
username:C.CString(string(b)),
}
tx, _ := pam.Start("sshd", username, conn)
r := tx.Authenticate(0)
if r == pam.SUCCESS{
return true, nil
} else {
return false, nil
}
}
type userPassword struct {
Username string
Password string
}
type myConHand struct {
username *C.char
}
//C.GoString
func (m myConHand) RespondPAM(msg_style int, msg string) (string, bool) {
str := C.GoString(m.username)
var UserPssword userPassword
_ = json.Unmarshal([]byte(str), &UserPssword)
switch msg_style {
case pam.PROMPT_ECHO_OFF:
fmt.Println("Password!!")
return UserPssword.Password, true
case pam.PROMPT_ECHO_ON:
fmt.Println("Username!!")
return UserPssword.Username, true
case pam.ERROR_MSG:
fmt.Println(msg)
return "", true
case pam.TEXT_INFO:
fmt.Println(msg)
return "", true
default:
return "", true
}
}
它有一些问题,例如我正在使用该/etc/pam.d/sshd服务,因为我知道我将使用的计算机具有相同的服务,但我不知道哪个操作系统具有/etc/pam.d/sshd,另一种选择是创建我自己的服务但是我必须为我发现的每一个不同的标准创建一个 3 Linux PAM、openPAM (macos) 和 Solaris PAM。
但总的来说,我认为这是一个强大的解决方案,因为我正在重用现有的身份验证机制。
大话西游666
相关分类